相信使用vue的同学,render渲染函数都是听过的,但是用的不多,毕竟模板语法完全够用,且模板语法更加的直观
但是有些时候使用render函数很香的,这个官网给了一个很好的例子
代码复用
render毕竟是纯js,既然是js那么就是有js的全部功能和特性(MC没有bug只有特性)
这个最好的体现在我自己二次封装组件了,在写公共props的时候我可以写一个公共的props然后和外部传入进来的props进行合并,减少重复工作
render(createElement: CreateElement, vm: DynamicForm, formItem: FormItemConfig) {
const config = RenderUtils.getConfig(vm, formItem, {
props: {
disabled: RenderUtils.setDisabled(formItem, vm) // 增强disabled
},
attrs: {
placeholder: formItem.props?.placeholder || '请输入' + formItem.label,
},
}, this)
const children = RenderUtils.renderSlotsChildren(formItem, createElement, this.slotNames, vm)
return [
createElement(`el-input`, config, children)
]
},
static getConfig(
vm: DynamicForm,
formItem: FormItemConfig,
config: VNodeData,
renderType: RenderTypeItem
): VNodeData {
return {
ref: RenderUtils.formItemToRef(formItem),
refInFor: true,
// @ts-ignore
model: RenderUtils.getModelConfig(vm, formItem),
props: {
...formItem.props,
...config.props
},
directives: [
RenderUtils.getTitle(vm, formItem, renderType.getTitle),
...(config.directives || [])
],
attrs: {
...formItem.props,
...config.attrs,
title: undefined,
},
on: {
...formItem.events,
'hook:created': () => {
formItem.events?.['hook:created'] && formItem.events['hook:created']()
},
...config.on
},
nativeOn: {
...formItem.events,
...config.nativeOn
}
}
}
减少组件层级
当你二次封装el-table的时候,多级表头如果你使用模板语法那就要多创建一个vue文件去做递归,递归组件
使用render函数你就可以直接包装成一个函数,使用函数去递归,这样你的组件层级不会多一个,但是就是可阅读性极差
v-model的另一种实现
在官网中,v-model在render函数中实现是要自己去实现
但是偶然的一次在看文件编译的时候发现还有一种方式,官网没有讲,这也打消了我对jsx实现v-model的乱想(我没有去babel-jsx的源码 ̄□ ̄||)O(∩_∩)O
在源码编译中,编译出来的render函数里面会有一个model的选项,这是我已经写好的
我们看一下编译的,
源代码
<template>
<div>
<el-input v-model="value"></el-input>
</div>
</template>
<script>
export default {
name: 'EmptyHome',
data(){
return {
value: ''
}
}
}
</script>
<style scoped lang="scss">
</style>
编译出来的
const __vue2_script = {
name: 'EmptyHome',
data() {
return {
value: ''
};
}
};
import { render as __vue2_render, staticRenderFns as __vue2_staticRenderFns } from "D:/CODE/nodejs/project/vue2-learning/src/EmptyHome.vue?vue&type=template&lang.js";
const __cssModules = {};
/* normalize component */
import __vue2_normalizer from "/vite/vueComponentNormalizer";
var __component__ = /*#__PURE__*/__vue2_normalizer(__vue2_script, __vue2_render, __vue2_staticRenderFns, false, __vue2_injectStyles, null, null, null);
function __vue2_injectStyles(context) {
for (let o in __cssModules) {
this[o] = __cssModules[o];
}
}
__component__.options.__file = "src/EmptyHome.vue";
/* hot reload */
import __VUE_HMR_RUNTIME__ from "\u0000/vite/vueHotReload";
import __VUE_IDENTIFIER__ from "vue";
__VUE_HMR_RUNTIME__.install(__VUE_IDENTIFIER__);
if (!import.meta.env.SSR && __VUE_HMR_RUNTIME__.compatible) {
if (!__VUE_HMR_RUNTIME__.isRecorded("b35343ba")) {
__VUE_HMR_RUNTIME__.createRecord("b35343ba", __component__.options);
}
import.meta.hot.accept(update => {
__VUE_HMR_RUNTIME__.reload("b35343ba", update.default);
});
import.meta.hot.accept("/src/EmptyHome.vue?vue&type=template&lang.js", update => {
var _h = _vm.$createElement;
var _c = _vm._self._c || _h;
return _c('div', [_c('el-input', {
model: {
value: _vm.value,
callback: function callback($$v) {
_vm.value = $$v;
},
expression: "value"
}
})], 1);
};
var staticRenderFns = [];
render._withStripped = true;
export { render, staticRenderFns };
这个在createElement没有定义,官网也没有说,但是确实是可以用的,这样用render写v-model就会变得简单
如果不是model,而是sync这个vue是有约定的,所以编译出来的也很好理解
最后
这篇文章主要想讲的就是render函数v-model的另一种官网没有写的写法O(∩_∩)O,也是在这里记录一下