您的位置:首页 > Web前端 > Vue.js

Vue插件开发一系列api Vue.util.defineReactive 手写实现

2020-04-07 18:32 2823 查看

写在开头

本文探索Vue插件开发一系列api ,很重要的一个就是:

Vue.util.defineReactive
,它就是Vue监听
current
变量重要执行者

console.log(Vue.util);

执行结果:

Vue.util.defineReactive

很重要的一个就是:

Vue.util.defineReactive
,它就是Vue监听
current
变量重要执行者

不妨从源码来学习:

/**
* Define a reactive property on an Object.
*/
//Vue的data监听,也是通过这个方法
function defineReactive$$1 (
obj,
key,
val,
customSetter,
shallow
) {
//依赖收集者
var dep = new Dep();

var property = Object.getOwnPropertyDescriptor(obj, key);
if (property && property.configurable === false) {
return
}

// cater for pre-defined getter/setters
var getter = property && property.get;
var setter = property && property.set;
if ((!getter || setter) && arguments.length === 2) {
val = obj[key];
}

var childOb = !shallow && observe(val);
//双向绑定
Object.defineProperty(obj, key, {
enumerable: true,
configurable: true,
get: function reactiveGetter () {
var value = getter ? getter.call(obj) : val;
if (Dep.target) {
//进行依赖收集
dep.depend();
/*采用依赖收集的原因:*/
//1.data里面的数据并不是所有地方都要用到
//2.如果我们直接更新整个视图,会造成资源浪费
//3.将依赖于某个变量的组件收集起来
if (childOb) {
childOb.dep.depend();
if (Array.isArray(value)) {
dependArray(value);
}
}
}
return value
},
set: function reactiveSetter (newVal) {
var value = getter ? getter.call(obj) : val;
/* eslint-disable no-self-compare */
if (newVal === value || (newVal !== newVal && value !== value)) {
return
}
/* eslint-enable no-self-compare */
if (customSetter) {
customSetter();
}
// #7981: for accessor properties without setter
if (getter && !setter) { return }
if (setter) {
setter.call(obj, newVal);
} else {
val = newVal;
}
childOb = !shallow && observe(newVal);
//触发依赖的组件产生更新
dep.notify();
}
});
}
双向绑定

上述关于响应式 双向绑定,强烈推荐之前写过的一篇文章:

推荐阅读:Vue 技术栈 手写响应式原理 到 探索设计模式

手写实现defineReactive

我们可以通过

defineReactive
来实现Vue监听current的监视者,监听某个第三方的变量

手写:

import Vue from 'vue'
import App from './App.vue'
import router from './router'

Vue.config.productionTip = false

//Vue插件开发一系列api
//console.log(Vue.util.defineReactive);
//test是属于window的对象
var test={
testa:'计时开始'
}
//设置定时器
setTimeout(function(){
test.testa='计时结束'
},2000)
function a(){
console.log(6);
}
a.install=function(vue){
//console.log(vue);
//监听testa
Vue.util.defineReactive(test,'testa');
//全局混入vue实例
vue.mixin({
data(){
return {
c:'欢迎访问超逸の博客'
}
},
methods:{
},
beforeCreate:function(){
this.test=test;
},
//全局生命周期注入
created:function(){
//console.log(this)
}

});
}
Vue.use(a);
new Vue({
router,
render: h => h(App)
}).$mount('#app')

然后我们在HelloWorld组件进行渲染,查看页面

执行结果:

疑问:为什么要写在

beforeCreate
里面?

解决:因为

create
阶段组件已经生成了,this实例已经创建了,而
beforeCreate
才刚开始。这样HelloWorld组件可以this调用来获取testa的值

学如逆水行舟,不进则退
  • 点赞 1
  • 收藏
  • 分享
  • 文章举报
一百个Chocolate 博客专家 发布了600 篇原创文章 · 获赞 2156 · 访问量 34万+ 私信 关注
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: