vue使用createElement异步渲染组件
采用了两种方式第一种方式,vue模板组件建立一个vue文件 ,假如名字叫mountElement.vue<template><div id="mountedDiv"></div></template><script>import { isVNode } from "@/plugin/VnodeUtil";import TempSlot f
·
实验了两种方式。vue模板组件异步渲染组件和函数式组件异步渲染组件。模板组件借用了slot插槽。
第一种方式,vue模板组件
建立一个vue文件 ,假如名字叫mountElement.vue
<template>
<div id="mountedDiv"></div>
</template>
<script>
import { isVNode } from "./VnodeUtil";
import TempSlot from "./TempSlot";
import Vue from "vue";
export default {
methods: {
//渲染
render(componentArr) {
let self = this;
let TempSoltConstructor = Vue.extend(TempSlot);
let instance = new TempSoltConstructor();
let vnodes = self.createVnode(componentArr);
if (isVNode(vnodes)) {
instance.$slots.default = [vnodes];
}
instance.$mount("#mountedDiv");
},
//生成虚拟dom
createVnode(elementArr) {
let self = this;
const h = self.$createElement;
return h(
"div",
{
style: {
height: "100vh",
overflowY: "auto",
width: "100vw",
overflowX: "hidden"
}
},
elementArr.map((element, index) => {
return h(element.name, element, element.slot);
})
);
}
}
};
</script>
其中VnodeUtil为
const hasOwnProperty = Object.prototype.hasOwnProperty;
export function noop() {};
export function hasOwn(obj, key) {
return hasOwnProperty.call(obj, key);
};
export function isVNode(node) {
return node !== null && typeof node === 'object' && hasOwn(node, 'componentOptions');
};
TempSlot为
<template>
<div>
<slot>
</slot>
</div>
</template>
父组件引入mountElement.vue 并使用ref,渲染的时候,http请求(或其他异步方法)返回的dom结构(必须包含name,其他的内容参考createElement中参数),使用this.$ref.mountElement.render(需要渲染的dom结构)。
第二种方式,采用函数式组件
这里,全局注册了一个函数式组件
Vue.component('element-list', {
functional: true,
props: {
componentArr: {
type: Function,
required: true
}
},
render: function (createElement, context) {
console.log("context=", context);
//这里让传入的componentArr是函数,执行结果返回数组,避开不能直接传Observer观察对象问题
var componentArr = context.props.componentArr();
/**
* 如果存在data.__ob__,说明data是被Observer观察的数据
* 不能用作虚拟节点的data
* 需要抛出警告,并返回一个空节点
*
* 被监控的data不能被用作vnode渲染的数据的原因是:
* data在vnode渲染过程中可能会被改变,这样会触发监控,导致不符合预期的操作
* Avoid using observed data object as vnode data:
* Always create fresh vnode data objects in each render!
*/
return createElement('div',
{
style: {
height: "100vh",
overflowY: "auto",
width: "100vw",
overflowX: "hidden"
}
},
getElements(createElement, componentArr)
/** componentArr && componentArr.length > 0 ? componentArr.map((element, index) => {
return createElement(
element.name,
element,
element.slot
)
}) : "" */
)
}
})
function getElements(createElement, root) {
return root ? (root instanceof Array && root.length > 0 ? root.map((element, index) => {
return createElement(
element.name,
element,
getElements(createElement, element.children)
)
}) : root.slot) : root
}
在父组件中调用
<element-list :componentArr="componentArr"></element-list>
其中
data() {
return {
componentArr: () => [] //这个参数一定要是个函数
};
},
异步渲染的时候,只要改变componentArr的值,这里 componentArr要赋值给一个函数。比如
componentArr =()=>{
return [{
name:"div",
slot:"测试div"
},{
name:"a",
slot:"测试a"}
]
}
更多推荐
已为社区贡献3条内容
所有评论(0)