Lefan817116 发表于 2025-6-13 11:36

一文了解什么是nvue

欢迎踏上 nvue 的奇妙冒险!如果你是 uni-app 开发者,听到“nvue”可能有点懵:这是啥?新潮饮料?外星科技?别慌,nvue(Native Vue)是 uni-app 框架中 App 端的“性能怪兽”,专为丝滑体验而生。这篇指南将以幽默风趣的笔调,带你从“nvue 是啥”到“用 nvue 开发 App 真香”,兼顾广度(全面覆盖组件、API、场景)和深度(深入剖析写法、性能优化、避坑技巧)。本文基于截至 2025 年 6 月 13 日的 uni-app 文档和社区实践,输出 Markdown 格式,方便直接复制使用。准备好了吗?让我们一起“拆解”nvue,开启高性能 App 开发之旅!

---

## 第一章:nvue 是个啥?别慌,它是 uni-app 的“原生小助手”

### 1.1 nvue 的“出身”:Weex 的“超级改造版”

nvue,全称 **Native Vue**,听名字就知道它跟 Vue.js 有点“亲戚关系”。它基于 Weex 引擎(一个高性能跨平台框架),经过 uni-app 团队的大刀阔斧改造,变成了 App 端的高性能渲染神器。Weex 原本像个“半成品跑车”,性能强但 API 匮乏,开发得前端、iOS、Android 三方忙得像陀螺。nvue 则像“跑车 2.0”,不仅继承了 Weex 的原生渲染速度,还融入了 uni-app 的丰富 API 和插件生态,让前端开发者能单枪匹马搞定 App 开发,省时省力省头发!

### 1.2 nvue vs vue:双胞胎兄弟的“性格差异”

在 uni-app 中,页面文件有两种后缀:`.vue` 和 `.nvue`,它们就像双胞胎兄弟,长得有点像,但性格迥异:

- **.vue 文件**:用 Webview 渲染,熟悉的 Web 开发体验,CSS 想怎么写就怎么写,支持 H5、小程序、App 多端通用。缺点?Webview 在长列表或复杂动画场景下可能“喘不过气”,像老牛拉车。
- **.nvue 文件**:用原生渲染(Weex 引擎),性能丝滑如刚出炉的奶油蛋糕,专为 App 端高性能场景打造。但 CSS 受限(只支持 Flex 布局),H5 和小程序支持度稍差。

**一句话总结**:vue 是跨端“全能选手”,nvue 是 App 端“性能王者”。如果你只做 H5 或小程序,nvue 可能是个“高冷备胎”;但如果你的 App 需要极致流畅,nvue 就是“真命天子”!

### 1.3 为什么要有 nvue?不就是多此一举吗?

你可能会吐槽:有 vue 这么好用的东西,为啥还要搞个 nvue?别急,听我讲个“性能悲剧”:

想象你开发了个 App,里面有个长列表页面,塞满图片和文字。用户滑动时,vue 页面卡得像PPT 放映,气得想砸手机。这时候,nvue 像超级英雄,带着原生渲染的“光环”登场,滑动流畅得像在丝绸上滑冰!

nvue 专治以下场景的性能痛点:
- **长列表或瀑布流**:nvue 的 `<list>`、`<recycle-list>`、`<waterfall>` 组件性能碾压 vue 的 `<scroll-view>`。
- **复杂下拉刷新**:nvue 的 `<refresh>` 组件支持自定义动画,效果丝滑。
- **层级问题**:vue 中 `map`、`video` 等原生组件层级最高,盖不住?nvue 同层渲染轻松搞定!
- **抖音式视频切换**:nvue 的 `<video>` 嵌在 `<swiper>` 中,滑动切换顺滑无压力。

总之,nvue 是 uni-app 给 App 端准备的“秘密武器”,性能拉满!

---

## 第二章:nvue 怎么用?从零到一上手开发

好了,了解了 nvue 的“出身”和“使命”,我们来动手实践!别怕,nvue 开发并不复杂,跟着我一步步来,你也能成为 nvue 大师!

### 2.1 创建第一个 nvue 页面:Hello World!

在 uni-app 项目中,创建 nvue 页面就像点外卖一样简单。假设你用 HBuilderX(uni-app 的御用编辑器):

1. **新建页面**:
   - 在 `pages` 目录右键,选“新建页面”。
   - 选择“nvue 页面”,输入名称(如 `hello.nvue`),HBuilderX 自动在 `pages.json` 注册。

2. **页面结构**:
   nvue 页面结构跟 vue 类似,包含 `<template>`、`<script>`、`<style>`。来看个 Hello World 示例:

```html
<template>
<div class="container">
    <text class="text">Hello nvue!</text>
</div>
</template>

<script>
export default {
data() {
    return {
      message: 'Hello nvue!'
    }
}
}
</script>

<style>
.container {
flex: 1;
justify-content: center;
align-items: center;
}
.text {
font-size: 30px;
color: #333;
}
</style>
```

**注意事项**:
- nvue 的 `<div>` 不能直接写文字,必须用 `<text>` 包裹,否则变量绑定(如 `{{ message }}`)失效。
- CSS 仅支持 Flex 布局,默认 `flex-direction: column`(垂直排列)。
- 只支持 `class` 选择器,忘了 `id`、标签选择器,否则报错:`Selector 'xxx' is not supported`。
- 不支持 `background-image`,想加背景?用 `<image>` 模拟。

3. **运行测试**:
   - 连接真机(nvue 不支持模拟器),点击 HBuilderX 的“运行”按钮。
   - 运行成功后,屏幕居中显示“Hello nvue!”,是不是有种“原生渲染我也会了”的成就感?

### 2.2 配置 nvue 编译模式:Weex 还是 uni-app?

nvue 有两种编译模式,选对模式让开发更顺畅:

- **Weex 模式**:老派玩法,只支持 Weex 组件和规范,仅编译到 App 端,跨端能力弱。不推荐新手。
- **uni-app 模式**:默认模式,支持 uni-app 组件和 API,可编译到 H5 和小程序,跨端更友好。强烈推荐!

配置方式:在 `manifest.json` 的 `app-plus` 节点设置:

```json
{
"app-plus": {
    "nvueCompiler": "uni-app"
}
}
```

uni-app 模式下,nvue 页面自动套 `<scroller>`,内容超高时可滚动,省心省力!

### 2.3 nvue 的 CSS 限制:Flex 虽好,但得悠着点!

nvue 的 CSS 是开发者最容易“翻车”的地方,盘点一下“怪癖”:

- **只支持 Flex 布局**:忘了 `float`、`grid`,默认 `flex-direction: column`。
- **只支持 class 选择器**:`id`、标签选择器会报错。
- **不支持简写属性**:如 `border: 1px solid black` 需拆成:
```css
border-width: 1px;
border-style: solid;
border-color: black;
```
- **不支持背景图**:用 `<image>` 加层级模拟。
- **文字必须用 `<text>`**:`<div>` 直接写文字会失效。
- **不支持 SCSS/LESS**:只能用原生 CSS。
- **单位**:支持 `px` 和 `wx`(750wx = 屏幕宽度)。

**示例**:
```html
<template>
<div class="container">
    <text class="text">Flex 布局真香!</text>
</div>
</template>

<style>
.container {
flex: 1;
flex-direction: row; /* 横向排列 */
justify-content: space-between;
align-items: center;
}
.text {
font-size: 24px;
color: #007AFF;
}
</style>
```

不会 Flex?快去 (https://css-tricks.com/snippets/css/a-guide-to-flexbox/) 补课!

### 2.4 nvue 与 vue 的页面通讯:兄弟俩的“聊天方式”

nvue 和 vue 页面可以混搭,比如首页用 nvue,其他页面用 vue。跳转用 uni-app 的路由 API:

```javascript
uni.navigateTo({
url: '/pages/other/other?data=hello'
});
```

传参建议用 `uni.setStorage` 和 `uni.getStorage`:

```javascript
// nvue 页面发送数据
uni.setStorage({
key: 'data',
data: 'Hello from nvue!',
success: () => {
    uni.navigateTo({ url: '/pages/vuePage/vuePage' });
}
});

// vue 页面接收数据
export default {
created() {
    uni.getStorage({
      key: 'data',
      success: (res) => {
      console.log(res.data); // Hello from nvue!
      }
    });
}
};
```

更优雅的方式是用 `uni.$on` 和 `uni.$emit`:

```javascript
// nvue 发送事件
uni.$emit('updateData', { message: 'Hello from nvue!' });

// vue 接收事件
uni.$on('updateData', (data) => {
console.log(data.message);
});
```

---

## 第三章:nvue 与 vue 的组件对比:从基础到高级

nvue 和 vue 的组件差异是开发者必须掌握的重点。以下是目前已知的 nvue 组件与 vue 组件的详细对比,包含代码示例和“避坑指南”。

### 3.1 基础组件对比

#### 3.1.1 容器:`<div>` vs `<div>`
- **vue**:支持直接写文字,CSS 支持 `float`、`grid`、`flex` 等,自由度高。
- **nvue**:`<div>` 仅作容器,文字需用 `<text>`,仅支持 Flex 布局。

**vue 示例**:
```html
<template>
<div class="container">
    Hello Vue!
    <div class="box">Box</div>
</div>
</template>

<style>
.container {
display: grid;
place-items: center;
background-image: url('bg.jpg');
}
.box {
width: 100px;
height: 100px;
background-color: #f0f0f0;
}
</style>
```

**nvue 示例**:
```html
<template>
<div class="container">
    <text class="text">Hello nvue!</text>
    <div class="box">Box</div>
</div>
</template>

<style>
.container {
flex: 1;
justify-content: center;
align-items: center;
}
.text {
font-size: 30px;
color: #333;
}
.box {
width: 100px;
height: 100px;
background-color: #f0f0f0;
}
</style>
```

#### 3.1.2 文本:`<span>`/文字 vs `<text>`
- **vue**:支持 `<span>` 或直接写文字,CSS 支持 `text-shadow`、`text-decoration` 等。
- **nvue**:必须用 `<text>`,不支持 `text-shadow` 等复杂样式。

**vue 示例**:
```html
<template>
<span class="title">Hello Vue!</span>
</template>

<style>
.title {
font-size: 24px;
font-weight: bold;
text-shadow: 2px 2px 2px rgba(0,0,0,0.3);
}
</style>
```

**nvue 示例**:
```html
<template>
<text class="title">Hello nvue!</text>
</template>

<style>
.title {
font-size: 24px;
font-weight: bold;
color: #333;
}
</style>
```

#### 3.1.3 图片:`<img>` vs `<image>`
- **vue**:用 `<img>`,支持 `alt` 和 CSS 样式。
- **nvue**:用 `<image>`,需设置 `width` 和 `height`,不支持 `alt`。

**vue 示例**:
```html
<template>
<img class="image" src="https://example.com/image.jpg" alt="Vue Image" />
</template>

<style>
.image {
width: 200px;
height: 200px;
border-radius: 10px;
}
</style>
```

**nvue 示例**:
```html
<template>
<image class="image" src="https://example.com/image.jpg" />
</template>

<style>
.image {
width: 200px;
height: 200px;
border-radius: 10px;
}
</style>
```

### 3.2 高级组件对比

#### 3.2.1 滚动:`<scroll-view>` vs `<scroller>`/`<list>`
- **vue**:`<scroll-view>` 支持横/纵向滚动,长列表性能一般。
- **nvue**:`<scroller>`(单页滚动)或 `<list>`(长列表优化),性能丝滑。

**vue 示例**:
```html
<template>
<scroll-view scroll-y class="scroll">
    <view v-for="item in list" :key="item.id">{{ item.name }}</view>
</scroll-view>
</template>

<style>
.scroll {
height: 500px;
}
</style>
```

**nvue 示例(list)**:
```html
<template>
<list class="list">
    <cell v-for="item in list" :key="item.id">
      <text>{{ item.name }}</text>
    </cell>
</list>
</template>

<style>
.list {
flex: 1;
}
</style>
```

#### 3.2.2 下拉刷新:`<scroll-view refresh>` vs `<refresh>`
- **vue**:用 `refresher-enabled` 实现,样式固定。
- **nvue**:用 `<refresh>`,支持自定义动画。

**vue 示例**:
```html
<template>
<scroll-view scroll-y refresher-enabled @refresherrefresh="onRefresh">
    <view v-for="item in list" :key="item.id">{{ item.name }}</view>
</scroll-view>
</template>

<script>
export default {
methods: {
    onRefresh() {
      setTimeout(() => {
      uni.stopPullDownRefresh();
      }, 1000);
    }
}
};
</script>
```

**nvue 示例**:
```html
<template>
<scroller>
    <refresh @refresh="onRefresh">
      <text>加载中...</text>
    </refresh>
    <div v-for="item in list" :key="item.id">
      <text>{{ item.name }}</text>
    </div>
</scroller>
</template>

<script>
export default {
methods: {
    onRefresh() {
      setTimeout(() => {
      this.$refs.refresh.stopPullDownRefresh();
      }, 1000);
    }
}
};
</script>
```

#### 3.2.3 视频:`<video>` vs `<video>`
- **vue**:原生组件,层级最高,覆盖困难。
- **nvue**:同层渲染,可用 `<cover-view>` 覆盖。

**vue 示例**:
```html
<template>
<video src="video.mp4" controls class="video"></video>
</template>
```

**nvue 示例**:
```html
<template>
<video src="video.mp4" autoplay class="video">
    <cover-view class="cover">分享</cover-view>
</video>
</template>

<style>
.cover {
position: absolute;
top: 10px;
right: 10px;
background-color: rgba(0,0,0,0.5);
color: white;
}
</style>
```

### 3.3 nvue 专属组件

- **`<recycle-list>`**:超高性能长列表,回收不可见 DOM。
```html
<template>
    <recycle-list for="(item, index) in list">
      <cell-slot>
      <text>{{ item.name }}</text>
      </cell-slot>
    </recycle-list>
</template>
```

- **`<waterfall>`**:瀑布流,适合图片布局。
```html
<template>
    <waterfall>
      <cell v-for="item in list" :key="item.id">
      <image :src="item.url" />
      </cell>
    </waterfall>
</template>
```

- **`<richtext>`**:富文本,支持复杂排版。
```html
<template>
    <richtext :nodes="[{ name: 'div', children: [{ type: 'text', text: 'Hello!' }] }]" />
</template>
```

---

## 第四章:nvue 的 API 对比与专属能力

nvue 和 vue 的 API 大部分通用,但 nvue 有一些专属模块和限制。

### 4.1 通用 API 示例

- **导航:`uni.navigateTo`**(vue/nvue 通用):
```javascript
uni.navigateTo({ url: '/pages/other/other' });
```

- **动画:`uni.createAnimation`**(nvue 需用 `animation` 属性):
```html
<div animation="{{animationData}}" class="box"></div>
<script>
export default {
    mounted() {
      const animation = uni.createAnimation({ duration: 1000 });
      animation.translateX(100).step();
      this.animationData = animation.export();
    }
};
</script>
```

### 4.2 nvue 专属 API

- **dom 模块**:操作 DOM 结构。
```javascript
const dom = weex.requireModule('dom');
dom.scrollToElement(this.$refs.myElement, { offset: 0 });
```

- **animation 模块**:底层动画控制。
```javascript
const animation = weex.requireModule('animation');
animation.transition(this.$refs.myElement, {
    styles: { transform: 'translateX(100px)' },
    duration: 1000
});
```

---

## 第五章:nvue 的性能优化与避坑指南

nvue 性能强劲,但也有“坑”:

1. **渲染慢**:控制 `v-for` 数据量,用 `key` 优化,批量更新用防抖。
2. **白屏问题**:首页设 `"renderer": "native"`,简化 `mounted` 逻辑。
3. **层级问题**:nvue 同层渲染解决 vue 原生组件层级过高问题。
4. **横竖屏切换**:不支持媒体查询,用 JS 监听方向调整样式。

---

## 第六章:实战案例:打造抖音式视频滑动页面

用 nvue 实现一个视频滑动页面,对比 vue 感受性能差异!

**nvue 示例**:
```html
<template>
<swiper class="swiper" @change="onSwiperChange">
    <swiper-item v-for="item in videos" :key="item.id">
      <video :src="item.url" autoplay class="video">
      <cover-view class="cover">分享</cover-view>
      </video>
    </swiper-item>
</swiper>
</template>

<style>
.swiper {
flex: 1;
height: 100vh;
}
.video {
width: 100%;
height: 100%;
}
.cover {
position: absolute;
top: 20px;
right: 20px;
padding: 10px;
background-color: rgba(0,0,0,0.5);
color: white;
}
</style>

<script>
export default {
data() {
    return {
      videos: [
      { id: 1, url: 'video1.mp4' },
      { id: 2, url: 'video2.mp4' }
      ]
    };
},
methods: {
    onSwiperChange(e) {
      console.log('Current index:', e.detail.current);
    }
}
};
</script>
```

**vue 示例**:
```html
<template>
<swiper class="swiper" @change="onSwiperChange">
    <swiper-item v-for="item in videos" :key="item.id">
      <video :src="item.url" controls class="video"></video>
    </swiper-item>
</swiper>
</template>

<style>
.swiper {
height: 100vh;
}
.video {
width: 100%;
height: 100%;
}
</style>
```

**性能对比**:nvue 的 `<swiper>` + `<video>` 滑动更流畅,`<cover-view>` 轻松覆盖按钮,vue 则可能卡顿且层级难控制。

---

## 第七章:nvue 的未来:uni-app x 与新篇章

uni-app 推出了 **uni-app x**,逻辑层和渲染层全原生,性能比 nvue 更强。但 nvue 仍是当前 App 端高性能首选,官方也在优化 CSS 和组件支持,未来可期!

---

## 结语:nvue,性能与限制的“麻辣香锅”

nvue 就像一道“麻辣香锅”,性能火辣但限制不少。只要掌握 Flex 布局、`<text>` 组件、性能优化技巧,你就能用 nvue 开发出丝滑无比的 App!从长列表到视频滑动,从下拉刷新到复杂动画,nvue 都能让你“哇”一声!

快去 HBuilderX 创建一个 nvue 页面,感受原生渲染的快感吧!想深入了解可参考 [官方文档](https://uniapp.dcloud.net.cn/tutorial/nvue-outline.html) !

1e3e 发表于 2025-6-13 11:44

hbuilderx下载了,认真学习一下自己实践一下

fuvenusck 发表于 2025-6-13 13:45

感谢分享,认真学习一下nvue
页: [1]
查看完整版本: 一文了解什么是nvue