Appearance
初始化
本节目标:理解“初始化”的核心思路,并能把它用于实际开发或面试表达。
vue 默认支持双向绑定:页面可以修改数据,一般是表单:radio checkbox input textarea可以监控到数据变化,并且更新视图(单向的)vue模式,并不是mvvm,vue默认只是做视图的实现原理:
使用Object.defineProperty:将数据对象中原有的属性,更改成带有get和set的一个属性;这样当修改对象属性值时,会触发set方法,我们在其中通知更新视图;
修改src下的index.js文件,主要逻辑: 对原型链进行拓展,对核心vue不断进行扩展
首先声明了Vue构造函数;接下来调用一系列initXX方法,目的是对Vue构造函数的原型进行扩展;
在Vue原型方法拓展好之后,我们导出Vue;之后,用户在调用new Vue()时,就会执行Vue构造函数中的代码,并最终返回一个vue实例,这个实例上有丰富的方法可供使用;
import { initMixin } from "./init";
function Vue(options) {
this._init(options);
}
// 对原型链进行拓展
initMixin(Vue)
export default Vue;init.js
主要逻辑:用使用vm保存this;将调用new Vue()时传入的参数options记录到实例的$options属性上;初始化vm实例initState(vm),主要是对用户定义的options中的data进行数据劫持;判断用户传入的参数options上是否有el属性,如果有,将页面挂载到指定的el元素内部去;
import { initState } from "./state";
export function initMixin(Vue) {
Vue.prototype._init = function (options) {
// vm比this更容易理解代表什么
const vm = this;
// 将参数option挂载到vm上
// 这样其它方法也可以方便取到options
vm.$options = options;
// vm上有很多数据,所以直接把vm传给方法
initState(vm);
if (vm.$options.el) {
// 如果有元素,页面要挂载
}
}
}state.js
主要逻辑:取得传入参数即Vue实例上的$options属性,即用户参数;判断是否有data属性,如果有的话,进行数据初始化,即initData;export function initState(vm) {
// 方便地从vm上取想要的数据
const opts = vm.$options;
if (opts.data) {
initData(vm);
}
}initData方法
主要逻辑:先取得参数vm上的data值,并命名为data;判断data是一个函数还是一个对象,如果是函数,则要调用一下,调用的时候一定要绑定this为vm实例;
对data即用户定义的数据进行劫持;function initData(vm) {
// 用户传入的数据
let data = vm.$options.data;
// 只有根实例可以data是一个对象
data = isFunction(data) ? data.call(vm) : data;
// 需要将data变成响应式的
// 观测对象中的属性
observe(data);
}export function isFunction(val){
return typeof val == 'function'
}