Skip to content
alex's blog
Go back

UniApp nvue 与 vue 的区别详解

编辑页面

在 UniApp 开发中,nvue 和 vue 是两种不同的页面类型。理解它们的区别对于选择合适的开发方式至关重要。本文将详细解析 nvue 和 vue 的区别、使用场景和最佳实践。

什么是 nvue?

nvue(native vue)是 UniApp 提供的原生渲染页面类型,使用 weex 引擎渲染,可以调用原生组件,性能接近原生应用。

什么是 vue?

vue 是 UniApp 的默认页面类型,使用 webview 渲染,兼容性更好,开发体验更接近 H5。

核心区别

1. 渲染引擎

vue:

nvue:

2. 性能表现

vue:

nvue:

3. 组件支持

vue 支持的组件:

nvue 支持的组件:

4. 样式支持

vue 样式:

<style>
.container {
  display: flex;
  background: linear-gradient(to right, #ff0000, #0000ff);
  box-shadow: 0 2px 4px rgba(0,0,0,0.1);
  border-radius: 10px;
}
</style>

nvue 样式:

<style>
.container {
  flex-direction: row; /* 必须使用 flex 布局 */
  background-color: #ff0000; /* 不支持渐变 */
  /* 不支持 box-shadow */
  border-radius: 10px; /* 部分支持 */
}
</style>

5. CSS 特性支持

特性vuenvue
Flex 布局✅ 完整支持✅ 必须使用
Grid 布局✅ 支持❌ 不支持
渐变背景✅ 支持❌ 不支持
阴影效果✅ 支持❌ 不支持
动画✅ CSS 动画✅ 仅支持 transition
伪类选择器✅ 支持❌ 不支持
媒体查询✅ 支持❌ 不支持

详细对比

1. 布局方式

vue:

<template>
  <view class="container">
    <view class="box">内容</view>
  </view>
</template>

<style>
.container {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}

.box {
  width: 200px;
  height: 200px;
  background-color: #007aff;
}
</style>

nvue:

<template>
  <div class="container">
    <div class="box">内容</div>
  </div>
</template>

<style>
.container {
  flex-direction: column; /* 必须使用 flex */
  align-items: center;
  justify-content: center;
}

.box {
  width: 200px;
  height: 200px;
  background-color: #007aff;
}
</style>

注意: nvue 必须使用 flex 布局,不支持其他布局方式。

2. 单位使用

vue:

<style>
.container {
  width: 750rpx; /* 推荐使用 rpx */
  padding: 20px; /* 也可以使用 px */
  font-size: 28rpx;
}
</style>

nvue:

<style>
.container {
  width: 750px; /* 使用 px,不支持 rpx */
  padding: 20px;
  font-size: 28px;
}
</style>

注意: nvue 不支持 rpx,需要使用 px,需要手动计算适配。

3. 事件处理

vue:

<template>
  <view @click="handleClick" @touchstart="handleTouch">
    点击我
  </view>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log('点击事件')
    },
    handleTouch() {
      console.log('触摸事件')
    }
  }
}
</script>

nvue:

<template>
  <div @click="handleClick">
    点击我
  </div>
</template>

<script>
export default {
  methods: {
    handleClick() {
      console.log('点击事件')
    }
  }
}
</script>

注意: nvue 支持的事件较少,主要支持 click、longpress 等基础事件。

4. 生命周期

vue 和 nvue 生命周期相同:

export default {
  onLoad() {
    console.log('页面加载')
  },
  onShow() {
    console.log('页面显示')
  },
  onReady() {
    console.log('页面渲染完成')
  },
  onHide() {
    console.log('页面隐藏')
  },
  onUnload() {
    console.log('页面卸载')
  }
}

5. API 支持

vue:

nvue:

使用场景

适合使用 vue 的场景

  1. 需要快速开发

    • 开发效率高
    • 组件和样式支持丰富
  2. 需要跨平台兼容

    • H5、小程序、App 统一代码
    • 样式和功能一致
  3. 需要复杂样式

    • 渐变、阴影等效果
    • 复杂的 CSS 布局
  4. 需要丰富的组件

    • 使用第三方组件库
    • 自定义复杂组件

适合使用 nvue 的场景

  1. 性能要求高

    • 长列表滚动
    • 复杂动画
    • 频繁更新
  2. 需要原生体验

    • 接近原生应用的流畅度
    • 启动速度快
  3. 简单页面

    • 布局简单
    • 样式需求不高
  4. 特定功能需求

    • 需要调用原生能力
    • 需要高性能渲染

混合使用

UniApp 支持 vue 和 nvue 页面混合使用:

// pages.json
{
  "pages": [
    {
      "path": "pages/index/index",
      "style": {
        "navigationBarTitleText": "首页"
      }
    },
    {
      "path": "pages/list/list",
      "style": {
        "navigationBarTitleText": "列表",
        "renderer": "native" // 使用 nvue
      }
    }
  ]
}

页面跳转

// vue 页面跳转到 nvue 页面
uni.navigateTo({
  url: '/pages/list/list'
})

// nvue 页面跳转到 vue 页面
uni.navigateTo({
  url: '/pages/index/index'
})

性能优化建议

vue 页面优化

<template>
  <!-- 使用 v-show 替代频繁切换的 v-if -->
  <view v-show="show">内容</view>
  
  <!-- 长列表使用虚拟列表 -->
  <scroll-view scroll-y>
    <view v-for="item in list" :key="item.id">
      {{ item.name }}
    </view>
  </scroll-view>
</template>

<script>
export default {
  data() {
    return {
      show: true,
      list: []
    }
  },
  onLoad() {
    // 延迟加载非关键数据
    setTimeout(() => {
      this.loadData()
    }, 100)
  }
}
</script>

nvue 页面优化

<template>
  <list>
    <cell v-for="item in list" :key="item.id">
      <div class="item">
        <text>{{ item.name }}</text>
      </div>
    </cell>
  </list>
</template>

<script>
export default {
  data() {
    return {
      list: []
    }
  },
  onLoad() {
    this.loadData()
  },
  methods: {
    loadData() {
      // 使用原生 list 组件提升性能
      this.list = this.fetchList()
    }
  }
}
</script>

常见问题

1. 如何选择使用 vue 还是 nvue?

建议:

2. nvue 页面样式不生效?

原因:

解决:

<style>
/* ❌ 错误 */
.container {
  display: block;
  background: linear-gradient(...);
}

/* ✅ 正确 */
.container {
  flex-direction: column;
  background-color: #007aff;
}
</style>

3. nvue 页面跳转慢?

原因:

解决:

4. 如何判断当前是 nvue 还是 vue?

// #ifdef APP-PLUS-NVUE
console.log('当前是 nvue 页面')
// #endif

// #ifndef APP-PLUS-NVUE
console.log('当前是 vue 页面')
// #endif

最佳实践

1. 项目结构

pages/
├── index/
│   └── index.vue        # vue 页面
├── list/
│   └── list.nvue        # nvue 页面
└── detail/
    └── detail.vue       # vue 页面

2. 条件编译

<template>
  <view class="container">
    <!-- #ifdef APP-PLUS-NVUE -->
    <text class="nvue-text">nvue 页面</text>
    <!-- #endif -->
    
    <!-- #ifndef APP-PLUS-NVUE -->
    <view class="vue-view">vue 页面</view>
    <!-- #endif -->
  </view>
</template>

<style>
/* #ifdef APP-PLUS-NVUE */
.container {
  flex-direction: column;
}
/* #endif */

/* #ifndef APP-PLUS-NVUE */
.container {
  display: flex;
  flex-direction: column;
}
/* #endif */
</style>

3. 样式适配

// utils/style.js
export function getStyle() {
  // #ifdef APP-PLUS-NVUE
  return {
    width: '750px', // nvue 使用 px
    fontSize: '28px'
  }
  // #endif
  
  // #ifndef APP-PLUS-NVUE
  return {
    width: '750rpx', // vue 使用 rpx
    fontSize: '28rpx'
  }
  // #endif
}

总结

vue 的优势

vue 的劣势

nvue 的优势

nvue 的劣势

选择建议

  1. 默认使用 vue:满足大部分开发需求
  2. 性能瓶颈使用 nvue:长列表、复杂动画等
  3. 混合使用:根据页面特点选择
  4. 优先考虑开发效率:除非性能是瓶颈

记住:先使用 vue 开发,遇到性能问题再考虑 nvue


nvue 和 vue 各有优劣,理解它们的区别能帮助你做出更好的技术选择,构建更优秀的应用。


编辑页面
Share this post on:

Next Post
UniApp 性能优化实战指南