【js】 vue 2.5.1 源码学习(一) 大体结构 (自写版本,非源码)
一、整体思路
1. 首先我们需要解析data,并且data里面的属性添加为vue的属性,并且拿到属性值 。 通过 原型方法 _peoxy实现 Obsever(代理函数) ==》 walk convert defineReactive
2. 对象属性的默认值 defineProperty
3. vue.init ==> $mount ==> compile
1 // 大概思路 1. 将data的值设置为Vue的属性。 _peoxy Obsever(代理函数) ==》 walk convert defineReactive 2 // 2. 对象属性的默认值 defineProperty 3 // 3. vue.init ==> $mount ==> compile 4 5 6 (function(root, factory){ 7 root.Vue = factory() 8 })(this,function(){ 9 var noop = function(){ 10 11 } 12 function compile(){ 13 14 } 15 function defineProperty(obj , key ,val , def ){ 16 // 判断是都又值,没有则选择默认值 17 if(val !== undefined){ 18 obj[key] = val 19 }else{ 20 obj[key] = def 21 } 22 } 23 function obsever(data){ 24 // 数据变化的监听代理 25 if(!data || typeof data !=='object') return 26 return new Obsever(data) 27 } 28 function Obsever(data){ 29 this.data = data 30 this.walk() 31 } 32 Obsever.prototype = { 33 walk:function(){ 34 var obj = this.data 35 this.convert(obj) 36 }, 37 convert: function(obj){ 38 var _this = this 39 Object.keys(obj).forEach(function(key){ 40 _this.defineReactive(obj,key,obj[key]) 41 }) 42 }, 43 defineReactive: function(obj,key,val){ 44 Object.defineProperty(obj,key,{ 45 get: function(){ 46 return val 47 }, 48 set:function(newVal){ 49 console.log('我能够监听到message他的变化') 50 val = newVal 51 } 52 }) 53 } 54 } 55 function Vue(options){ 56 this.$options = options || {} 57 var data = this._data = options.data 58 var _this = this 59 defineProperty(this , '$rander' , this.render , noop ) 60 Object.keys(data).forEach(function(value){ 61 // console.log('eee') 62 _this._proxy(value,data[value]) 63 }) 64 obsever(data) 65 this.init(options); 66 } 67 // 将data的属性设置到vue上 68 Vue.prototype._proxy= function(key,val){ 69 var _this = this 70 Object.defineProperty(this,key,{ 71 set: function(newVal){ 72 console.log('newVal===' +newVal) 73 this._data[key] = newVal 74 }, 75 get: function(){ 76 return this._data[key] 77 } 78 }) 79 } 80 // 初始化Vue 81 Vue.prototype.init = function(options){ 82 var _this = this 83 var el = options.el 84 if(el!==undefined){ 85 this.$mount(el) // 拿到template 86 } 87 } 88 Vue.prototype.$mount= function(el){ 89 var template = this.template 90 this.$el = typeof el === 'string' ? document.querySelector(el) : document.body 91 if(this.$el == null){ 92 error('Elenemt' + this.$options.el + 'none found') 93 } 94 defineProperty(this,'$template',template,this.$el.outerHTML) 95 if(this.$render === noop){ 96 this.$render = Vue.compile(this.$template) 97 } 98 99 } 100 Vue.compile = function(){ 101 // 解析html。 102 } 103 return Vue 104 })
1 <body> 2 <div id="app"> 3 {{ message }} 4 </div> 5 <!-- <script src="https://cdn.jsdelivr.net/npm/vue@2.5.21/dist/vue.js"></script> --> 6 <script src="./vue.js"></script> 7 <script type="text/javascript"> 8 var vm = new Vue({ 9 el:"#app", 10 data: { 11 message: "hello Vue", 12 key: "wodow" 13 }, 14 computed: { 15 add:function(){ 16 // this.xxx 17 } 18 }, 19 methods: { 20 21 }, 22 mounted: function(){ 23 24 } 25 26 }) 27 vm.message = "hello yue" // vue 实例会代替data里面的值。 28 console.log( vm.message) 29 </script> 30 </body>
以上代码只是简单的叙述了一个大概开始,后续还有更多。