Vueソース-2.データハイジャック
4892 ワード
import { initMixin } from "./init"
function Vue(options) {
// Vue
this._init(options)
}
// Vue
initMixin(Vue)
export default Vue
import { initState } from './state';
// init
export function initMixin(Vue) {
//
Vue.prototype._init = function(options) {
//
const vm = this; // vue this.$options
vm.$options = options
//
initState(vm)
}
}
import { observe } from "./observer/index"
export const initState = function(vm) {
let opts = vm.$options
console.log(opts);
// vue 、 、 、 、 watch
if(opts.props) {
initProps(vm)
}
if(opts.methods) {
initMethods(vm)
}
if(opts.data) {
initData(vm)
}
if(opts.computed) {
initComputed(vm)
}
if(opts.watch) {
initWatch(vm)
}
}
function initData(vm) {
//
let data = vm.$options.data // data
/**
* 1. data._data data
* 2. data data()
*/
data = vm._data = typeof data == 'function' ? data.call(vm) : data
// , -
// MVVM
// object.defineProperty() get 、set
observe(data) //
}
/**
* 1. data , Object.defineProperty es5
* 2. Object.defineProperty ie8 , vue2 ie8
*/
import { isObject, def } from '../utils/index';
import { arrayMethods } from './array.js'
class Observer {
constructor(value) {
// vue , , set get
// vue3.0 proxy ,proxy , get set , 2-3
def(value, '__ob__', this)
if(Array.isArray(value)) {
// ,
// push shift unshift
//
value.__proto__ = arrayMethods //
this.observerArray(value)
} else {
this.walk(value)
}
}
observerArray(data) {
data.forEach(item => {
observe(item)
})
}
walk(data) {
let keys = Object.keys(data)
keys.forEach(key => {
defineReactive(data, key, data[key]) //
});
}
}
function defineReactive(data, key, value) {
observe(value) //
Object.defineProperty(data, key, {
get() { //
return value
},
set(newValue) { //
if(newValue === value) return
observe(newValue) // ,
value = newValue
}
})
}
export function observe(data) {
let isObj = isObject(data)
if(!isObj) {
return
}
//
return new Observer(data)
}
//
export function isObject(data) {
return typeof data === 'object' && data !== null
}
//
export function def(data, key, value) {
Object.defineProperty(data, key, {
enumerable: false,
configurable: false,
value
})
}