《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>

原文地址:https://www.cnblogs.com/linbudu/p/11067845.html

时间: 2024-10-28 19:33:48

《Vue.js实战》章9:Render函数(1)的相关文章

Vue.js实战 章五:内置指令

<!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" con

vue.js实战学习——指令与事件

注:此内容摘抄自:梁灏的<Vue.js实战> 1.指令是Vue.js模版中最常用的一项功能,它带有前缀 v- ,比如:v-if , v-html ,v-pre 等.指令的主要职责就是当其表达式的值改变时,相应的将某些行为应用到DOM上. <div class="app1"> <p v-if="show">哈喽?</p> </div> var app=new Vue({ el:'.app1', data:{

vue.js实战——购物车练习(包含全选功能)

vue.js实战第5章 54页的练习1 直接放代码好了,全选的部分搞了好久,代码好像有点啰嗦,好在实现功能了(*^▽^*) HTML: <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-sca

Vue学习笔记进阶篇——Render函数

本文为转载,原文:Vue学习笔记进阶篇--Render函数 基础 Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML.然而在一些场景中,你真的需要 JavaScript 的完全编程的能力,这就是 render 函数,它比 template 更接近编译器. <h1> <a name="hello-world" href="#hello-world"> Hello world! </a> </h1>

vue.js实战学习——v-bind 及class与 style绑定

注:此内容摘抄自:梁灏的<Vue.js实战> 注:记得要引入vue.js才能运行哦,文章中贴出的代码直接复制是不行的,html css js 都放在了一起,而且也没有引用vue.js. DOM元素经常会动态的绑定一些class类名或style样式. 1.了解v-bind指令 它的主要用法是动态更新HTML元素上的属性. 在数据绑定中,最常见的两个需求就是元素的样式名称class和内联样式style的动态绑定,他们也是HTML的属性,因此可以使用v-bind指令.我们只需要用v-bind计算出表

vue.js实战学习——内置指令(一)

注:此内容摘抄自:梁灏的<Vue.js实战> 注:记得要引入vue.js才能运行哦,文章中贴出的代码直接复制是不行的,html css js 都放在了一起,而且也没有引用vue.js.   1.v-cloak v-cloak不需要表达式,它会在Vue实例结束编译时从绑定的HTML元素上移除,经常和CSS的display:none: 配合使用. <div class="app1" v-cloak> {{message}} </div> var app1

热烈庆祝《Vue.js 实战教程 V2.x(一)基础篇》上线了!

课程简介 课程地址:https://ke.qq.com/course/432961 机构名称:大华软件学院 授课讲师:大强老师 课程名称:Vue.js 实战教程 V2.x(一)基础篇 课程简介:包括前端发展史.Vue.js简介.第一个Vue.js程序.安装环境和Vue.Vue实例.模板语法.计算属性和侦听器.Class与Style绑定.条件渲染.列表渲染.事件处理.表单输入绑定.组件基础等等. 适合人群: 1.初出茅庐,想学习前端开发的同学: 2.没用过Vue.js,想学习更多框架的同学: 3.

Vue.js 实战教程 V2.x(7)计算属性和侦听器

7计算属性和侦听器 7.1计算属性 模板内的表达式非常便利,但是设计它们的初衷是用于简单运算的. 在模板中放入太多的逻辑会让模板过重且难以维护. 所以,对于任何复杂逻辑,你都应当使用计算属性. 基础例子 <div id="example"> <p>Original message: "{{ message }}"</p> <p>Computed reversed message: "{{ reversedMe

Vue.js 实战教程 V2.x(6)模板语法

Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据. 6.1插值 var obj = { msg: 'Hello Vue.js', rawHtml: '<span style="color: red">This should be red.</span>' } new Vue({ el: '#app', data: obj }) <div id="app"> ... <