Vue源码之关于虚拟机$delete()/Vue.use()内部原理详解
虚拟机$delete()
虚拟机。$删除用法见官网。
为什么需要Vue.delete()?
在ES6之前,JS没有提供方法来侦测到一个属性被删除了,因此如果我们通过删除删除一个属性,Vue是侦测不到的,因此不会触发数据响应式。
见下面的演示。
!DOCTYPE html html lang=' en ' head meta charset=' UTF-8 '/meta name=' viewport ' content=' width=device-width,initial-scale=1.0 '/meta http-equiv=' X-UA-Compatible ' content=' ie=edge '/title vue Demo/title script src=' http 3360https://cdn。jsdeliver。net/NPM/vue '/脚本/头体div id=' app '名字: {{ user.name }}年纪: {{ user.age }}按钮@单击='addUserAgeField '删除一个年纪字段/button /div脚本const app=new Vue({ el: '#app ',数据: { user : { name : ' test ',age: 10 } },mounted() {},方法: { adduseragfield(){//delete this。用户。年龄;//这样是不起作用,不会触发数据响应式更新这个$delete(this.user,' age') //应该使用} } });/脚本/正文/html源码分析内部实现
源码位置vue/src/core/instance/state.js的stateMixin方法
导出函数statemicin(vue :类组件){ 0.vue。原型。$ set=set vue。原型。$ delete=del.}然后查看倒三角形函数位置,vue/src/core/observer/index.js。
/** *删除属性并在必要时触发更改。*目标:将被删除属性的目标对象,可以是对象/数组* key:删除属性*/导出函数del (target: Arrayany | Object,key: any) { //非生产环境下,不允许删除一个原始数据类型,或者未定义,null if (process.env.NODE_ENV!==' production '(isUndef(目标)| | isPrimitive(目标)){ warn(` 0无法删除未定义、零或基元值: ${(target: any)} `)上的反应属性)} //如果目标是数组,并且键是一个合法索引,通过数组的splcie方法删除值,并且还能触发数据的响应(数组拦截器截取到变化到元素,通知依赖更新数据)if(数组。isarray(target)是validarrayindex(key)){ target。拼接(键,1)返回} //获取ob const ob=(target: any).__ob__ //目标._isVue:不允许删除某视频剪辑软件实例对象上的属性//(ob。vmcount):不允许删除根数据对象的属性,触发不了响应如果(目标. isVue | |(ob。VM count(){ process。ENV。NODE _ ENV!=='production' warn('避免删除某视频剪辑软件实例或其根$数据上的属性' '-只需将其设置为空即可)返回} //如果属性压根不在对象上,什么都不做处理if(!hasOwn(target,key)) { return } //走到这一步说明,目标是对象,并且键在目标上,直接使用删除删除删除目标[键] //如果鄂毕河(Ob)不存在,说明目标本身不是响应式数据,如果(!ob) { return } //存在ob,通过鄂毕河(Ob)里面存储的资料执行防止实例的通知方法通知依赖更新ob.dep.notify()}工具函数
//判断是否v是未定义导出函数isUndef (v: any):布尔%检查{返回v===未定义| | v===null }//判断v是否是原始数据类型(基本数据类型)导出函数isPrimitive(值: any):布尔%检查{ return(值类型=='string' ||值类型==' number ' | |/$ flow-disable-line值类型=='符号' ||值类型==='布尔')}//判断对象上是否有属性const hasOwn属性=Object。原型。hasOwn属性导出函数hasOwn (obj: Object | Array*,key : string): boolean {返回hasOwn属性。呼叫关于__ob__属性,在很多源码地方我们都会看到类似这样获取观察员实例)
const ob=(target: any).__ob__牢记只要数据被观察过就会打上这个私有属性,是在观察者类的构造器里面发生的
导出类观察者{构造函数(值: any){ this。value=value//云娥你看-什么-是吗是吗,你是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说,我是说_ _ _ ob _。离开将此情况通知()。dep=new dep()this。vmcount=0//那是什么_ _ _ _ _ if _ _ def(值,' __ob_,' this)if(数组。isaarray(value)){ if(has proto){ proto include(value,arrayMethods)} else { copy include(value,arrayMethods,array keys这。observer ray(value)} else { this。walk(value)} }-我.}视图。使用()
你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,1590年蜜蜂!蜜蜂!
云娥与云娥。
阿久vue。使用()喜曰武契特-你好-你好
vue。使用()林书豪林书豪视图(视图)噼嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯嚯
绿筠小姐3330视图/src/core/index.js
视图(视图)
initGlobalAPI()
绿筠小姐3330视图/src/core/global-api/index.js
导出函数初始化全局应用编程接口(查看3330全局应用编程接口)>-我.//哎哎哎哎哎use() initUse视图-我.}initUse()
绿筠小姐3330视图/src/core/global-api/use.js
导出函数init use(查看3330全局API){//贺盛瑞(音译)视图(视图)1590年。//贺盛瑞?贺盛瑞3330//vista-dev/src/core/global-API/index。js initglobalapi()何曰//检视-dev/src/core/index.js贺盛瑞贺盛瑞initGlobalAPI()哎哎哎哎哎哎哎API//视图。使用():是吗查看。js-检视。射流研究…你好//唉呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀呀,啁啾安装(安装)凯伊姆//哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟,是阿叔安装(安装)凯伊姆//安装费基蒙维基奥,云娥视图(视图)吴亚玲吴亚玲查看。使用=函数(:函数插件|对象)/(installedplugins)哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟安装(安装)哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟const installeddlugins=(this)._ installedPlugins |(此处)。_ installed plugins=[]))if(installed plugins。(插件)-1){//唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔唔返回此} //附加参数//我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊!我的天啊查看。使用(mylugin,{ some option : true })const args=to array(arguments,1) //args哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟视图(视图)你好吗,云娥安装(安装)伯公曰args.unshift(this) //云娥云娥安装(安装)凯伊姆,哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟哟此(视图),哎哎哎哎安装(安装)凯伊姆//拜占庭,安装贺盛德贺盛德贺盛德视图(视图)你好吗,云娥?云娥?云娥:if(插件类型。install===function }//插件云娥plugin.install.apply(plugin,args)} else if(plugin type==" function "){//plugin朱建安吗plugin.apply(null,args) } //install吕克吕克吕克吕克吕克安装了lugins。push(plugin)return this } } vuex喜曰
阿曼苏丹国查看。js-检视。射流研究…你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看,你看安装(安装)凯伊姆。贺盛德贺盛德贺盛德视图(视图)你好吗,云娥?云娥?云娥:
云娥与云娥同在武契特什么事安装(安装)高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文高文
绿筠小姐3330 vuex-dev/src/store。js-虚拟媒体
允许查看//安装时绑定//安装3330关于武契特你好视图,视图,使用(Vuex)吕俊钦曰安装(安装)凯伊姆//云娥vue。使用()喜曰。视图-dev/src/core/global-API/use。jsexport函数install(_ view){ if(view _ view===view){ if(process。环境。node _ env!==' production '){控制台。错误([vuex]已安装视图。使用(vuex)只应调用一次)} return } //云娥,吴亚玲!吴亚玲视图(视图)孟尝君窗口。视图。我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是,我的意思是查看。使用()view=_ view applymixin(视图)}applyMixin()
绿筠小姐3360 vuex/src/mixin.js
导出默认函数(Vue){ const version=Number(Vue。版本。拆分(' . '))[0])如果(版本=2) { //如果是2.x.x以上版本,注入一个全局混合,执行vueInit方法vue。mixin({ BeforeCreate3360 vue xit })} else {//重写初始化并注入vuexInit过程//,以实现1.x向后兼容。//重写某视频剪辑软件原型上的_init方法,注入vueinit方法_init方法见vue-dev/src/core/instance/init。js const _ init=vue。原型。_ init//作为缓存变量vue。原型。_ init=function(options={ }){ options。init=选项。初始化?[vue xit].concat(选项。init): vue xit//重新执行_init _init.call(this,options)}/* * * Vuex init hook,注入到每个实例的初始化钩子列表中。*///注入商店到某视频剪辑软件构造器函数vue xit(){//这里的这个。指的是某视频剪辑软件构造器/** *新Vue({ *.*商店、*路线* }) *///选项:就是新Vue(选项)//源码见vue-dev/src/core/instance/init。js initMixin方法常量选项=这个.$options //商店注入//商店是我们使用新Vuex .商店(选项)的实例//注入商店到某视频剪辑软件构造函数上的$商店属性上,所以我们在某视频剪辑软件组件里面使用这个。$商店来使用if(选项。store){//选项。商店为真说明是根节点根这个$ store=options。store==' function '?选项。store():选项。store } else if(选项。父选项。父母。$ store){//子组件直接从父组件中获取$商店,这样就保证了所有组件都公用了全局的同一份储存这个$ store=options。父母。$ store } } }至于安装方法状态管理是如果执行的?
导出类商店{构造函数(选项={}) { //浏览器环境下安装vuex if(!某视频剪辑软件类型的窗口!=="未定义"窗口Vue) {安装(窗口Vue) }.}}以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。
版权声明:Vue源码之关于虚拟机$delete()/Vue.use()内部原理详解是由宝哥软件园云端程序自动收集整理而来。如果本文侵犯了你的权益,请联系本站底部QQ或者邮箱删除。