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(); } }); }
双向绑定
上述关于响应式 双向绑定,强烈推荐之前写过的一篇文章:
手写实现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
- 收藏
- 分享
- 文章举报
相关文章推荐
- Vue 路由工作流程 hash 与 history
- Vue 技术栈 带你探究 vue-router 源码 手写vue-router
- 2020 零基础到快速开发 Vue全家桶开发电商管理系统(Element-UI)【目录】
- 什么场景下使用vuex
- 新建Vue项目,报错Expected indentation of 2 spaces but found 8
- Vue 设置背景图片样式
- Vue 新手学习笔记:vue-element-admin 给每个页面设置相应的 Title
- 第一个vue项目
- 关于vue-cli创建的项目位置的问题
- 安装vue-cli脚手架
- ngnix 部署 vue项目-基础篇
- Vue项目问题与分析
- Vue项目创建
- 首次加载前端vue项目浅谈
- 浅谈Vue组件的生命周期
- 浅谈vue-router
- Spring Boot+Vue前后端分离,如何避免前端页面 404
- vue一直报般配不匹配
- vue仿淘宝滑动验证码功能(样式模仿)
- Vue插件之滑动验证码用法详解