zoukankan      html  css  js  c++  java
  • 《Vue.js实战》章9:Render函数(1)

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <meta name="viewport" content="width=device-width, initial-scale=1.0">
        <meta http-equiv="X-UA-Compatible" content="ie=edge">
        <title>Document</title>
        <script src="Vue.2.6.10.js"></script>
    </head>
    <body>
        <!-- 写在前面:虚拟dom,是一个轻量级的js对象,在状态发生变化时,进行Diff运算,对比,生成补丁对象,并更新DOM节点,
        与传统dom操作相比,其是基于js计算的,所以开销会少上不少。 -->
        <div id="app1">
            <ele></ele>
        </div>
    
        <div id="app2">
            <ele2></ele2>
        </div>
    
        <div id="app3">
            <ele3></ele3>
        </div>
    
        <div id="app4">
            <ele4></ele4>
        </div>
    
        <div id="app5">
            <ele5>
                <div>
                    <child5></child5>
                </div>
            </ele5>
        </div>
    </body>
    <script>
        //Vnode对象通过一些特定的选项,描述了真实的dom结构
        var vNode = {
            tag:'div',
            attributes:{
                id:'container'
            },
            children:{
                //...
            }
        };
        // 一个render函数的例子
    
        Vue.component('ele',{
            render(createElement) {
                return createElement(
                    'div',
                    {//可选的数据对象,包括style、props、dom属性、on、nativeOn(仅对于指令,用于监听原生而非$emit事件)、自定义指令、作用域slot、具名slot等
                        class:{
                            'show':this.show//动态绑定class
                        },
                        attrs:{
                            id:'element'//html特型
                        },
                        on:{
                            click:this.handleClick//给div绑定click事件
                        }
                    },
                    '文本内容'
                )
            },
            data() {
                return {
                    show:true
                }
            },
            methods: {
                handleClick:function(){
                    console.log('clicked!');
                }
            },
        });
    
        var app1 = new Vue({
           el:"#app1" 
        });
    
        //在所有组件树中,如果vNode是组件或含有组件的slot,那么vnode必须唯一,以下给出两个错误示例
        var childCom ={
            render:function(createElement){
                return createElement('p','text')//省略数据对象形式,渲染结果为<p>text</p>
            }
        };
        Vue.component('ele2',{
            render:function(createElement){
                //创建一个子节点(使用子组件childCom)
                var childNode = createElement(childCom);
                return createElement('div',[
                    childNode,
                    childNode
                ])//子节点的传入形式可以是字符串或者数组
    
            }
        });
        var app2 = new Vue({
           el:"#app2" 
        });
    
    
        //错误示例2,重复使用含有组件的slot
        Vue.component('child',{
            render:function(createElement){
                return createElement('p','text');
            }
        });
        Vue.component('ele3',{
            render(createElement) {
                createElement('div',[
                    this.$slots.default,
                    this.$slots.default
                ])
            },
        });
        var app3 = new Vue({
           el:"#app3" 
        });
    
    
        //这两个实例中都在组件里使用了重复的vnode,
        // 第一种情况vnode是局部注册的组件,第二种
        //是含有组件的slot(复习:即<div></div>部分,使用$slots.default访问得到,其内部又含有组件)
    
        //正确的重复渲染多个组件的方法:
        var child4 = {
            render:function(createElement){
                return createElement('p',"text");
            }
        };
        Vue.component('ele4',{
            render:function(createElement){
                return createElement('div',
                Array.apply(null,{//将global对象作为thisObj
                    length:5
                }).map(function(){
                    return createElement(child4);
                }))
            }
        });
        var app4 = new Vue({
           el:"#app4" 
        });
    
        //对于带有组件的slot,复用需要将slot的每个子节点都克隆一份
        Vue.component('child5',{
            render:function(createElement){
                return createElement('p','text');
            }
        });
        Vue.component('ele5',{
            render:function(createElement){
                //深度克隆slot节点
                function cloneVNode(vnode){
                    const clonedChildren = vnode.children && 
                    vnode.children.map(function(vnode){
                        return cloneVNode(vnode);
                    });//返回的是vnode数组对象
                    console.log(clonedChildren);
                    const cloned = createElement(
                        vnode.tag,//‘div’
                        vnode.data,//{object}
                        clonedChildren//子节点(数组/字符串形式)
                    );
                    cloned.text = vnode.text;//克隆节点的关键属性值等于传入的slot子节点的关键属性
                    cloned.isComment = vnode.isComment;
                    cloned.componentOptions = vnode.componentOptions;
                    cloned.elm = vnode.elm;
                    cloned.context = vnode.context;
                    cloned.ns = vnode.ns;
                    cloned.isStatic = vnode.isStatic;
                    cloned.key = vnode.key;
    
                    return cloned;
                }
                const vNodes = this.$slots.default;
                console.log(vNodes);//<div>...</div>
                const clonedVNodes = vNodes.map(function(vnode){
                    console.log(vnode);//在这里slot只有一个子节点,因此遍历也只会遍历这一个
                    return cloneVNode(vnode);
                });
                console.log(clonedVNodes);
                //获取slot插槽内的内容(子节点),使用map方法依次执行cloneVnode
                //函数,在该函数中进行关键属性的复制
                return createElement('div',[
                    vNodes,
                    clonedVNodes,
                    clonedVNodes//可以重复
                ]);
            }
        });
    
        var app5 = new Vue({
           el:"#app5" 
        });
    
        
    </script>
    </html>
  • 相关阅读:
    文件修改的两种方式
    人工智能 01. 语音合成,语音识别,相似度,图灵机器人,智能对话
    flask --- 04 . 偏函数, 线程安全,栈堆,
    flask --- 03 .特殊装饰器, CBV , redis ,三方组件
    flask --- 02. 路由, 初始化配置,蓝图
    linux --- 10.常见命令
    flask --- 01 .初始
    linux --- 9. docker 容器 和 rabbitmq 队列
    linux --- 8. mysql数据库,redis 数据库
    linux --- 7. 路飞学城部署
  • 原文地址:https://www.cnblogs.com/linbudu/p/11067845.html
Copyright © 2011-2022 走看看