常州建设银行新北分行网站,wordpress做的社交,潍坊百度网站建设,明星网页制作模板一、Observable 是什么
Observable 翻译过来我们可以理解成可观察的
我们先来看一下其在Vue中的定义 Vue.observable#xff0c;让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象 返回的对象可以直接用于渲染函数和计算属性内#xff0c;并且会在发生变…一、Observable 是什么
Observable 翻译过来我们可以理解成可观察的
我们先来看一下其在Vue中的定义 Vue.observable让一个对象变成响应式数据。Vue 内部会用它来处理 data 函数返回的对象 返回的对象可以直接用于渲染函数和计算属性内并且会在发生变更时触发相应的更新。也可以作为最小化的跨组件状态存储器
Vue.observable({ count : 1})其作用等同于
new vue({ count : 1})在 Vue 2.x 中被传入的对象会直接被 Vue.observable 变更它和被返回的对象是同一个对象
在 Vue 3.x 中则会返回一个可响应的代理而对源对象直接进行变更仍然是不可响应的
二、使用场景
在非父子组件通信时可以使用通常的bus或者使用vuex但是实现的功能不是太复杂而使用上面两个又有点繁琐。这时observable就是一个很好的选择
创建一个js文件
// 引入vue
import Vue from vue
// 创建state对象使用observable让state对象可响应
export let state Vue.observable({name: 张三,age: 38
})
// 创建对应的方法
export let mutations {changeName(name) {state.name name},setAge(age) {state.age age}
}在.vue文件中直接使用即可
templatediv姓名{{ name }}年龄{{ age }}button clickchangeName(李四)改变姓名/buttonbutton clicksetAge(18)改变年龄/button/div
/template
import { state, mutations } from /store
export default {// 在计算属性中拿到值computed: {name() {return state.name},age() {return state.age}},// 调用mutations里面的方法更新数据methods: {changeName: mutations.changeName,setAge: mutations.setAge}
}三、原理分析
源码位置src\core\observer\index.js
export function observe (value: any, asRootData: ?boolean): Observer | void {if (!isObject(value) || value instanceof VNode) {return}let ob: Observer | void// 判断是否存在__ob__响应式属性if (hasOwn(value, __ob__) value.__ob__ instanceof Observer) {ob value.__ob__} else if (shouldObserve !isServerRendering() (Array.isArray(value) || isPlainObject(value)) Object.isExtensible(value) !value._isVue) {// 实例化Observer响应式对象ob new Observer(value)}if (asRootData ob) {ob.vmCount}return ob
}Observer类
export class Observer {value: any;dep: Dep;vmCount: number; // number of vms that have this object as root $dataconstructor (value: any) {this.value valuethis.dep new Dep()this.vmCount 0def(value, __ob__, this)if (Array.isArray(value)) {if (hasProto) {protoAugment(value, arrayMethods)} else {copyAugment(value, arrayMethods, arrayKeys)}this.observeArray(value)} else {// 实例化对象是一个对象进入walk方法this.walk(value)}
}walk函数
walk (obj: Object) {const keys Object.keys(obj)// 遍历key通过defineReactive创建响应式对象for (let i 0; i keys.length; i) {defineReactive(obj, keys[i])}
}defineReactive方法
export function defineReactive (obj: Object,key: string,val: any,customSetter?: ?Function,shallow?: boolean
) {const dep new Dep()const property Object.getOwnPropertyDescriptor(obj, key)if (property property.configurable false) {return}// cater for pre-defined getter/settersconst getter property property.getconst setter property property.setif ((!getter || setter) arguments.length 2) {val obj[key]}let childOb !shallow observe(val)// 接下来调用Object.defineProperty()给对象定义响应式属性Object.defineProperty(obj, key, {enumerable: true,configurable: true,get: function reactiveGetter () {const value getter ? getter.call(obj) : valif (Dep.target) {dep.depend()if (childOb) {childOb.dep.depend()if (Array.isArray(value)) {dependArray(value)}}}return value},set: function reactiveSetter (newVal) {const 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 (process.env.NODE_ENV ! production customSetter) {customSetter()}// #7981: for accessor properties without setterif (getter !setter) returnif (setter) {setter.call(obj, newVal)} else {val newVal}childOb !shallow observe(newVal)// 对观察者watchers进行通知,state就成了全局响应式对象dep.notify()}})
}参考文献
https://blog.csdn.net/qq_32682301/article/details/105419673https://wbbyouzi.com/archives/343