(十一)技术指引2-数据驱动的秘密
说到数据驱动,可谓是是Vue的一大特点,其实也不是Vue自己的特色,在这之前Angular从1.x版本就又有了,到底什么是数据驱动呢?我个人理解的数据驱动就是数据的变化来改变某个逻辑或某种状态。那Vue的数据驱动又是什么呢?我个人的理解就是通过数据变化来改变Vue的视图。
好像我说的还是很模糊,那么下边我就来个图文并茂。
还是不懂,没关系。下边为了让大家更加了解数据驱动的理念,并解决使用过程中可能出现的一系列问题,我就将结合小时候我们经常玩的 “拼图游戏” 来展示 Vue 数据驱动的到底是什么。
效果展示
我们先把我们的简易“拼图游戏”的效果图放上,目的是为了让大家知道我们要做什么。
我们的这个小功能要求在不操作 DOM 的情况下实现以上功能;这里需要我们对 Vue 数据驱动及数据可视化有一个非常清楚的认知,用以呈现操作数据的同时驱动可视化界面的还原。废话不多说,我们直接开始我们的代码工作吧。
核心代码
接下来我们看一下我们小游戏的核心代码:
首先是游戏的整个容器面板的代码
上边是我们游戏面板的html代码。很简单不多说了。
上边是我们的游戏面板生成1-15的顺序数字;但是我们这里要求的是随机并且是打乱了顺序的1-15之间的整数。那么我们怎么是实现呢?我们想一下这个很简单使用js中的Math方法;
这里我们使用 Math.random() 来返回 0 和 1 之间的伪随机数,可能为 0,但总是小于1,[0, 1),而通过这一特性我们可以实现生成 n-m,包含 n 但不包含 m 的整数,具体步骤如下:
- 第一步算出 m-n 的值,假设等于 w
- 第二步 Math.random() * w
- 第三步 Math.random() * w + n
- 第四步 Math.floor(Math.random() * w + n)
上述代码中 n 值永远是 0,而 w(即 len - i) 值随着循环 i 值的变大而不断减小。
上述打乱顺序的问题解决了,那么问题又来了,这个不是16个格子嘛。为毛少一个,不要着急,马上push一个空字符串。
事件机制
实现随机数字后,当我们点击方块,如果其上下左右存在为空的格子就需要将其进行交换,而由于是数据驱动界面,这里我们便需要交换两者在数组中的位置来实现
由于是 16 宫格的拼图,所以我们在点击获取位置的时候需要考虑边界情况,比如第 4 个格子为空,我们点击第 5 个格子不应该交换它们,因为在界面上第 4 个格子不在第 5 个格子的左侧,所以我们使用模方法 index % 4 来进行边界的判断,同时使用 Vue 提供的 $set 方法来将响应属性添加到数组上,细心朋友发现了这句话注释了 this.$forceUpdate();这句话的意思是什么呢?this.$forceUpdate();进行强制渲染,效果实现。防止在实际业务中层级过深无法渲染的问题。
校验机制
那么什么标准来判断我们的游戏什么时候有效完成了呢?直接上代码,在做详解
我们使用数组的 every 方法来测试数组的所有元素是否都通过了指定函数的测试,当所有数字大小和对应的数组下标 + 1 相吻合时即会返回 true。
以上,我们就完成了整个“拼图游戏”的简单功能。
知识点解惑
在实现这个简单游戏功能,我在开发初期有一些疑惑,比如:数组赋值为什么要用 $set 方法?数组随机打乱为什么不用 sort 排序呢?后来我反复做了测试,下面便来进行讲解:
为什么用 $set 方法而不是直接操作数据
大家应该都知道如果不用 $set 方法我们可以直接通过操作数组索引的形式对数组进行赋值,从而交换拼图的中两者的数据:
这时候你会发现这样做的话,数据是被强制改变了,但是页面View并没有因此重新渲染,这是为什么呢?其实 Vue 官方已经给出了明确的答案:
我们这里使用的便是第一种利用索引的方式,由于 Vue 检测不到数组变动,因此页面便无法重绘。同样 Vue 也不能检测对象属性的添加或删除,需要使用 Vue.set(object, key, value) 方法来实现。另外还有一种方法就是使用$forceUpdate()来强制更新渲染。
为什么用Math方法而不用 sort 排序
其实 sort 方法也能够实现数组的随机排序,代码如下:
我们通过使用 Math.random() 的随机数减去 0.5 来返回一个大于、等于或小于 0 的数,sort 方法会根据接收到的值来对相互比较的数据进行升序或是降序排列。
但是由于 JavaScript 内置排序算法的缺陷性,使用 sort 排序的结果并不随机分布,经过大量的测试你会发现越大的数字出现在越后面的概率越大。
总结
本笔记通过这样一个非常简单的小游戏来强化个人对于 Vue 数据驱动的理解。相比操作 DOM 元素,操作数据其实更加的便捷和快速,可以使用较少的代码来实现一些较为复杂的逻辑。