• 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的参数有哪些吧。

  • 相关阅读:
    jsp中el表达式的非空判断和变量赋值
    Java8新特性问题
    Git分支问题解决
    随机生成小学算数题项目
    微信聊天机器人
    微信小项目——统计好友人数,省市分布,排序并统计好友签名特点,用pyechat显示图像并存为HTML文件
    用for同时遍历多个列表并用try...except进行数值运算
    为什么元组只有单个元素时加逗号结尾?
    数据库
    爬虫初学——爬取中国大学排名并存为csv文件
  • 原文地址:https://www.cnblogs.com/mengfangui/p/9989894.html
Copyright © 2020-2023  润新知