最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Vue2為何能通過(guò)this訪問(wèn)到data與methods的屬性

 更新時(shí)間:2022年09月05日 10:19:46   作者:前端Ah???????  
這篇文章主要介紹了Vue2為何能通過(guò)this訪問(wèn)到data與methods的屬性,文章圍繞主題展開(kāi)詳細(xì)的內(nèi)容戒殺,具有一定的參考價(jià)值,需要的小伙伴可以參考一下

前言

在我沒(méi)接觸vue之前我不著調(diào)this是啥壓根就沒(méi)有接觸過(guò),在我學(xué)過(guò)了vue之后我知道了this,那時(shí)候理解的this就是你要使用data中的屬性或調(diào)用methods中的方法等其他東西都要用this去調(diào)用,那時(shí)候其實(shí)我還是不知道this是啥,后面慢慢的才知道,當(dāng)然我知道應(yīng)該就是八股文背出來(lái)的,通過(guò)今天讀這個(gè)源碼,讓我理解的更加深刻了,原來(lái)還可以這么用。

一、vue的使用

看這一段代碼我們能知道有個(gè)Vue的構(gòu)造函數(shù) ,然后我們使用new Vue創(chuàng)建了它的實(shí)例,并給它傳了一個(gè)對(duì)象參數(shù),里面有data和methods,那么在這個(gè)Vue構(gòu)造函數(shù)做了什么才能讓我使用this可以直接訪問(wèn)里面的屬性或者方法呢?

    //創(chuàng)建vue的實(shí)例
    const vm = new Vue({
        data: {
            desc: '為什么this能夠直接訪問(wèn)data中的屬性',
        },
        methods: {
            sayName() {
                console.log(this.desc);
            }
        },
    });
    console.log(vm.name);
    console.log(vm.sayName());

二、Vue的構(gòu)造函數(shù)

接收一個(gè)options參數(shù)

  • 使用 instanceof 判斷 this對(duì)象上是否出現(xiàn)了Vue的prototype,我們都知道this的指向是取決于誰(shuí)調(diào)用
  • this._init(options) 證明在這調(diào)用要么我們創(chuàng)建的實(shí)例上有_init方法要么方法在Vue的prototype上,但是我們可以看到實(shí)例上并沒(méi)有_init方法 ,那么肯定在一個(gè)地方給Vue的prototype上加上了_init方法 繼續(xù)往下看
 function Vue(options) {
        if (!(this instanceof Vue)
        ) {
            warn('Vue是一個(gè)構(gòu)造函數(shù),應(yīng)使用“new”關(guān)鍵字調(diào)用');
        }
        this._init(options);
}
//Vue() //錯(cuò)誤的調(diào)用方式 進(jìn)入警告判斷 此時(shí)this指向window 然后window的 window.__proto__的指向的Window構(gòu)造函數(shù)的prototype

三 初始化initMixin(Vue)

在源碼中會(huì)看到很多初始化的函數(shù)在這我們initMixin()

這個(gè)函數(shù)就是在Vue的原型上增加了_init方法,方法接收一個(gè)參數(shù),然后定義了vm變量,在我看的時(shí)候就想看看這個(gè)函數(shù)的this指向誰(shuí),其實(shí)也不難函數(shù)掛在Vue構(gòu)造函數(shù)的原型上,調(diào)用還是在構(gòu)造函數(shù)里面使用this調(diào)用,構(gòu)造函數(shù)的this指向Vue實(shí)例,根據(jù)this的指向規(guī)則 此時(shí)的vm就指向了Vue構(gòu)造函數(shù)的實(shí)例。

使用this的訪問(wèn)規(guī)則如果實(shí)例上沒(méi)有就去原型上找

然后執(zhí)行 initState(vm)

initMixin(Vue)
function initMixin(Vue) {
        //prototype上增加init方法
        Vue.prototype._init = function (options) {
            var vm = this; //Vue實(shí)例
          	vm.age = 30
          //代碼進(jìn)行了刪減
            initState(vm);
        }
}
//這里只是舉例測(cè)試
const vm = new Vue({})
console.log(vm.age) //30

四 initState(vm)

這里就是對(duì)我們傳入的data 或者methods進(jìn)行不同的處理

 //initState方法代碼進(jìn)行了刪減
    function initState(vm) {
        vm._watchers = [];
        var opts = vm.$options; //這里是我們?cè)趧?chuàng)建實(shí)例的時(shí)候傳的參數(shù)
        //如果傳了methods 則去調(diào)用
        if (opts.methods) { initMethods(vm, opts.methods); }
        if (opts.data) {
            initData(vm);
        } else {
            observe(vm._data = {}, true /* asRootData */);
        }
    }

五 initMethods(vm, opts.methods)

如果有methods則取調(diào)用initMethods方法

前面主要是判斷 methods中的值是不是函數(shù),key有沒(méi)有跟props沖突等

最后一段代碼就是在vm的實(shí)例上增加方法vm[key]=methods[key],在讀的時(shí)候我有這樣一個(gè)以為為什么還要用bind改變this指向呢不本來(lái)就是寫(xiě)在vm實(shí)例上的方法嗎 只能使用vm調(diào)用 那么方法的this不就指向vm嗎?

/*
    vm:構(gòu)造函數(shù)實(shí)例
    methods:我們傳的methods對(duì)象
    */
    function initMethods(vm, methods) {
        var props = vm.$options.props;
        //循環(huán)methods對(duì)象
        for (var key in methods) {
            {
                //判斷是否是函數(shù) 不是的化則作出警告
                if (typeof methods[key] !== 'function') {
                    warn(
                        "Method "" + key + "" has type "" + (typeof methods[key]) + "" in the component definition. " +
                        "Did you reference the function correctly?",
                        vm
                    );
                }
                //判斷 methods 中的每一項(xiàng)是不是和 props 沖突了,如果是,警告。
                if (props && hasOwn(props, key)) {
                    warn(
                        ("Method "" + key + "" has already been defined as a prop."),
                        vm
                    );
                }
                //判斷 methods 中的每一項(xiàng)是不是已經(jīng)在 new Vue實(shí)例 vm 上存在,而且是方法名是保留的 _ $ (在JS中一般指內(nèi)部變量標(biāo)識(shí))開(kāi)頭,如果是警告。
                if ((key in vm) && isReserved(key)) {
                    warn(
                        "Method "" + key + "" conflicts with an existing Vue instance method. " +
                        "Avoid defining component methods that start with _ or $."
                    );
                }
            }
            //給實(shí)例增加methods中的方法 這樣其實(shí)我們就已經(jīng)可以用vm訪問(wèn) 到methods中的方法了
            vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
        }
    }

問(wèn)了群里大佬之后原來(lái)這步操作時(shí)為了防止用戶改變this指向,專(zhuān)門(mén)做了個(gè)例子

在這我有定義了對(duì)象a里面有個(gè)age屬性和fn,fn我賦值vm實(shí)例上的sayHi,然后a.fn()調(diào)用很明顯this的指向已經(jīng)被改變了,使用bind之后則不會(huì)

  const vm = new Vue({
        methods: {
            sayHi() {
                console.log(this.age, 'hello-this')
            }
        }
    });
    let a = {
        age: 15,
        fn: vm.sayHi
    }
    console.log(a.fn(), 'vm') //打印15

六 initData(vm)

data是如何做到的使用this可以直接訪問(wèn)的,其實(shí)原理都一樣,

首先在vm實(shí)例上增加了_data,里面存的我們傳入的data參數(shù)

 function initData(vm) {
        var data = vm.$options.data;
        data = vm._data = typeof data === 'function'
            ? getData(data, vm)
            : data || {};
        //如果不是對(duì)象則警告
        if (!isPlainObject(data)) {
            data = {};
            warn(
                'data functions should return an object:\n' +
                'https://vuejs.org/v2/guide/components.html#data-Must-Be-a-Function',
                vm
            );
        }
        // proxy data on instance
        var keys = Object.keys(data);
        var props = vm.$options.props;
        var methods = vm.$options.methods;
        var i = keys.length;
        while (i--) {
            var key = keys[i];
            //判斷key值有沒(méi)有跟methods中的key重名
            {
                if (methods && hasOwn(methods, key)) {
                    warn(
                        ("Method "" + key + "" has already been defined as a data property."),
                        vm
                    );
                }
            }
            //判斷key值有沒(méi)有跟props中的key重名
            if (props && hasOwn(props, key)) {
                warn(
                    "The data property "" + key + "" is already declared as a prop. " +
                    "Use prop default value instead.",
                    vm
                );
                //是否是內(nèi)部私有保留的字符串$ 和 _ 開(kāi)頭
            } else if (!isReserved(key)) {
              //代理
                proxy(vm, "_data", key);
            }
        }
        // observe data
        observe(data, true /* asRootData */);
    }

七 proxy(vm, "_data", key)

get 和 set 方法 注意里面的this 指向vm實(shí)例對(duì)象,上面已經(jīng)在vm實(shí)例對(duì)象上增加了_data 所有在獲取或者設(shè)置屬性值的時(shí)候 都是this._data[key] 也就是vm._data[key],

然后通過(guò)Object.defineProperty往實(shí)例對(duì)象上添加屬性,所以當(dāng)我們?cè)L問(wèn)vm[key] 也就是 vm._data[key]

  function proxy (target, sourceKey, key) {
      sharedPropertyDefinition.get = function proxyGetter () {
        return this[sourceKey][key]
      };
      sharedPropertyDefinition.set = function proxySetter (val) {
        this[sourceKey][key] = val;
      };
      Object.defineProperty(target, key, sharedPropertyDefinition);
  }
//創(chuàng)建vue構(gòu)造函數(shù)
    function Vue(options) {
        if (!(this instanceof Vue)
        ) {
            warn('Vue是一個(gè)構(gòu)造函數(shù),應(yīng)使用“new”關(guān)鍵字調(diào)用');
        }
        this._init(options);
    }
    //初始化
    initMixin(Vue);
    function initMixin(Vue) {
        //prototype上增加init方法
        Vue.prototype._init = function (options) {
            var vm = this; //Vue實(shí)例
            let methods = options.methods
            initState(vm);
        }
    }
    //initState方法代碼進(jìn)行了刪減
    function initState(vm) {
        vm._watchers = [];
        var opts = vm.$options; //這里是我們?cè)趧?chuàng)建實(shí)例的時(shí)候傳的參數(shù)
        //如果傳了methods 則去調(diào)用
        if (opts.methods) { initMethods(vm, opts.methods); }
        if (opts.data) {
            initData(vm);
        } else {
            observe(vm._data = {}, true /* asRootData */);
        }
    }
    /*
    vm:構(gòu)造函數(shù)實(shí)例
    methods:我們傳的methods對(duì)象
    */
    function initMethods(vm, methods) {
        var props = vm.$options.props;
        //循環(huán)methods對(duì)象
        for (var key in methods) {
            {
                //一些條件判斷
            }
            //給實(shí)例增加methods中的方法 這樣其實(shí)我們就已經(jīng)可以用vm訪問(wèn) 到methods中的方法了
            vm[key] = typeof methods[key] !== 'function' ? noop : bind(methods[key], vm);
        }
    }
    const vm = new Vue({
        methods: {
            sayHi() {
                console.log('hello-this')
            }
        }
    });
    vm.sayHi() //hello-this

總結(jié)

其實(shí)看明白了Methods是怎么做到直接用this可以直接訪問(wèn)的后面的都是差不多的,主要就是一個(gè)構(gòu)造函數(shù),然后創(chuàng)建一個(gè)實(shí)例,在實(shí)例上增加屬性或者方法,這樣我們就可以用實(shí)例對(duì)象直接訪問(wèn)了。原理就是那么簡(jiǎn)單。

到此這篇關(guān)于Vue2為何能通過(guò)this訪問(wèn)到data與methods的屬性的文章就介紹到這了,更多相關(guān)Vue2訪問(wèn)data內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • vue強(qiáng)制刷新組件的方法示例

    vue強(qiáng)制刷新組件的方法示例

    這篇文章主要介紹了vue強(qiáng)制刷新組件的方法示例,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2019-02-02
  • Vant picker選擇器設(shè)置默認(rèn)值導(dǎo)致選擇器失效的解決

    Vant picker選擇器設(shè)置默認(rèn)值導(dǎo)致選擇器失效的解決

    這篇文章主要介紹了Vant picker選擇器設(shè)置默認(rèn)值導(dǎo)致選擇器失效的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-01-01
  • 解決Element組件的坑:抽屜drawer和彈窗dialog

    解決Element組件的坑:抽屜drawer和彈窗dialog

    這篇文章主要介紹了解決Element組件的坑:抽屜drawer和彈窗dialog問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-07-07
  • vue3使用base64加密的兩種方法舉例

    vue3使用base64加密的兩種方法舉例

    這篇文章主要給大家介紹了關(guān)于vue3使用base64加密的兩種方法,我們?cè)趘ue項(xiàng)目中有時(shí)會(huì)使用到Base6464轉(zhuǎn)碼,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-07-07
  • Vue波紋按鈕組件制作

    Vue波紋按鈕組件制作

    本文給大家分享了VUE制作點(diǎn)擊按鈕出現(xiàn)水波紋效果的組件過(guò)程,對(duì)此有需求的朋友可以跟著學(xué)習(xí)下。
    2018-04-04
  • 手把手教你使用Vue實(shí)現(xiàn)彈窗效果

    手把手教你使用Vue實(shí)現(xiàn)彈窗效果

    在vue中彈窗是常用的組件之一,可以用來(lái)展示警告、成功提示和錯(cuò)誤信息等內(nèi)容,這篇文章主要給大家介紹了關(guān)于如何使用Vue實(shí)現(xiàn)彈窗效果的相關(guān)資料,需要的朋友可以參考下
    2024-02-02
  • 使用vue實(shí)現(xiàn)一個(gè)電子簽名組件的示例代碼

    使用vue實(shí)現(xiàn)一個(gè)電子簽名組件的示例代碼

    這篇文章主要介紹了使用vue實(shí)現(xiàn)一個(gè)電子簽名組件的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-01-01
  • Vue3如何使用axios發(fā)起網(wǎng)絡(luò)請(qǐng)求

    Vue3如何使用axios發(fā)起網(wǎng)絡(luò)請(qǐng)求

    這篇文章主要介紹了Vue3如何使用axios發(fā)起網(wǎng)絡(luò)請(qǐng)求,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • vue常用知識(shí)點(diǎn)整理

    vue常用知識(shí)點(diǎn)整理

    Vue是一套用于構(gòu)建用戶界面的漸進(jìn)式JavaScript框架。這篇文章整理了vue中的常用知識(shí)點(diǎn),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2022-06-06
  • vue 組件開(kāi)發(fā)原理與實(shí)現(xiàn)方法詳解

    vue 組件開(kāi)發(fā)原理與實(shí)現(xiàn)方法詳解

    這篇文章主要介紹了vue 組件開(kāi)發(fā)原理與實(shí)現(xiàn)方法,結(jié)合實(shí)例形式詳細(xì)分析了vue.js組件開(kāi)發(fā)的原理與實(shí)現(xiàn)方法,需要的朋友可以參考下
    2019-11-11

最新評(píng)論

开远市| 北京市| 文登市| 青河县| 双鸭山市| 桃江县| 新干县| 乐平市| 咸丰县| 申扎县| 乐都县| 句容市| 乐山市| 普宁市| 堆龙德庆县| 广平县| 色达县| 辽阳县| 怀柔区| 汽车| 喀喇沁旗| 珠海市| 全椒县| 黎城县| 西安市| 呼和浩特市| 清远市| 沙田区| 尖扎县| 钟祥市| 鄂伦春自治旗| 云南省| 阳山县| 洛浦县| 兴国县| 晋州市| 九江市| 开平市| 凌源市| 清水河县| 甘南县|