vue 源码分析

初始化 
Data,props,event监听
beforCreated,Created
挂载
执行编译,首次渲染、创建和追加过程
编译
编译模块分为三个阶段:parseoptimizegenerate
数据响应式
渲染函数执行时会触发getter进行依赖收集,将来数据变化时会触发setter进行更新
虚拟dom
Vue 工作机制
// dom
<div   style="color:red" @click="xx"><a> click me</a>
</div>
// vdom
{
tag: 'div',
props:{name:'开课吧',
        style:{color:red},
onClick:xx}
children: [
 {
    tag: 'a',
    text: 'click me'
}
 ]
}
更新视图
数据修改时监听器会执行更新,通过对比新旧vdom,得到最小修改,就是 patch
实现自己的Vue
简化版架构图
// 创建kvue.js// new KVue({// data: {
//
// }// })
class KVue {
  constructor(options) {
// 保存选项
this.$options = options;// 传入data选项
this.$data = options.data;// 响应化this.observe(this.$data);
}
  observe(value) {
if (!value || typeof value !== "object") {
return;}
// 遍历,执行数据响应式Object.keys(value).forEach(key => {
      this.defineReactive(value, key, value[key]);
});
}
defineReactive(obj, key, val) {// 递归
this.observe(val);
// obj定义属性Object.defineProperty(obj, key, {
get() {
return val;
},
  set(newVal) {
        if (newVal === val) {
return;}
val = newVal;
console.log(`${key}属性更新了`);}
});}
}
// 创建index.html
<script src="kvue.js"></script><script>
      const app = new KVue({
data: {
          test: "I am test",
foo: {
bar: "bar"}
}});
      app.$data.test = "hello, kaikeba!";
      app.$data.foo.bar = "oh my bar";
</script>
$data做代理, kvue.js
observe(value) {
  //...
Object.keys(value).forEach(key => {this.defineReactive(value, key, value[key]);// 代理data中的属性到vue根上this.proxyData(key);
});}
// vue根上定义属性代理data中的数据proxyData(key) {
  Object.defineProperty(this, key, {
get() {
      return this.$data[key];
},
    set(newVal) {
this.$data[key] = newVal;
}});
}
<script>
    app.test = "hello, kaikeba!";
    app.foo.bar = "oh my bar";
</script>
编译compile
class KVue {
constructor(options) {
// ...
// 新建一个Watcher观察者对象,这时候Dep.target会指向这个Watcher对象new Watcher(this,'test');
// 访问get函数,为了触发依赖收集
this.test
       new Watcher(this,'foo.bar');
       this.foo.bar
}
}
<body>
<div
id="app">
    <p>{{name}}</p>
<p
k-text="name"></p>
<p>
{{age}}</p>
<p>
      {{doubleAge}}
</p>
<input type="text" k-model="name"><button @click="changeName">呵呵</button><div k-html="html"></div>
  </div>
<script
src='./compile.js'></script>
<script
src='./kvue.js'></script>
<script>
const kaikeba = new KVue({
      el:'#app',
      data: {
name: "I am test.",
age:12,html:'<button>这是一个按钮</button>'
      },
created(){
console.log('开始啦')setTimeout(()=>{
this.name='我是测试'}, 1500)
},methods:{
changeName(){
this.name = '哈喽,开课吧'this.age = 1
}}
})
  </script>
</body>
posted @ 2019-11-05 19:12  focus_yaya  阅读(254)  评论(0编辑  收藏  举报