vue中的render函数、h()函数、函数式组件详解
作者:奥特曼
一、什么是render
官网:用于编程式地创建组件虚拟 DOM 树的函数。
在我们使用webpack脚手架创建项目时,都能在main.js中看到一个render函数
import Vue from 'vue' import App from './App.vue' new Vue({ render: h => h(App) }).$mount('#app')
对于render函数 es6中写成了箭头函数
es5写法:
render: function (createElement) { return createElement(App); }
实际上createElement只是形参用h代表了,h()
是 hyperscript 的简称——意思是“能生成 HTML (超文本标记语言) 的 JavaScript”。这个名字来源于许多虚拟 DOM 实现默认形成的约定。一个更准确的名称应该是 createVnode()
,但当你需要多次使用渲染函数时,一个简短的名字会更省力。
二、vue中的render
字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement
方法作为第一个参数用来创建 VNode
。
如果组件是一个函数组件,渲染函数还会接收一个额外的 context
参数,为没有实例的函数组件提供上下文信息。
Vue 选项中的 render
函数若存在,则 Vue 构造函数不会从 template
选项或通过 el
选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。
h()函数用法还是比较多的
// 除了类型必填以外,其他的参数都是可选的 h('div') h('div', { id: 'foo' }) // attribute 和 property 都能在 prop 中书写 // Vue 会自动将它们分配到正确的位置 h('div', { class: 'bar', innerHTML: 'hello' }) // props modifiers such as .prop and .attr can be added // with '.' and `^' prefixes respectively h('div', { '.name': 'some-name', '^width': '100' }) // 类与样式可以像在模板中一样 // 用数组或对象的形式书写 h('div', { class: [foo, { bar }], style: { color: 'red' } }) // 事件监听器应以 onXxx 的形式书写 h('div', { onClick: () => {} }) // children 可以是一个字符串 h('div', { id: 'foo' }, 'hello') // 没有 props 时可以省略不写 h('div', 'hello') h('div', [h('span', 'hello')]) // children 数组可以同时包含 vnodes 与字符串 h('div', ['hello', h('span', 'hello')])
得到的 vnode 为如下形式:
const vnode = h('div', { id: 'foo' }, []) vnode.type // 'div' vnode.props // { id: 'foo' } vnode.children // [] vnode.key // null
当然我们常见的template的形式(Vue 的模板)实际上被编译成了渲染函数。
export default { render (h) { const p = h('p', 'hi') return h('div', { class: 'red' }, [p, p]) } }
三、函数式组件
函数式组件是一种定义自身没有任何状态的组件的方式。它们很像纯函数:接收 props,返回 vnodes。函数式组件在渲染过程中不会创建组件实例 (也就是说,没有 this
),也不会触发常规的组件生命周期钩子。
官网函数式组件格式:
当一个组件没有管理任何状态,也没有监听任何传递给它的状态,也没有生命周期方法。实际上,它只是一个接受一些 prop 的函数。在这样的场景下,我们可以将组件标记为 functional
,这意味它无状态 (没有响应式数据),也没有实例 (没有 this
上下文)。一个函数式组件就像这样:
export default Vue.component('render-component', { // 该组件抽成js文件, functional: true, // 提供第二个参数作为上下文 render: function (createElement, context) { return createElement('h1', '我是函数式子组件') } })
组件需要的一切都是通过 context
参数传递,它是一个包括如下字段的对象:
- props:提供所有 prop 的对象
- children:VNode 子节点的数组
- slots:一个函数,返回了包含所有插槽的对象
- scopedSlots:(2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
- data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
- parent:对父组件的引用
- listeners:(2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是 data.on 的一个别名。
- injections:(2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的 property。
函数式组件可以像普通组件一样被注册和使用。如果你将一个函数作为第一个参数传入 h
,它将会被当作一个函数式组件来对待。
补充 h函数使用场景
button.vue
<script> export default { props: { type: { type: String, default: 'normal' }, text: { type: String, default: 'normal' }, size: { type: String, default: 'medium' } }, computed: { tag () { switch (this.type) { case 'success': return 1 case 'danger': return 2 case 'warning': return 3 default: return 1 } } }, render (h) { return h('div', { class: { btn: true, buttom: 'name', 'btn-success': this.type === 'success', 'btn-danger': this.type === 'danger', 'btn-warning': this.type === 'warning', 'btn-mini': this.size === 'mini', 'btn-small': this.size === 'small', 'btn-medium': this.size === 'medium' }, domProps: { innerText: this.text }, on: { click: this.handleClick } }) }, methods: { handleClick () { console.log('button') } } } </script> <style lang="less" scoped> .buttom { padding: 10px 0; margin: 5px; display: flex; align-items: center; justify-content: center; border-radius: 10px; } .buttom:hover { background: #c9c9c9; } .btn-success { background: #48ff8b; color: #fff; } .btn-danger { background: #ff4848; color: #fff; } .btn-warning { background: #ffbf48; color: #fff; } .btn-small { width: 120px; height: 20px; } .btn-medium { width: 120px; height: 30px; } .btn-mini { width: 120px; height: 10px; } </style>
使用
<Button type="danger" text="名字" size="mini"></Button> <Button type="warning" text="名字" size="small"></Button> <Button type="success" text="名字" size="mini"></Button> <Button type="danger" text="名字" size="medium"></Button> <Button type="success" text="名字" size="mini"></Button> <Button type="warning" text="名字" size="medium"></Button>
到此这篇关于vue中的render函数、h()函数、函数式组件的文章就介绍到这了,更多相关vue render函数 h()函数内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!