vue源码系列之 响应式数据处理
index.html
< ! DOCTYPE html>
< html lang= "en" >
< head>
< meta charset= "UTF-8" >
< meta http- equiv= "X-UA-Compatible" content= "IE=edge" >
< meta name= "viewport" content= "width=device-width, initial-scale=1.0" >
< title> Document< / title>
< / head>
< body>
< div id= "app" > { { name } } < / div>
< script src= "dist/vue.js" > < / script>
< script>
let vm = new Vue ( {
el: "#app" ,
data ( ) {
return {
name: "xpl" ,
a: {
name: "aaa" ,
b: {
name: "bbb"
}
}
}
}
} )
console. log ( "vm" , vm) ;
< / script>
< / body>
< / html>
src / index.js
对Vue实例对象调用时,传入的数据 options进行初始化操作
import {
initMixin
} from "./init" ;
function Vue ( options ) {
this . _init ( options) ;
}
initMixin ( Vue)
export default Vue;
src / init.js
对传入的对象进行拓展等,有data的数据劫持,props,watch等拓展! 首先先阐述的是对data的设置为响应式数据
把this指向当前Vue实例对象,设置为vm对象 给与Vue实例对象挂载$options
属性,之后进行拓展 initSate(vm) // 初始化数据 状态开始
import {
initSate
} from "./state" ;
export function initMixin ( Vue ) {
Vue . prototype. _init = function ( options ) {
const vm = this ;
vm. $options = options;
initSate ( vm)
}
}
state.js
针对Vue实例对象上的 $options
选项根据不同的方式去处理,data,props,watch等初始化状态 这边阐述的是,针对data 数据的初始化状态
强制vm对象添加_data属性,进行关联起来,实现MVVM模式 observe(data); 针对数据data进行数据的监听,实现响应式数据的设置!
import {
observe
} from "./observe/index" ;
import {
isFunction
} from "./utils" ;
export function initSate ( vm ) {
const opts = vm. $options;
if ( opts. data) {
initData ( vm) ;
}
}
function initData ( vm ) {
let data = vm. $options. data;
data = vm. _data = isFunction ( data) ? data . call ( vm) : data;
observe ( data) ;
}
observe / index.js
监听data数据对象,
首先先判断是否为对象,为对象的时候 才观测 之后调用 Observer(data)
观察者模式 观察者针对传入的对象进行遍历,对每一个对象上的属性进行劫持,设置为响应式属性 defineReactive方法为 定义响应式数据
首先默认而言,传入的数据是对象套对象,则需要对数据data的递归劫持 observe(value);
再者就是通过 Object.defineProperty
方法对数据进行设置响应式数据
其中又分为取值,直接返回value即可 又分为修改值
若是普通的修改值,则直接返回newVal 若是修改的是对象中的属性,则又需要递归劫持 observe(newVal)
import {
isObject
} from "../utils" ;
class Observer {
constructor ( data ) {
this . walk ( data) ;
}
walk ( data ) {
Object. keys ( data) . forEach ( key => {
defineReactive ( data, key, data[ key] ) ;
} )
}
}
function defineReactive ( data, key, value ) {
observe ( value) ;
Object. defineProperty ( data, key, {
get ( ) {
return value;
} ,
set ( newVal) {
observe ( newVal)
value = newVal;
}
} )
}
export function observe ( data ) {
if ( ! isObject ( data) ) {
return ;
}
return new Observer ( data)
}
utils.js
export function isFunction ( val ) {
return typeof val === 'function'
}
export function isObject ( val ) {
return typeof val === 'object' && val !== null
}