国产99久久精品_欧美日本韩国一区二区_激情小说综合网_欧美一级二级视频_午夜av电影_日本久久精品视频

最新文章專題視頻專題問答1問答10問答100問答1000問答2000關鍵字專題1關鍵字專題50關鍵字專題500關鍵字專題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關鍵字專題關鍵字專題tag2tag3文章專題文章專題2文章索引1文章索引2文章索引3文章索引4文章索引5123456789101112131415文章專題3
問答文章1 問答文章501 問答文章1001 問答文章1501 問答文章2001 問答文章2501 問答文章3001 問答文章3501 問答文章4001 問答文章4501 問答文章5001 問答文章5501 問答文章6001 問答文章6501 問答文章7001 問答文章7501 問答文章8001 問答文章8501 問答文章9001 問答文章9501
當前位置: 首頁 - 科技 - 知識百科 - 正文

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

來源:懂視網 責編:小采 時間:2020-11-27 21:54:57
文檔

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

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

用法

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

先來看看官網的介紹:

簡單的說,當組件的引入層次過多,我們的子孫組件想要獲取祖先組件得資源,那么怎么辦呢,總不能一直取父級往上吧,而且這樣代碼結構容易混亂。這個就是這對選項要干的事情

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

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

來個實例就明顯了:

<!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!,對應的DOM節(jié)點渲染為:

是不是感覺和props的傳值差不多,我們在中間再嵌套一層組件就知道他的用處了,例如:

<!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!,對應的DOM節(jié)點渲染為:

 

就是這個用處吧,多層嵌套時還是很方便的

源碼分析

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

  provide/inject組合的源碼分為三個部分,分別是組件注冊、Vue實例化和組件實例化的過程,如下:

組件注冊時

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

function mergeOptions ( //第1451行
 parent,
 child,
 vm
) {
 {
 checkComponents(child);
 }

 if (typeof child === 'function') {
 child = child.options;
 }

 normalizeProps(child, vm);
 normalizeInject(child, vm); //對inject進行一次規(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是一個數(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是一個對象
 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
 );
 }
}

對于例1來說,mergeOptions()之后inject等于:{message: {from: "message"}},如下:

Vue實例化時

執(zhí)行_init()時會執(zhí)行mergeOptions()進行數(shù)據(jù)的合并,對于provide的合并策略等于mergeDataOrFn()函數(shù)(和data的合并策略是一樣的,定義在1321行),返回一個匿名函數(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ù)
 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()之后會調用initProvide()初始化provide:

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

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

e]

組件實例化時

 _init()時會執(zhí)行initInjections(),經過了前面兩步的處理,這里比較簡單了,直接從父Vue或父Vue的父Vue獲取對應的值即可,如下:

function initInjections (vm) { //第2681行 初始化inject
 var result = resolveInject(vm.$options.inject, vm); //遍歷祖先節(jié)點,獲取對應的inject,例如:比如:{foo: "bar"}
 if (result) { //如果獲取了對應的值,則將它變成響應式
 toggleObserving(false);
 Object.keys(result).forEach(function (key) {
 /* istanbul ignore else */
 {
 defineReactive(vm, key, result[key], function () {   //將key編程響應式,這樣就可以訪問該元素了
 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:當前組件的實例
 if (inject) { //如果inject非空
 // inject is :any because flow is not smart enough to figure out cached
 var result = Object.create(null); //存儲最后的結果
 var keys = hasSymbol
 ? Reflect.ownKeys(inject).filter(function (key) { //如果有符號類型,調用Reflect.ownKeys()返回所有的key,再調用filter
 /* istanbul ignore next */
 return Object.getOwnPropertyDescriptor(inject, key).enumerable
 })
 : Object.keys(inject); //獲取所有的key,此時keys就是個字符串數(shù)組,比如:["foo"]

 for (var i = 0; i < keys.length; i++) { //這里遍歷每個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這個屬性
 result[key] = source._provided[provideKey]; //則將值保存到result[key]中
 break //并跳出while循環(huán)
 }
 source = source.$parent; //否則將source賦值給父Vue實例,直到找到對應的providekey為止
 }
 if (!source) { //如果最后source不存在,即沒有從當前實例或祖先實例的_provide找到privideKey這個key
 if ('default' in inject[key]) {
 var provideDefault = inject[key].default; //如果有定義defult,則使用默認值
 result[key] = typeof provideDefault === 'function'
 ? provideDefault.call(vm)
 : provideDefault;
 } else {
 warn(("Injection \"" + key + "\" not found"), vm);
 }
 }
 }
 return result //返回結果,比如:{foo: "bar"}
 }
}

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

總結

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

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

文檔

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

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

最新推薦

猜你喜歡

熱門推薦

專題
Top
主站蜘蛛池模板: 国内高清久久久久久久久 | 在线欧美色图 | 欧美一区二区三区在线观看 | 国产高清不卡一区二区 | 91精品观看91久久久久久 | 久久国产精品成人免费 | 成人欧美精品久久久久影院 | 国内精品免费 | 欧美视频精品一区二区三区 | 影音先锋亚洲综合小说在线 | 国产不卡在线 | 最新国产精品精品视频 | 小处雏高清一区二区三区 | 欧美在线一 | 欧美精品在线视频观看 | 久久综合伊人77777麻豆 | 国产a国产片 | 欧美日韩成人高清色视频 | 久久频道毛片免费不卡片 | 国产 日韩欧美 | 欧美二区三区 | 国产呦系列 欧美呦 日韩呦 | 日韩视频免费看 | 一本久久精品一区二区 | 亚洲v欧美v日韩v国产v | 亚洲一区 中文字幕 久久 | 免费看特级淫片日本 | 欧美在线观看一区二区三 | 欧美日韩中文国产 | 91精品国产综合久久久久久 | 精品国产香蕉 | 成人国产精品久久久免费 | 劲爆欧美精品13页 | 在线看精品 | 欧美第四页 | 国产在线观看不卡 | 日韩经典第一页 | 中文字幕久久亚洲一区 | 国产高清在线免费观看 | 国产精品香蕉一区二区三区 | 亚洲一区中文字幕在线观看 |