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 ...
})
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 211,639评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,277评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,221评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,474评论 1 283
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,570评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,816评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,957评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,718评论 0 266
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,176评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,511评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,646评论 1 340
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,322评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,934评论 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,755评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,987评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,358评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,514评论 2 348

推荐阅读更多精彩内容