vue2的实现(2)之初始化数据data

771 阅读3分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。

vue2的实现(2)之初始化数据data

回顾

  • 上次内容我们介绍了,创建目录结构,搭建一个rollup的打包环境,见图一。

这里我的根文件夹叫做rewrite-vue

  • rewrite-vue/src目录,用于存放我们的源代码。

  • rewrite-vue/rollup.config.js,里面是rollup的配置文件。

  • dist目录是我们打包后存放的文件。

    2022-01-25-1.png

    (图一目录结构)

Vue的构造函数是如何考量的?

  • rewrite-vue/src/index.jsVue的入口文件,里面是Vue构造函数。
  • Vue类为什么不使用ESclass来写?
    • 首先我们使用class来写,往原型prototype上写方法都是下面这样写,写在类的里面。
      class Vue{
        constructor(){
      
        }
        _init(){
      
        }
      }
      
    • 但是这样写,就不方便把不同的方法,拆分到不同的文件中了,但是也可以下面这样写,这样写看起来很别扭,毫无违和感。
      class Vue{
          constructor(){
      
          }
      }
      
      Vue.prototype._init = function (){
        ...
      } 
      
    • 所以Vue采用了ES5的构造函数的写法,这样也方便扩展,把不同的逻辑,拆分到不同的文件。
    • rewrite-vue/src/index.js
      import initMixin from './init'
      
      function Vue(options){
        this._init(options)
      }
      
      initMixin(Vue)
      
      export default Vue 
      
    • initMixin这个方法需要直接调用,作用是扩展Vue原型的方法,_init方法就是在initMixin里面扩展的,这样就可以把他拆分到rewrite-vue/src/init.js
    • 我们使用Vue的时候会传入options选项对象,里面会有datapropswatchcomputed等等,像下面这样。
      const vm = new Vue({
        data:{
          name:'Vue',
          age:666
        }
      })
      
    • new Vue会调用_init方法传入options

初始化数据data

  • new Vue传入选项之后,Vue是如何处理呢?
  • new Vue会调用_init方法这个方法是在initMixin中扩展的,下面我们来看一下。
  • rewrite-vue/src/init.js
    import initState from './state'
    function initMixin(Vue){
      Vue.prototype._init = function(options){
        const vm = this
        vm.$options = options
        initState(vm)
      }
    }
    export default initMixin
    
  • initMixin接受Vue的构造函数,在扩展_init方法,我们要先把用户传入的options,保存在实例上,vm.$options以后就可以拿到选项对象了。
  • 接下来就是初始化状态了,这里的状态是指我们传入的状态相关的数据,比如data, props, computed等等,我们先来初始化数据data。因为初始化状态又是独立的逻辑所以我们可以把他拆离出去。
  • 新建rewrite-vue/src/state.js,里面是关于状态的处理逻辑。
    export function initState(vm){
      const opts = vm.options
      if(opts.data){
        initData(vm)
      }
    }
    
    function initData(vm){
      let data = vm.$options.data
      data = typeof data === 'function' ? data.call(vm) : data
      vm._data = data
    
      console.log(data)
    }
    
  • 判断data是否存在,存在的话调用initData方法进行初始化,Vuedata可以传递函数或者对象我们得判断一下,然后把数据赋给vm._data,给当前实例同步一份,vm._data就是我们传入的data选项数据了。

测试一下

  • 写到这里,我们来测试一下,看看控制台有输出吗,运行npm run dev,打包一下我们的代码,在dist/index.html中输入以下代码,浏览器控制台打印如下.

  • dist/index.html

    <script src="./vue.js"></script>
    <script>
      const vm = new Vue({
        data:{
          name:'vue2',
          age:3
        }
      })
    </script>
    

    2022-01-05-2.png (图二控制台打印)

看到这里的同学,动动发财的小手,点个赞吧,希望你2022,身体健康,多挣钱,多学习,多进步。 今天是更文第九天加油~

往期精彩

vue2的实现(1)之搭建rollup打包环境

手撕koa,从零掌握koa的实现原理(1)

手撕koa,从零掌握koa的实现原理(2)

手撕koa,从零掌握koa的实现原理(3)

手撕koa,从零掌握koa的实现原理(4)

手撕koa,从零掌握koa的实现原理(5)

手撕koa,从零掌握koa的实现原理(6)

手撕koa,从零掌握koa的实现原理(7)