• Vue 学习笔记 — 组件初始化


    简书

    在vue中有3个概念很容易搞混,data,computed,props,特别是我们这些原后端开发人员。

    new Vue({
        el: "#x",
        data: { id: 1 },
        props: ["id"],
        computed: {
            id: function () { return 3; }
        }
    });
    

    测试一下,结果是propsdata无法共存,data优先级高于computed

    我经常是吧组件封装成一个extend来使用的,比如这样:

    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8" />
        <script src="js/vue2.2.6.js"></script>
        <script src="js/vCheckBox.js"></script>
    </head>
    <body>
        <input type="checkbox" id="test1" />
        <script>
            var test1 = new vCheckBox({
                el: "#test1",
                data: {
                    text: "测试多选框"
                }
            });
        </script>
    </body>
    </html>
    

    效果:

    一开始用的还挺嗨的,直到有一次一个extend用了大量的conputed

    然后这个组件对应的文档是这样的:

    结果杯具就发生了:

    var pager = new vPager({
        el: "#pager",
        data: {
            pageSize: 10
        }
    });
    

    刚才文章开头说了,data的优先级是高于computed的,所以导致pageSize的计算属性被覆盖了,结果可想而知。
    所以最后使用的时候改成了这样:

    var pager = new vPager({
        el: "#pager",
        created: function () {
            this.pageSize = 10;
        }
    });
    

    但是总感觉很不舒服

    所以我决定写一个mixin来优化这个初始化的操作;

    var pager = new vPager({
        el: "#pager",
        init: {
            pageSize: 10
        }
    });
    

    我希望达到这样的效果,无论是data或者computed都可以被赋值

    vue.mixin({
        created: function () {
            var init = this.$options.init;
            if (typeof init === "object") {
                for (var key in init) {
                    if (init.hasOwnProperty(key) && this.hasOwnProperty(key)) {
                        this[key] = init[key];
                    }
                }
            }
        }
    });
    

    这是最初的样子,挺简单的,经过一段时间的使用,又增加了一些功能,最后的变成了这样子:

    (function (vue) {
        if (vue == null) return;
        vue.config.optionMergeStrategies.init = function (parent, child) { return child; }
        vue.mixin({
            beforeCreate: function () {
                var opt = this.$options;
                if (opt.init === undefined) return;
                if (opt.created == null) {
                    opt.created = [];
                }
                var me = this;
    
                opt.created.push(init);
                var hasOnInit = "onInit" in opt.methods;
                if (!hasOnInit) {
                    opt.methods.onInit = initCallback;
                }
                if ("reInit" in opt.methods === false) {
                    opt.methods.reInit = init;
                }
                //--- function ---
                function initCallback(data) {
                    if (hasOnInit && typeof me.onInit === "function") {
                        me.onInit.apply(me, arguments);
                    }
                    setData(data);
                    me.$emit("init", { vm: me, data: data });
                }
    
                function setData(data) {
                    if (typeof data === "object") {
                        for (var key in data) {
                            if (data.hasOwnProperty(key) && key in me) {
                                me[key] = data[key];
                            }
                        }
                    }
                }
    
                function init() {
                    var initData = me.$options.init;
                    var callback = initCallback;
                    if (typeof initData === "function") {
                        if (initData.length > 0) {
                            initData = initData.call(me, callback);
                            callback = null;
                        } else {
                            initData = initData.call(me);
                        }
                    }
    
                    setData(initData);
                    callback && callback(initData);
                }
            }
        });
    })(window.Vue);
    

    这是个全局的mixin,为每个存在init选项的Vue实例添加init功能

    init功能:

    • 如果init选项为object,则使用init选项的值初始化Vue实例的字段,并触发init事件;
    • 如果init选项为无参的function,执行function后使用返回值初始化Vue实例字段,并触发init事件;
    • 如果init选项为有参的function,则会传入一个回调函数,执行回调函数会触发init事件,可以在init函数中直接返回初始值也可以在回调函数中传入初始值;
    • 为Vue添加一个函数reInit(),用于使用原始init选项重新初始化对象并触发init事件(对象存在reInit成员该功能无效);
    • 为Vue添加一个函数onInit(data),用于使用data参数初始化对象并触发init事件;
    关闭init功能

    要关闭init功能也可以在初始化时将init:undefined,为此需要专门写一个合并选项策略

    Vue.config.optionMergeStrategies.init = function (parent, child) { return child; }
    

    策略比较粗暴,直接让子选项覆盖父选项;
    除了最初的初始化属性的功能以外还支持init为function的情况:

    init 为无参的`function
    var pager = new vPager({
        el: "#pager",
        init: function() {
            var p = location.search.slice(1).split(',');
            return {
                pageNumber: p[0] || 1,
                pageSize: p[1] || 20
            }
        }
    });
    
    init 为有参的`function,直接返回初始化数据,延迟触发回调
    var pager = new vPager({
        el: "#pager",
        init: function (callback) {
            $.ajax({
                ... ,
                context: this
            }).done(function (data) {
                this.pageNumber = data.pageNumber;
                this.pageSize = data.pageSize;
                callback();
            });
            return {
                pageNumber: 1,
                pageSize: 20
            }
        }
    });
    
    init 为有参的`function,延迟传入初始化数据并触发回调
    var pager = new vPager({
        el: "#pager",
        init: function (callback) {
            $.ajax({
                ... ,
                context: this
            }).done(function (data) {
                callback({
                    data.pageNumber,
                    data.pageSize
                });
            });
        }
    });
    
    init 事件

    触发 init 事件

    vm.$emit("init", { vm: vm, data: initData })
    

    订阅 init 事件

    vm.$on("init", function(event){
        event.vm ...
        event.initData ...
    })
    
  • 相关阅读:
    如何为Android写一个PhoneGap插件
    Javascript高性能动画与页面渲染
    jquery mobile Popup
    android学习资料免费下载
    锋利的jquery第2版高清 pdf
    android获取sd卡最后一张照片
    mongodb 基础
    django 实现读写分离
    docker 部署django方式
    mysql 主从读写
  • 原文地址:https://www.cnblogs.com/blqw/p/6719089.html
Copyright © 2020-2023  润新知