(三) -模拟和测试 Vue 的构造函数——el作为 Vue 实例的挂载目标 & 数据劫持,就是把data中的成员设置为settergetter,作为响应式数据-数据驱动视图

模拟 Vue 的构造函数——el作为 Vue 实例的挂载目标 & 数据劫持,就是把data中的成员设置为setter/getter,作为响应式数据-数据驱动视图

el——https://cn.vuejs.org/v2/api/#el

el 提供一个在页面上已存在的 DOM 元素作为 Vue 实例的挂载目标。可以是 CSS 选择器,也可以是一个 HTMLElement 实例。

在实例挂载之后,元素可以用 vm.$el 访问。

为了模拟 Vue 的构造函数:

  1. 创建了Vue的构造函数Vue() ,新建文件vue.js中,是为了让vue访问数据更方便

  2. 接收一个参数,把参数存储起来 this.$options = options

  3. 将来处理数据和模板的关系,把data和模板$el分别存储起来

    接下来:

    **第一件事:**把data中的成员挂载到vue实例上 this.proxyData()

    1.在proxyData()方法中,遍历所有属性

    2.把每一个属性通过defineProperty()方法都挂载到vue实例上

    3.给每一个属性设置get和set;使vue实例中的数据变成响应式数据

第二件事:是为了测试vue构造函数

在index.html中,

1.把之前引入的vue文件注释,引入自己写的vue.js文件,别的代码不改

<!-- <script src="./node_modules/vue/dist/vue.js"></script> -->
<script src="./MVVM/vue.js"></script>

2.打开index.html文件,在控制台打印vue实例

数据劫持,就是把data中的成员设置为setter/getter

在这里插入图片描述
模拟vue实例——注入
在这里插入图片描述

vue.js

// options ===> { el: '', data: {} }
function Vue(options) {
    this.$options = options
    this.$data = options.data || {}
        // 判断el是否是字符串 选择器,否则就是dom对象
    const el = options.el
        // document.querySelector(el)  找到选择器  ,否则就是 DOM对象el
    this.$el = typeof el === 'string' ? document.querySelector(el) : el

    // 注入:就是为了把data中的成员挂载到vue实例上,并设置setter/getter
    this.proxyData()
        // 数据劫持,就是把data中的成员设置为setter/getter
    new Observer(this.$data)

    // 编译模板,就是编译模板中的差值表达式和指令
    new Compiler(this)
}

//把data中的成员挂载到vue实例上
Vue.prototype.proxyData = function() {
    // 1.遍历data中的所有属性    this.$data-所有属性,数组遍历-for each , 对象遍历- Object.keys(遍历目标)
    Object.keys(this.$data).forEach(key => {
        // 2.调用defineProperty把属性转换为getter/setter  设置到  Vue实例上  ,参数——1.this就是vue实例  2.属性-key  3.{}-设置属性的修饰符
        Object.defineProperty(this, key, {
            // 可遍历枚举
            enumerable: true,
            // 不可配置  不可删除
            configurable: false,
            //获取数据
            get() {
                console.log('vue get', key)
                    //属性用变量代替,取值要用[]
                return this.$data[key]
            },
            //设置数据  value-传过来的新的值
            set(value) {
                //1.新旧值一样 直接return,不进行其他操作
                if (value === this.$data[key]) {
                    return
                }
                //2.新旧值不一样  把传过来的新值value存起来
                this.$data[key] = value
            }
        })
    })
}

index.html

<body>
  <!-- View -->
  <div id="app">
    <h1>{{ name }}</h1>
    <h1>{{ age }}</h1>

    <div>
      <input type="text" v-model="name">
    </div>
    <span v-text="name"></span>
    <input type="text" v-model="age">
  </div>
  <!-- <script src="./node_modules/vue/dist/vue.js"></script> -->
  <script src="./MVVM/eventEmitter.js"></script>
  <script src="./MVVM/compiler.js"></script>
  <script src="./MVVM/observer.js"></script>
  <script src="./MVVM/vue.js"></script>
  <script>
    // ViewModel
    const vm = new Vue({
      el: '#app',
      // Model
      data: {
        name: 'zs',
        age: 18
      }
    })
  </script>
</body>

示例:

function Vue (options) {
    // options基本结构有 ===>{el:'",data:{}}
  this.$el = options.el
  this.$data = options.data || {}
  // 1. 数据劫持
  //    当数据改变的时候,通知模板编译
  for (let key in this.$data) {
    Object.defineProperty(this, key, {
      get () {
        return this.$data[key]
      },
      set (value) {
        if (value != this.$data[key]) {
          this.$data[key] = value
          // 当 set 触发,需要对外发布一个事件
        }
      }
    })
  }
  // 2. 模板编译
  //    订阅数据的改变,当数据改变更细 DOM
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值