<span id="mktg5"></span>

<i id="mktg5"><meter id="mktg5"></meter></i>

        <label id="mktg5"><meter id="mktg5"></meter></label>
        最新文章專(zhuān)題視頻專(zhuān)題問(wèn)答1問(wèn)答10問(wèn)答100問(wèn)答1000問(wèn)答2000關(guān)鍵字專(zhuān)題1關(guān)鍵字專(zhuān)題50關(guān)鍵字專(zhuān)題500關(guān)鍵字專(zhuān)題1500TAG最新視頻文章推薦1 推薦3 推薦5 推薦7 推薦9 推薦11 推薦13 推薦15 推薦17 推薦19 推薦21 推薦23 推薦25 推薦27 推薦29 推薦31 推薦33 推薦35 推薦37視頻文章20視頻文章30視頻文章40視頻文章50視頻文章60 視頻文章70視頻文章80視頻文章90視頻文章100視頻文章120視頻文章140 視頻2關(guān)鍵字專(zhuān)題關(guān)鍵字專(zhuān)題tag2tag3文章專(zhuān)題文章專(zhuān)題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專(zhuān)題3
        問(wèn)答文章1 問(wèn)答文章501 問(wèn)答文章1001 問(wèn)答文章1501 問(wèn)答文章2001 問(wèn)答文章2501 問(wèn)答文章3001 問(wèn)答文章3501 問(wèn)答文章4001 問(wèn)答文章4501 問(wèn)答文章5001 問(wèn)答文章5501 問(wèn)答文章6001 問(wèn)答文章6501 問(wèn)答文章7001 問(wèn)答文章7501 問(wèn)答文章8001 問(wèn)答文章8501 問(wèn)答文章9001 問(wèn)答文章9501
        當(dāng)前位置: 首頁(yè) - 科技 - 知識(shí)百科 - 正文

        Vue 2.0 中依賴(lài)注入 provide/inject組合實(shí)戰(zhàn)

        來(lái)源:懂視網(wǎng) 責(zé)編:小采 時(shí)間:2020-11-27 21:54:57
        文檔

        Vue 2.0 中依賴(lài)注入 provide/inject組合實(shí)戰(zhàn)

        Vue 2.0 中依賴(lài)注入 provide/inject組合實(shí)戰(zhàn):用法 -------------------------------------------------------------------------------- 先來(lái)看看官網(wǎng)的介紹: 簡(jiǎn)單的說(shuō),當(dāng)組件的引入層次過(guò)多,我們的子孫組件想要獲取祖先組件得資源,那么怎么辦呢,總不能一直取父級(jí)往上吧,而且這樣代碼結(jié)構(gòu)容易混亂
        推薦度:
        導(dǎo)讀Vue 2.0 中依賴(lài)注入 provide/inject組合實(shí)戰(zhàn):用法 -------------------------------------------------------------------------------- 先來(lái)看看官網(wǎng)的介紹: 簡(jiǎn)單的說(shuō),當(dāng)組件的引入層次過(guò)多,我們的子孫組件想要獲取祖先組件得資源,那么怎么辦呢,總不能一直取父級(jí)往上吧,而且這樣代碼結(jié)構(gòu)容易混亂

        用法

        --------------------------------------------------------------------------------

        先來(lái)看看官網(wǎng)的介紹:

        簡(jiǎn)單的說(shuō),當(dāng)組件的引入層次過(guò)多,我們的子孫組件想要獲取祖先組件得資源,那么怎么辦呢,總不能一直取父級(jí)往上吧,而且這樣代碼結(jié)構(gòu)容易混亂。這個(gè)就是這對(duì)選項(xiàng)要干的事情

        provide和inject需要配合使用,它們的含義如下:

        provide        ;一個(gè)對(duì)象或返回一個(gè)對(duì)象的函數(shù),該對(duì)象包含可注入起子孫的屬性,可以使用ES6的Symbols作為key(只有原生支持Symbol才可以)
        inject         ;一個(gè)字符串?dāng)?shù)組或一個(gè)對(duì)象
                         ;字符串?dāng)?shù)組    ;provide對(duì)象里哪些屬性可用
                        ;一個(gè)對(duì)象        ;key是本地的綁定名,value是provide里對(duì)應(yīng)的對(duì)象名,也可以是一個(gè)對(duì)象,此時(shí)from屬性是provide里對(duì)應(yīng)的對(duì)象名,default屬性是不存在時(shí)的默認(rèn)值

        來(lái)個(gè)實(shí)例就明顯了:

        <!DOCTYPE html>   <!--例1-->    
        <html lang="en"> 
        <head>
         <meta charset="UTF-8">
         <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
         <title>Document</title> 
        </head>
        <body>
         <div id="app"><child></child></div>
         <script>
         Vue.component('child',{
         inject:['message'],
         template:'<p>{{message}}</p>'
         })
         new Vue({
         el:'#app',provide:{message:'Hello Vue!'}
         })
         </script>
        </body>
        </html>

        輸出:Hello Vue!,對(duì)應(yīng)的DOM節(jié)點(diǎn)渲染為:

        是不是感覺(jué)和props的傳值差不多,我們?cè)谥虚g再嵌套一層組件就知道他的用處了,例如:

        <!DOCTYPE html>   <!--例2-->    
        <html lang="en">
        <head>
         <meta charset="UTF-8">
         <title>Document</title>
         <script src="https://cdn.jsdelivr.net/npm/vue@2.6.10/dist/vue.js"></script>
        </head>
        <body>
         <div id="app"><test></test></div>
         <script>
         Vue.component('child',{
         inject:['message'],
         template:'<p>{{message}}</p>'
         })
         Vue.component('test',{
         template:`<div><child></child></div>`
         })
         new Vue({
         el:'#app',provide:{message:'Hello Vue!'}
         })
         </script>
        </body>
        </html>

        輸出:Hello Vue!,對(duì)應(yīng)的DOM節(jié)點(diǎn)渲染為:

         

        就是這個(gè)用處吧,多層嵌套時(shí)還是很方便的

        源碼分析

        --------------------------------------------------------------------------------

          provide/inject組合的源碼分為三個(gè)部分,分別是組件注冊(cè)、Vue實(shí)例化和組件實(shí)例化的過(guò)程,如下:

        組件注冊(cè)時(shí)

        注冊(cè)時(shí)會(huì)執(zhí)行Vue.extend()(第4770行),內(nèi)部會(huì)執(zhí)行mergeOptions()合并一些屬性,mergeOptions如下:

        function mergeOptions ( //第1451行
         parent,
         child,
         vm
        ) {
         {
         checkComponents(child);
         }
        
         if (typeof child === 'function') {
         child = child.options;
         }
        
         normalizeProps(child, vm);
         normalizeInject(child, vm); //對(duì)inject進(jìn)行一次規(guī)范化
         normalizeDirectives(child);
         var extendsFrom = child.extends;
         if (extendsFrom) {
         parent = mergeOptions(parent, extendsFrom, vm);
         }
         if (child.mixins) {
         for (var i = 0, l = child.mixins.length; i < l; i++) {
         parent = mergeOptions(parent, child.mixins[i], vm);
         }
         }
         var options = {};
         var key;
         for (key in parent) {
         mergeField(key);
         }
         for (key in child) {
         if (!hasOwn(parent, key)) {
         mergeField(key);
         }
         }
         function mergeField (key) {
         var strat = strats[key] || defaultStrat;
         options[key] = strat(parent[key], child[key], vm, key);
         }
         return options
        }
        

        normalizeInject定義如下:

        function normalizeInject (options, vm) { //第1398行
         var inject = options.inject;
         if (!inject) { return }
         var normalized = options.inject = {};
         if (Array.isArray(inject)) { //如果inject是一個(gè)數(shù)組
         for (var i = 0; i < inject.length; i++) { //遍歷inject
         normalized[inject[i]] = { from: inject[i] }; //保存到normalized里面,例如:{foo: {from: "foo"}}
         }
         } else if (isPlainObject(inject)) { //如果inject是一個(gè)對(duì)象
         for (var key in inject) {
         var val = inject[key];
         normalized[key] = isPlainObject(val)
         ? extend({ from: key }, val)
         : { from: val };
         }
         } else {
         warn(
         "Invalid value for option \"inject\": expected an Array or an Object, " +
         "but got " + (toRawType(inject)) + ".",
         vm
         );
         }
        }

        對(duì)于例1來(lái)說(shuō),mergeOptions()之后inject等于:{message: {from: "message"}},如下:

        Vue實(shí)例化時(shí)

        執(zhí)行_init()時(shí)會(huì)執(zhí)行mergeOptions()進(jìn)行數(shù)據(jù)的合并,對(duì)于provide的合并策略等于mergeDataOrFn()函數(shù)(和data的合并策略是一樣的,定義在1321行),返回一個(gè)匿名函數(shù)(第1154行),如下:

        function mergeDataOrFn ( //第1154行
         parentVal,
         childVal,
         vm
        ) {
         if (!vm) { //這是組件的分支
         // in a Vue.extend merge, both should be functions
         if (!childVal) {
         return parentVal
         }
         if (!parentVal) {
         return childVal
         }
         // when parentVal & childVal are both present,
         // we need to return a function that returns the
         // merged result of both functions... no need to
         // check if parentVal is a function here because
         // it has to be a function to pass previous merges.
         return function mergedDataFn () {
         return mergeData(
         typeof childVal === 'function' ? childVal.call(this, this) : childVal,
         typeof parentVal === 'function' ? parentVal.call(this, this) : parentVal
         )
         }
         } else { //這是非組件的實(shí)例,返回一個(gè)函數(shù)
         return function mergedInstanceDataFn () {
         // instance merge
         var instanceData = typeof childVal === 'function'
         ? childVal.call(vm, vm)
         : childVal;
         var defaultData = typeof parentVal === 'function'
         ? parentVal.call(vm, vm)
         : parentVal;
         if (instanceData) {
         return mergeData(instanceData, defaultData)
         } else {
         return defaultData
         }
         }
         }
        }

        然后返回到_init()之后會(huì)調(diào)用initProvide()初始化provide:

        function initProvide (vm) { //第3619行
         var provide = vm.$options.provide; //嘗試獲取provide
         if (provide) { //如果provide存在,當(dāng)它是函數(shù)時(shí)執(zhí)行該返回,否則直接將provide保存到Vue實(shí)例的_provided屬性上
         vm._provided = typeof provide === 'function' 
         ? provide.call(vm)
         : provide;
         }
        }

        返回后_provided等于{message:"Hello Vue!"},如下

        e]

        組件實(shí)例化時(shí)

         _init()時(shí)會(huì)執(zhí)行initInjections(),經(jīng)過(guò)了前面兩步的處理,這里比較簡(jiǎn)單了,直接從父Vue或父Vue的父Vue獲取對(duì)應(yīng)的值即可,如下:

        function initInjections (vm) { //第2681行 初始化inject
         var result = resolveInject(vm.$options.inject, vm); //遍歷祖先節(jié)點(diǎn),獲取對(duì)應(yīng)的inject,例如:比如:{foo: "bar"}
         if (result) { //如果獲取了對(duì)應(yīng)的值,則將它變成響應(yīng)式
         toggleObserving(false);
         Object.keys(result).forEach(function (key) {
         /* istanbul ignore else */
         {
         defineReactive(vm, key, result[key], function () {   //將key編程響應(yīng)式,這樣就可以訪問(wèn)該元素了
         warn(
         "Avoid mutating an injected value directly since the changes will be " +
         "overwritten whenever the provided component re-renders. " +
         "injection being mutated: \"" + key + "\"",
         vm
         );
         });
         }
         });
         toggleObserving(true);
         }
        }
        
        function resolveInject (inject, vm) { //第3649行 確定Inject inject:例如:{foo: {from: "foo"}} vm:當(dāng)前組件的實(shí)例
         if (inject) { //如果inject非空
         // inject is :any because flow is not smart enough to figure out cached
         var result = Object.create(null); //存儲(chǔ)最后的結(jié)果
         var keys = hasSymbol
         ? Reflect.ownKeys(inject).filter(function (key) { //如果有符號(hào)類(lèi)型,調(diào)用Reflect.ownKeys()返回所有的key,再調(diào)用filter
         /* istanbul ignore next */
         return Object.getOwnPropertyDescriptor(inject, key).enumerable
         })
         : Object.keys(inject); //獲取所有的key,此時(shí)keys就是個(gè)字符串?dāng)?shù)組,比如:["foo"]
        
         for (var i = 0; i < keys.length; i++) { //這里遍歷每個(gè)key
         var key = keys[i];
         var provideKey = inject[key].from;
         var source = vm;
         while (source) {
         if (source._provided && hasOwn(source._provided, provideKey)) { //如果source存在_provided 且 含有provideKey這個(gè)屬性
         result[key] = source._provided[provideKey]; //則將值保存到result[key]中
         break //并跳出while循環(huán)
         }
         source = source.$parent; //否則將source賦值給父Vue實(shí)例,直到找到對(duì)應(yīng)的providekey為止
         }
         if (!source) { //如果最后source不存在,即沒(méi)有從當(dāng)前實(shí)例或祖先實(shí)例的_provide找到privideKey這個(gè)key
         if ('default' in inject[key]) {
         var provideDefault = inject[key].default; //如果有定義defult,則使用默認(rèn)值
         result[key] = typeof provideDefault === 'function'
         ? provideDefault.call(vm)
         : provideDefault;
         } else {
         warn(("Injection \"" + key + "\" not found"), vm);
         }
         }
         }
         return result //返回結(jié)果,比如:{foo: "bar"}
         }
        }

        注:provide 和 inject 綁定并不是可響應(yīng)的。這是刻意為之的。然而,如果你傳入了一個(gè)可監(jiān)聽(tīng)的對(duì)象,那么其對(duì)象的屬性還是可響應(yīng)的。

        總結(jié)

        以上所述是小編給大家介紹的Vue 2.0 中依賴(lài)注入 provide/inject組合實(shí)戰(zhàn),希望對(duì)大家有所幫助,如果大家有任何疑問(wèn)請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
        如果你覺(jué)得本文對(duì)你有幫助,歡迎轉(zhuǎn)載,煩請(qǐng)注明出處,謝謝!

        聲明:本網(wǎng)頁(yè)內(nèi)容旨在傳播知識(shí),若有侵權(quán)等問(wèn)題請(qǐng)及時(shí)與本網(wǎng)聯(lián)系,我們將在第一時(shí)間刪除處理。TEL:177 7030 7066 E-MAIL:11247931@qq.com

        文檔

        Vue 2.0 中依賴(lài)注入 provide/inject組合實(shí)戰(zhàn)

        Vue 2.0 中依賴(lài)注入 provide/inject組合實(shí)戰(zhàn):用法 -------------------------------------------------------------------------------- 先來(lái)看看官網(wǎng)的介紹: 簡(jiǎn)單的說(shuō),當(dāng)組件的引入層次過(guò)多,我們的子孫組件想要獲取祖先組件得資源,那么怎么辦呢,總不能一直取父級(jí)往上吧,而且這樣代碼結(jié)構(gòu)容易混亂
        推薦度:
        標(biāo)簽: VUE 2.0 實(shí)戰(zhàn)
        • 熱門(mén)焦點(diǎn)

        最新推薦

        猜你喜歡

        熱門(mén)推薦

        專(zhuān)題
        Top
        主站蜘蛛池模板: 2020国产精品亚洲综合网| 亚洲a级在线观看| a国产成人免费视频| 亚洲国产人成中文幕一级二级| 国产成人高清亚洲一区久久| 国产小视频免费观看| 亚洲第一街区偷拍街拍| 日本v片免费一区二区三区| 亚洲乱妇老熟女爽到高潮的片| 好爽…又高潮了毛片免费看| 亚洲精品无码mⅴ在线观看| 国产乱色精品成人免费视频| 手机永久免费的AV在线电影网| 中文字幕亚洲图片| 久久精品免费视频观看| 亚洲成a人片在线观看中文app| 亚洲免费黄色网址| 亚洲AV香蕉一区区二区三区| 亚洲第一黄色网址| 久久免费视频网站| 亚洲免费观看在线视频| 国产网站在线免费观看| 久久久久久久久久久免费精品| 亚洲AV永久无码精品成人| 国产黄色免费网站| 国产成人+综合亚洲+天堂| 亚洲综合色自拍一区| 国产电影午夜成年免费视频| 色欲aⅴ亚洲情无码AV| 亚洲午夜久久久久妓女影院| 最近中文字幕2019高清免费| 亚洲最大中文字幕无码网站 | 亚洲人JIZZ日本人| 最近中文字幕完整免费视频ww| 亚洲人成人无码.www石榴| 亚洲伊人久久精品影院| 99久久免费国产香蕉麻豆| 精品久久久久久亚洲综合网| 亚洲Aⅴ无码专区在线观看q| 最新中文字幕免费视频| 老司机69精品成免费视频|