因为最近接手维护一个基于 ivew 的项目, 新增模块中包含很多自定义功能, 所以大量使用到了 render 函数; 故对其做一下总结...关于 render 函数, 官方文档也做了比较详细的介绍: render 函数: https://cn.vuejs.org/v2/guide... ; 一般组件我们都是用 template模板的方式去写; 有时候会造成代码上的冗余, 不好扩展.
在学习 render 函数之前, 最好先了解一下虚拟节点 vNode, 以及虚拟节点树组成的虚拟vdom, 这样会更好的理解 render 函数
/*
*@describe {渲染函数}
*@params {见下方}
*@returns {一段VNode}
*/
createElement函数: 通常写为 h 函数, 也是官方推荐的
h(
// {String | Object | Function} => 'p' | 'Select' | (h, p) => {}
// 一个 html 标签名、组件选项对象,或者
// resolve 了上述任何一种的一个 async 函数。必填项。
'div',
// {Object}
// 一个与模板中属性对应的数据对象。可选。
{
style: {
width: '100px'
},
},
// {String | Array}
// 子级虚拟节点 (VNodes),一般是数组: 由 `h()` 构建而成,参数: ('标签|组件', {attrs}, text)
// 也可以使用字符串来生成“文本虚拟节点”。可选。
[
'先写一些文字',
h('h1', '一则头条'),
h(MyComponent, {
props: {
someProp: 'foobar'
}
})
]
)
函数式组件 可以看做是组件里的一个函数,入参是渲染上下文(render context),返回值是渲染好的HTML字符串
对于函数式组件,可以这样定义:
Stateless(无状态):组件自身是没有状态的
Instanceless(无实例):组件自身没有实例,也就是没有this
由于函数式组件中没有this,参数需要靠context来传递;
export default {
name: 'functional-button',
functional: true,
render (h, context) {
return h('button', '按钮 1 号')
}
}
由官方文档可知: context 参数如下:
props:提供所有 prop 的对象
children: VNode 子节点的数组
slots: 一个函数,返回了包含所有插槽的对象
scopedSlots: (2.6.0+) 一个暴露传入的作用域插槽的对象。也以函数形式暴露普通插槽。
data:传递给组件的整个数据对象,作为 createElement 的第二个参数传入组件
parent:对父组件的引用
listeners: (2.3.0+) 一个包含了所有父组件为当前组件注册的事件监听器的对象。这是data.on 的一个别名。
injections: (2.3.0+) 如果使用了 inject 选项,则该对象包含了应当被注入的属性。
<template>
<div class="home">
<func-button>
hello button
</func-button>
</div>
</template>
<script>
import FuncButton from '../function-components/func-button'
export default {
name: 'home',
components: {
FuncButton
}
}
</script>
现在我们将这个 func-button.js 组件改造一下, 上面的hello button 文本节点为func-button.js的childern属性(数组|String),我们可以让父组件去控制组件的button按钮内容, 改写如下:
// export default {
// name: 'functional-button',
// functional: true,
// render (h, context) {
// return h('button', '按钮 1 号')
// }
// }
export default {
name: 'funtional-button',
functional: true,
render (h, { children }) {
return h('button', children)
}
}
code如下:
<template>
<div class="home">
<func-button @click="handleClick">
hello button
</func-button>
</div>
</template>
<script>
import FuncButton from '../function-components/func-button'
export default {
name: 'home',
components: {
FuncButton
},
methods: {
handleClick () {
alert('你点到我了')
}
}
}
</script>
// func-button组件
export default {
functional: true,
// 组件的属性集成在data里, 为了简便,我们可以用 data 来替换下面的 props, listeners等
// 写成 h('button', data, ['hello', ...children])
render (h, { props, listeners, children }) {
return h(
'button',
{
attrs: props,
on: {
click: listeners.click
}
},
children
)
}
}
平时开发还是多用temlate因为直观简洁,各种指令用着很方便,但是经常写template有时会觉得代码看着很冗余,如果想自己控制渲染逻辑比如循,判断等等时我们就可以考虑使用JSX
<script>
export default {
name: 'h-title',
props: {
id: {
type: Number,
default: 1
}
},
render () {
const hText = `<h${this.id}>${this.$slots.default[0].text}</h${this.id}>`
return <div domPropsInnerHTML={hText}></div>
}
}
</script>
// List.vue 组件
<template>
<div>
<template v-for="(item, index) in data">
<li :key="index" v-if="!render">{{ item }}</li>
<ListItem
v-else
:key="`a${index}`"
:render="render"
:item="item"
></ListItem>
</template>
</div>
</template>
<script>
import ListItem from "./list-item"
export default {
components: {
ListItem
},
props: {
// 支持自定义渲染
render: {
type: Function
},
data: {
type: Array,
default: () => []
}
}
};
</script>
// list-item.js
export default {
props: {
render: {
type: Function
},
item: {
type: String
}
},
render(h) { // createElement
return this.render(h, this.item)
}
}
// 父组件中
<List :data="['香蕉','苹果','橘子']" :render="render"></List>
// 可以渲染你想要的标签和内容
render (h, data) {
return <span>{data}</span>
}
市面上的主流框架,相信作为一个前端搬砖人员,或多或少都会有所接触到。如ReactJs、VueJs、AngularJs。那么对于每个框架的使用来说其实是比较简单的,还记得上大学时候,老师曾经说过:技术就是窗户纸,捅一捅就破了
第一种方式($createElement),h是一个函数类型变量。第二种方式:createElementFunction 是一个函数类型变量;第三种写法:es6语法之箭头函数
v-model的本质是通过绑定组件的value和input(绝大多数)来实现双向绑定,拆开来是组件的value绑定父组件的data数据,当data数据改变时,组件的value因为被绑定了,所以data的变化会触发value的变化,换个方向
我们知道 Vue 模板是非常强大的,基本可以完成我们日常开发的所有任务。但是,有一些用例,如基于输入或插槽值创建动态组件方式,render 函数会比模板完成的更好也更出色。
内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!