zoukankan      html  css  js  c++  java
  • vue 数组 新增元素 响应式原理 7种方法

    1、问题

    思考一个问题,以下代码:

    <!DOCTYPE html>
    <html>
        <head>
            <meta charset="utf-8" />
            <title>vue 数组 响应式原理</title>
        </head>
        <body>
            <div id="app">
                <div v-for="item in list">
                    {{ item }}
                </div>
            </div>
    
            <script src="https://cdn.bootcss.com/vue/2.5.17/vue.min.js"></script>
            <script type="text/javascript">
                var app = new Vue({
                    el: '#app',
                    data: {
                        list: [1, 2, 3]
                    }
                })
            </script>
    
        </body>
    </html>

    当我们在控制台输入:app.list[0] = 100时,vue会监测到变化吗?

     app.push(100)呢? 

     

     引申出的问题就是:

    vue对数组新增的元素,包括push、unshift和splice(插入)的元素是怎么做到响应式的呢

    2、Vue对新增的数组元素响应式原理

    (1)核心代码(observer/array.js)

    /*
     * not type checking this file because flow doesn't play well with
     * dynamically accessing methods on Array prototype
     */
    
    import { def } from '../util/index'
    
    const arrayProto = Array.prototype
    export const arrayMethods = Object.create(arrayProto)
    
    const methodsToPatch = [
      'push',
      'pop',
      'shift',
      'unshift',
      'splice',
      'sort',
      'reverse'
    ]
    
    /**
     * Intercept mutating methods and emit events
     */
    methodsToPatch.forEach(function (method) {
      // cache original method
      const original = arrayProto[method]
      def(arrayMethods, method, function mutator (...args) {
        const result = original.apply(this, args)
        const ob = this.__ob__
        let inserted
        switch (method) {
          case 'push':
          case 'unshift':
            inserted = args
            break
          case 'splice':
            inserted = args.slice(2)
            break
        }
        if (inserted) ob.observeArray(inserted)
        // notify change
        ob.dep.notify()
        return result
      })
    })

    在这个函数中使用到了def函数,def函数的定义是(util/lang.js):

    export function def (obj: Object, key: string, val: any, enumerable?: boolean) {
      Object.defineProperty(obj, key, {
        value: val,
        enumerable: !!enumerable,
        writable: true,
        configurable: true
      })
    }

    即对元素的属性重新定义,尤其是value的获取。

    回到observer/array.js,除了正常返回push、unshift和splice(插入)函数执行的result结果外,还通知了变化!ob.dep.notify! 所以对新增的数组元素实现了响应式的变化。

    留一个问题:

    switch (method) {
          case 'push':
          case 'unshift':
            inserted = args
            break
          case 'splice':
            inserted = args.slice(2)
            break
        }

    为什么push、unshift和splice处理的参数不一样? 

    查一下splice的参数有哪些吧。

  • 相关阅读:
    0428备份
    1
    0416工作备份
    Bootstrap dropdown a标签或者button 点击事件
    禁止Html5在手机上屏幕页面缩放
    查看端口占用情况
    cakephp 中的find的用法
    cakephp 中连接查询多表 或group by
    cakephp 中的in的用法
    php批量下载文件
  • 原文地址:https://www.cnblogs.com/mengfangui/p/9989894.html
Copyright © 2011-2022 走看看