美文网首页让前端飞Vue前端开发那些事
说说如何利用 Render 函数来实现 Vue.js 的内置指令

说说如何利用 Render 函数来实现 Vue.js 的内置指令

作者: deniro | 来源:发表于2019-02-03 18:20 被阅读17次

    因为在 Render 函数中无法使用 Vue 内置指令,比如 v-if 等,但我们可以在 Render 函数中,利用原生的 JavaScript 来实现这些指令。

    1 v-if/v-else

    html:

    <div id="app">
        <e :is-show="isShow"></e>
        <button @click="isShow=!isShow">切换</button>
    </div>
    

    js:

    Vue.component('e', {
        render: function (createElement) {
            if (this.isShow) {
                return createElement('p', 'isShow 为 true');
            } else {
                return createElement('p', 'isShow 为 false');
            }
        },
        props: {
            isShow: {
                type: Boolean,
                default: false
            }
        }
    });
    
    var app = new Vue({
        el: '#app',
        data: {
            isShow: false
        }
    });
    

    效果:

    2 v-for

    可以使用 for 循环来实现 v-for 指令。

    html:

    <div id="app2">
        <e2 :list="list"></e2>
    </div>
    

    js:

    Vue.component('e2', {
        render: function (createElement) {
            var nodes = [];
            for (var i = 0; i < this.list.length; i++) {
                nodes.push(createElement('p', this.list[i]));
            }
            return createElement('div', nodes);
        },
        props: {
            list: {
                type: Array
            }
        }
    });
    
    var app2 = new Vue({
        el: '#app2',
        data: {
            list: [
                '人民心理学,实践出真知',
                '氢能源上游解析',
                '能救命的可穿戴设备都长什么样?'
            ]
        }
    });
    

    渲染结果:

    createElement 用于创建 DOM 节点,可以把它当作 JavaScript 的函数来理解。

    3 v-if 加 v-for 综合示例

    下面是综合利用 JavaScript 的 if 、else 和数组的 map 方法来渲染列表的示例。

    html:

    <div id="app3">
        <e3 :list="list"></e3>
        <button @click="click">显示</button>
    </div>
    

    js:

    Vue.component('e3', {
        render: function (createElement) {
            if (this.list.length) {
                return createElement('ul', this.list.map(function (item) {
                    return createElement('li', item);
                }));
            } else {
                return createElement('p', '无数据');
            }
        },
        props: {
            list: {
                type: Array,
                default: function () {
                    return [];
                }
            }
        }
    });
    
    var app3 = new Vue({
        el: '#app3',
        data: {
            list: []
        },
        methods: {
            click: function () {
                this.list = [
                    '人民心理学,实践出真知',
                    '氢能源上游解析',
                    '能救命的可穿戴设备都长什么样?'
                ];
            }
        }
    });
    

    这里我们使用了 map() 方法,该方法会对数组的每一项运行给定函数,返回每次函数调用的结果组成的数组。

    效果:

    上述 Render 函数所对应的 template 编码方式为:

    <ul v-if="list.length">
        <li v-for="item in list">{{item}}</li>
    </ul>
    <p v-else>无数据</p>
    
    

    4 v-model

    html:

    <div id="app4">
        <e4></e4>
    </div>
    

    js:

    Vue.component('e4', {
        render: function (createElement) {
            var that = this;
            return createElement('div', [
                createElement('input', {
                    domProps: {
                        value: this.value
                    },
                    on: {
                        input: function (event) {
                            that.value = event.target.value;
                        }
                    }
                }),
                createElement('p', '绑定值:' + this.value)
            ])
        },
        data: function () {
            return {
                value: ''
            }
        }
    });
    
    var app4 = new Vue({
        el: '#app4'
    });
    

    效果:

    这个 Render 函数所对应的 template 编码方式为:

    <div>
        <input v-model="value">
        <p>绑定值:{{value}}</p>
    </div>
    

    5 事件与按键修饰符

    事件与按键修饰符也可以自行实现:

    修饰符 语句
    .stop event.stopPropagation()
    .prevent event.preventDefault()
    .self if(event.target !== event.currentTarget) return;
    .enter.13 if(event.keyCode !== 13) return;
    .ctrl if(event.ctrlKey) return;
    .alt if(event.altKey) return;
    .shift if(event.shiftKey) return;
    .meta if(event.metaKey) return;

    有的事件修饰符, Vue.js 还提供了特殊前缀:

    修饰符 前缀
    .capture !
    .once ~
    .capture.once.once.capture ~!

    假设我们希望实现一个留言上墙的功能,即在输入框中输入内容,内容会放在留言列表中。

    html:

    <div id="app5">
        <e5></e5>
    </div>
    

    js:

    Vue.component('e5', {
        render: function (createElement) {
            var that = this;
    
            //渲染列表
            if (this.list.length) {
                var listNode = createElement('ul', this.list.map(function (item) {
                    return createElement('li', item);
                }));
            } else {
                var listNode = createElement('p', '无内容');
            }
    
            return createElement('div', [
                listNode,
                createElement('input', {
                    attrs: {
                        placeholder: '想说的话……'
                    },
                    style: {
                        width: '200px'
                    },
                    on: {
                        keyup: function (event) {
                            //如果不是回车键,直接返回
                            if (event.keyCode !== 13) {
                                return;
                            }
    
                            //把输入的内容新增到聊天列表
                            that.list.push(event.target.value);
    
                            //清空输入框
                            event.target.value='';
                        }
                    }
                })
            ])
        },
        data:function () {
            return {
                value:'',
                list:[]
            }
        }
    });
    
    var app5 = new Vue({
        el: '#app5'
    });
    

    效果:

    6 未定义 slot 内容的默认值

    slot 内容的默认值可以通过 this.$slots.default 来判定 ——

    html:

    <div id="app6">
        <e6></e6>
        <e6>
            <p>5亿年前的地球,磁场几乎全消失了,科学家:因祸得福</p>
        </e6>
    </div>
    

    js:

    Vue.component('e6', {
        render: function (createElement) {
            if (this.$slots.default === undefined) {
                return createElement('div', '无消息');
            } else {
                return createElement('div', this.$slots.default);
            }
        }
    });
    
    var app6 = new Vue({
        el: '#app6'
    });
    

    效果:


    本文示例代码

    相关文章

      网友评论

        本文标题:说说如何利用 Render 函数来实现 Vue.js 的内置指令

        本文链接:https://www.haomeiwen.com/subject/iwakdqtx.html