Vue 2.0中依赖注入提供/注入组合实战
用法
-
先来看看官网的介绍:
简单的说,当组件的引入层次过多,我们的子孙组件想要获取祖先组件得资源,那么怎么办呢,总不能一直取父级往上吧,而且这样代码结构容易混乱。这个就是这对选项要干的事情
提供和注射需要配合使用,它们的含义如下:
提供;一个对象或返回一个对象的函数,该对象包含可注入起子孙的属性,可以使用ES6的标志作为键(只有原生支持标志才可以)注射;一个字符串数组或一个对象;字符串数组;提供对象里哪些属性可用;一个对象;键是本地的绑定名,值是提供里对应的对象名,也可以是一个对象,此时从属性是提供里对应的对象名,默认属性是不存在时的默认值
来个实例就明显了:
!DOCTYPE html!-例1-html lang=' en ' head meta charset=' UTF-8 '脚本src=' http :https://cdn。jsdeliver。net/NPM/[电子邮件保护]/dist/vue。js/'脚本标题文档/title/head body div id=' app ' child/child/div脚本Vue。组件(' child ',{ inject:['message'],template:'p{{message}}/p' })新Vue} })/脚本/正文/html输出:你好Vue!对应的数字正射影像图节点渲染为:
是不是感觉和小道具的传值差不多,我们在中间再嵌套一层组件就知道他的用处了,例如:
!DOCTYPE html!-例2-html lang=' en ' head meta charset=' UTF-8 ' title document/title script src=' http :3359 cdn。jsdeliver。net/NPM/[电子邮件保护]/dist/Vue。js '/脚本/头体div id=' app ' test/test/div脚本Vue。组件('子',{ input :[' message '],template : ' p { { message } }/p ' })Vue .} })/脚本/正文/html输出:你好Vue!对应的数字正射影像图节点渲染为:
就是这个用处吧,多层嵌套时还是很方便的
源码分析
-
提供/注入组合的源码分为三个部分,分别是组件注册、Vue实例化和组件实例化的过程,如下:
组件注册时
注册时会执行Vue.extend()(第4770行),内部会执行合并选项()合并一些属性,合并选项如下:
函数合并选项(//第1451行父、子、vm) { { checkComponents(子);} if(类型为child==' function '){ child=child。选项;} normalizeProps(子级,VM);normalizeInject(子,VM);//对注射进行一次规范化规格化指令(子);var extendsFrom=child . extends if(extends from){ parent=合并选项(parent,extends from,VM);} if (child.mixins) { for (var i=0,l=child。mixins。长度;我。i ) { parent=mergeOptions(parent,child.mixins[i],VM);} } var选项={ }var关键字;用于(父级中的键){ mergeField(键);}对于(键入子){ if(!hasOwn(父,键)){ mergeField(键);} }函数合并字段(键){ var strat=strats[键]| | DefaultStrat;选项[键]=strat(父[键],子[键],vm,键);}返回选项}正常输入定义如下:
函数normalizeInject(选项,vm) { //第1398行var inject=options.injectif(!inject){ return } var normalized=选项。inject={ };if (Array.isArray(inject)) { //如果注射是一个数组for(var I=0;我注射。长度;i ) { //遍历注入标准化[注入[i]]={ from:注入[I]};//保存到标准化的里面,例如: { foo : { from : ' foo ' } } } } else if(isplayanobject(inject)){//如果注射是一个对象用于(注入中的定义变量键){ var val=注入[key];规范化的[key]=isplayanoobject(val)?extend({ from: key },val): { from : val };} } else { warn(' inject ' :选项的值无效,应为数组或对象,',但得到了(toratype(inject))' .VM);}}对于例一来说,合并选项()之后注射等于: {消息: {来自: '消息' } },如下:
某视频剪辑软件实例化时
执行_init()时会执行合并选项()进行数据的合并,对于提供的合并策略等于mergeDataOrFn()函数(和数据的合并策略是一样的,定义在1321行),返回一个匿名函数(第1154行),如下:
函数mergeDataOrFn (//第1154行parentVal,childVal,vm) { if(!vm) { //这是组件的分支//在Vue.extend合并中,如果(!childVal) { return parentVal } if(!parentVal) { return childVal } //当parentVal和childVal都存在时,//我们需要返回一个函数,该函数返回两个函数的//合并结果.这里不需要//检查parentVal是否是一个函数,因为//必须是一个函数才能传递之前的合并。返回函数mergeddatfan(){ 0返回merge data(childVal==' function '的类型?childVal.call(this,this) : childVal,typeof parentVal==='function '?parentVal.call(this,this) : parentVal ) } } else { //这是非组件的实例,返回一个函数返回函数mergedinstancedatafan(){//实例合并var实例数据=类型为childVal===' function '?子Val.call(vm,VM):子valvar默认数据=parent VaL类型==' function '?parentVal.call(vm,VM): parent VaL;if(instance data){ 0返回mergeData(instanceData,defaultData) } else {返回默认数据} } }然后返回到_init()之后会调用initProvide()初始化提供:
函数initProvide (vm) { //第3619行var provide=vm .$ options.provide//尝试获取提供如果(提供){ //如果提供存在,当它是函数时执行该返回,否则直接将提供保存到某视频剪辑软件实例的_已提供属性上虚拟机_ provided=provide==' function '的类型?provide.call(vm) :提供;}}返回后_已提供等于{message:'Hello Vue!'},如下
组件实例化时
_init()时会执行initInjections(),经过了前面两步的处理,这里比较简单了,直接从父某视频剪辑软件或父某视频剪辑软件的父某视频剪辑软件获取对应的值即可,如下:
函数initinn形容词(VM){//第2681行初始化注入定义变量结果=resolveineject(VM .$options.inject,VM);//遍历祖先节点,获取对应的注射,例如:比如: { foo : ' bar ' } if(result){/如果获取了对应的值,则将它变成响应式toggleObserving(假);Object.keys(结果)。forEach(函数(键){ /*伊斯坦布尔忽略else */{ defineereactive(VM,key,result[key],function () { //将键编程响应式,这样就可以访问该元素了警告('避免直接改变注入的值,因为只要提供的组件重新呈现,更改就会被覆盖。'注入被变异: \ ' '键\ ' \ ',VM);});} });toggleObserving(真);} }函数resolveInject (inject,vm) { //第3649行确定注射注射液:例如: { foo : {来自: ' foo ' } } VM :当前组件的实例如果(注入){ //如果注射非空//注入为:任何,因为流动不够智能,无法计算出缓存的定义变量结果=对象。create(null);//存储最后的结果var keys=hasSymbol?Reflect.ownKeys(注入)。过滤器(功能(键){ //如果有符号类型,调用Reflect.ownKeys()返回所有的关键,再调用过滤器/*伊斯坦布尔忽略下一个*/返回对象。getowntpropertysdescriptor(inject,key).可枚举的}) :对象.键(注入);//获取所有的关键,此时键就是个字符串数组,比如:[' foo ']为(var I=0;长度;i ) { //这里遍历每个key var key=key[I];var provideKey=inject[key].来自;var source=vmwhile(source){ if(source ._提供了hasOwn(来源。_提供,provideKey)) { //如果来源存在_已提供且含有provideKey这个属性结果[键]=来源。_提供了[ProvideKey];//则将值保存到结果[关键字]中break //并跳出正在…循环}来源=来源$ parent//否则将来源赋值给父某视频剪辑软件实例,直到找到对应的providekey为止} if(!来源){ //如果最后来源不存在,即没有从当前实例或祖先实例的_提供找到privideKey这个key if(' default ' in inject[key]){ var provideDefault=inject[key].违约;//如果有定义德弗尔特,则使用默认值结果[键提供默认值==='函数'的类型?提供默认值。调用(虚拟机):提供默认值;} else { warn('注入\ '键' \ '未找到),VM);} } }返回结果/返回结果,比如:{foo: 'bar'} }}注:提供和注射绑定并不是可响应的。这是刻意为之的。然而,如果你传入了一个可监听的对象,那么其对象的属性还是可响应的。
总结
以上所述是小编给大家介绍的Vue 2.0中依赖注入提供/注入组合实战,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!
版权声明:Vue 2.0中依赖注入提供/注入组合实战是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。