📄
fe-share
  • fe-share
  • JavaScript
    • Canvas 图片处理
    • Javascript 性能
    • JavaScript 原型(2) - 原型与原型链
    • JavaScript 原型(1) - 构造函数
    • JavaScript - Promise
    • Canvas 灰度
    • ES6 解构赋值
    • Proxy
    • Object.defineProperty()简介
  • Engineering
    • 登录鉴权
    • 缓存
    • Chrome-devtools
    • Docker
    • 技术架构演化
    • Git
    • webpack
    • BS 架构与 CS 架构
    • SVN(Subversion)
    • gulp
    • 前端架构
  • MachineLearning
    • GAN生成对抗网络
    • 虚拟对抗训练
    • 深度度量学习
    • 原型网络
    • 联邦学习
    • 机器学习常见评价指标
    • Transformer算法
    • Self-attention 推荐算法
    • CNN 卷积神经网络
    • 集成学习算法
    • RNN循环神经网络
    • PyTorch安装和基本操作
  • CSS
    • 什么是BFC
  • React
    • React 生命周期
    • Hooks
    • SWR
    • React 数据流
  • 跨端
    • Flutter 介绍
  • Golang
    • Golang 基础
  • Vue
    • nextTick()的使用
    • vue-cli2.x 的使用与项目结构分析
    • Vue响应式原理及总结
    • VueX的使用
    • 记录一个问题的探索过程
  • Node
    • Node 优势
    • Node Stream
    • Node 模块系统
  • AR
    • SceneKit
由 GitBook 提供支持
在本页

这有帮助吗?

  1. Vue

记录一个问题的探索过程

在本周工作中,碰到了一个比较棘手的问题。表格绑定的数组元素更新后,表格无法重新渲染的问题。趁着周末的时间解决一下。

为了提高还原度,也为了简化问题,所以用Vue写了一个demo

模板:

<template>
    <div>
        <p
            v-for="(item, index) in showObj.rows"
            :key="index"
            :style="`color:${item.color}`">
            Hello World!
        </p>
        <button @click="handleAdd">Add</button>
        <button @click="handleChange">Change</button>
        <button @click="handleClear">Clear</button>
    </div>
</template>

Vue实例

export default {
    name: 'HomePage',
    data() {
        return {
            showObj: {
                rows: []
            },
            obj: {
                rows: [{
                    color: 'Red'
                }, {
                    color: 'Green'
                }, {
                    color: 'Blue'
                }]
            }
        }
    },
    methods: {
        handleAdd() {
            let red = Math.floor(Math.random()*256);
            let green = Math.floor(Math.random()*256);
            let blue = Math.floor(Math.random()*256);
            this.obj.rows.push({
                color: `rgb(${red},${green},${blue})`
            })
        },
        handleClear() {
            this.obj.rows = this.obj.rows.slice(0, 3);
        },
        handleChange() {
            this.obj.rows.splice(Math.floor(Math.random() * this.obj.rows.length), 1, {
                color: 'white'
            })
        },
    },
    mounted() {
        this.showObj.rows = this.obj.rows;
    }
}
  • demo中对DOM绑定的数组进行了新增元素与更新元素两种方式的变更,可以发现数据与渲染都正确进行。所以可以排除Vue没有监听到数据变化的问题。

  • 在对数组进行初始化操作,只保留前三项的操作后,再次对数组进行Add与Change操作就会发现数据与渲染均不正确。

  • 复现问题以后思考造成问题的原因。注意到用于渲染展示的数组是与进行变更的缓存数组通过浅拷贝绑定的。如果在操作过程中缓存的数组指针丢失,那么确实会造成渲染不正确的情况。

handleClear() {
  console.log(this.obj.rows === this.showObj.rows)
  this.obj.rows = this.obj.rows.slice(0, 3);
  console.log(this.obj.rows === this.showObj.rows)
}
  • 于是检查是否指针丢失,可以发现输出结果是false与true。

  • 到这里,其实问题的结果已经很明了了,由于slice方法本身并不改变原数组,而在内存中创建了一个新的空间储存新数组,再次赋值后指针就丢失了。

  • 回头想想其实是一个很简单的js问题,但在工作中,却因为代码量较多等种种原因,花了很长时间没有解决。希望能在之后的编码中多多注意,谨记。

上一页VueX的使用下一页Node

最后更新于5年前

这有帮助吗?