Vue中为什么要引入render函数?

Vue运行版与完整版Vue:解析与模板解析的区别
本文探讨了Vue项目中,为何使用render函数而非template属性,并揭示了Vue不同版本的选择。重点讲述了运行版Vue如何通过render函数进行模板解析,以及引入完整版Vue的必要性与体积优化。

前言

使用Vue脚手架创建项目的入口文件main.js中,默认代码如下:

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

可以看到,代码中通过import引入了App组件,但是却并没有通过components注册,还使用了一个render函数,而没有利用template属性

//上述代码的等价写法
import Vue from 'vue/dist/vue'//注意此处差异
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
    template: `<App/>`,
    components: { App },
}).$mount('#app')

想要知道上述代码为什么等价,就需要从Vue的不同版本说起

背景

Vue有两大部分组成,一个是核心功能,包括生命周期、事件处理等内容,另一部分是模板解析器,用来对Vue模板进行解析。

Vue.js中包括了这两部分的全部内容(即完整版的vue),但是这样会有一个问题,当项目开发完毕进行打包时,打包后的文件会引入完整版vue的全部代码,但是实际上打包后的输出文件中已经不需要Vue模板解析器部分的代码了(模板已经被解析好了,浏览器可以直接运行),引入完整版Vue只会增大打包后文件的体积。

为了解决这个问题,Vue团队提供了不同版本的Vue,vue.js为完整版的Vue,其他版本都是在vue.js完整版上进行的精简,比如vue.runtime.*为Vue的运行版,不包括Vue模板解析器部分代码。

在这里插入图片描述

既然Vue有不同的版本,那么我们在import引入Vue的时候,到底用的是哪个版本呢?

查看Vue包中的package.json文件可以发现,ES6模块化的入口文件是vue.runtime.esm.js,即Vue默认帮我们引入的是vue的运行版,其中不包括模板解析器部分代码。

在这里插入图片描述

运行版Vue想要进行模板解析,就需要使用render函数。Vue官方案例中,入口文件main.js的内容如下,其中使用了render函数进行模板解析。

import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
  render: h => h(App),
}).$mount('#app')

如果我们使用template属性进行模板解析,会报错You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.

//通过 import Vue from 'vue/dist/vue'引入完整版的vue,则代码不会报错

import Vue from 'vue'//默认引入运行版的vue,使用template编写模板会报错

Vue.config.productionTip = false

new Vue({
    template: `<h1>hello</h1>`,
}).$mount('#app')

注意:上边说的模板解析指的是解析vm配置对象的template属性中定义的模板

组件中的模板(.vue中template标签中的内容),vue使用了vue-template-compiler帮助我们解析,而且可以看到他只在开发依赖中,在生产依赖中是没有的,这也很好解释,因为打包后的文件浏览器已经可以直接运行了,不存在vue模板语法,也就不需要vue-template-compiler了。

"dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11"
},
"devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "babel-eslint": "^10.1.0",
    "eslint": "^6.7.2",
    "eslint-plugin-vue": "^6.2.2",
    "vue-template-compiler": "^2.6.11"
},

原理

在vm的配置对象中使用template属性,可以通过HTML语法,创建vue模板页面,我们编写的Vue模板在底层先会被转换成虚拟Dom,才会渲染到页面中(真实Dom)。

在vm的配置对象中使用 render函数 ,可以直接用js构建虚拟DOM,免去了转译(Vue模板转译成虚拟Dom)的过程。

后记

上边只是我的一点理解,如果有什么问题,希望大家批评指正。

Vue 3 中,JSX 的使用与 Vue 2 有所不同,尤其是在 render 函数的编写方式上。Vue 3 支持通过 `@vue/babel-plugin-jsx` 插件来实现 JSX 语法的支持,并且在编写 render 函数时,开发者可以使用更接近 React 的方式来构建组件的 Virtual DOM 结构。以下是一些关键点和示例,展示了如何在 Vue 3 的 JSX 中使用 render 函数。 ### render 函数的基本结构 在 Vue 3 中,render 函数通常用于自定义组件的渲染逻辑。使用 JSX 时,render 函数的写法与 Vue 2 类似,但需要引入 `h` 函数(即 `createVNode`)作为参数传递给 render 函数。例如: ```javascript import { defineComponent, h } from 'vue' const MyComponent = defineComponent({ render(h) { return <div>Hello, JSX in Vue 3!</div> } }) ``` 在这个例子中,`h` 是 `createVNode` 的别名,用于创建虚拟节点。这种方式使得 render 函数中的 JSX 语法更加直观和简洁。 ### 使用组件和 props 在 JSX 中使用组件时,可以直接通过标签名来引用已定义的组件。例如,如果有一个 `Button` 组件,可以在 render 函数中这样使用: ```javascript import { defineComponent, h } from 'vue' import Button from './Button.vue' const MyComponent = defineComponent({ render(h) { return <Button onClick={this.handleClick}>Click me</Button> }, methods: { handleClick() { console.log('Button clicked') } } }) ``` 在这里,`onClick` 是一个事件监听器,绑定到 `handleClick` 方法上。这种写法类似于 HTML 标签的属性传递方式,但在 Vue 3 中,事件监听器需要使用 `on` 前缀。 ### 动态渲染内容 在 render 函数中,可以动态地渲染内容,例如根据数据状态来决定显示什么内容。以下是一个简单的例子,展示了如何根据组件的状态来渲染不同的内容: ```javascript import { defineComponent, h } from 'vue' const MyComponent = defineComponent({ data() { return { showText: true } }, render(h) { return ( <div> {this.showText ? <p>显示文本</p> : <p>隐藏文本</p>} </div> ) } }) ``` 在这个例子中,`showText` 是一个布尔值,决定了显示哪一段文字。这种条件渲染的方式非常灵活,适用于各种动态内容的场景。 ### 函数式组件 Vue 3 还支持函数式组件,这种组件没有自己的状态,只依赖于传入的 props。函数式组件的 render 函数可以直接返回 JSX 内容。以下是一个简单的函数式组件示例: ```javascript import { defineComponent, h } from 'vue' const FunctionalComponent = defineComponent((props, { slots }) => { return () => ( <div> <h1>Functional Component</h1> {slots.default ? slots.default() : <p>No slot content provided</p>} </div> ) }) ``` 在这个例子中,`FunctionalComponent` 是一个函数式组件,它接收 `props` 和 `slots` 作为参数,并返回一个 render 函数。这个 render 函数返回 JSX 内容,其中包含了默认插槽的内容。 ### 总结 在 Vue 3 中,使用 JSX 编写 render 函数可以显著提高代码的可读性和可维护性。通过引入 `h` 函数,开发者可以轻松地创建虚拟节点,并利用 JSX 的语法特性来简化组件的渲染逻辑。无论是在普通组件还是函数式组件中,JSX 都能提供一种更加直观和简洁的方式来编写 render 函数。 ###
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值