👍解说vue开发过程中的“深坑”,HeyUI组件库开发总结

迭代苔原
• 阅读 3178
之前,我发了一些关于HeyUI组件库的一些文章,有些人建议我把开发中遇到的问题共享出来,这一篇算是一个尝试,看大家反馈,会有更多的开发知识共享。

首先,这一篇,说的是vue开发中的“深坑”,并不是有一些文章写的“vue安装失败,模块找不到,或者vue-router如何定义”等等基础错误。

然后,这一篇需要阅读者对vue有着基本的了解,并且使用过,如果你对vue还不懂,建议先收藏,以后再看。

HeyUI

如果对我们组件库不熟悉的小伙伴可以参见我们官网:
heyui.top
或者围观我们的github:
github.com/heyui/heyui

这一篇主要说的是vue使用中遇到的常见并且很难解决的错误,有可能系统没有报错,但是我们就是找不到原因。

问题一、数据修改了,但是界面仍然没有更新

<template>
    <div id="app">
      <p>a:{{value.a}}</p>
      <p><button @click="changeValueA">change a value</button></p>
      <p><button @click="changeValueToughA">change a value use $set</button></p>
      <p>b:{{value.b}}</p>
      <p><button @click="changeValueB">change b value</button></p>
      <p><button @click="changeValue">change value</button></p>
    </div>
</template>
<script>
    new Vue({
      el: '#app',
      data: {
        value: {
          b: 1
        }
      },
      methods: {
        changeValueA() {
          this.value.a = new Date().getTime();
        },
        changeValueToughA() {
          this.$set(this.value, "a", new Date().getTime())
        },
        changeValueB() {
          this.value.b = new Date().getTime();
        },
        changeValue() {
          this.value = {
            a: 1,
            b: 2
          };
        }
      }
    })
</script>

如上图所示,执行结果是:

  • 直接点击change a value是无效的。
  • <span style="color: red">先点击change a value无效后,再点击change a value use &dollar;set也会无效。</span>
  • 点击change a value use &dollar;set有效,并且点击过后,点击change a value又有效了
  • 点击change value后,点击change a value又有效了
  • 点击change b value一直有效

大家应该注意以下事项

  • 由于在data下直接定义的对象,添加属性是不会监听的,比如说value.a在data中其实未定义,你只有通过$set的方式通知vue才能够完成属性赋值并更新视图。
  • 如果对定义的对象直接进行属性添加,会导致$set也会失效。
  • 如果本身data下面的对象的属性已经定义了,对于对象属性的变更是能够被监听的,比如说value.b,你可以直接通过修改b的值来更新视图。
  • 最后一个changeValue方法,是对vue data下的直接属性进行修改,是能够被整个监听到,并且更新属于value下所有子属性的视图。

在线demo: https://codepen.io/vvpvvp/pen/XYvxMg?editors=1010

这个主要问题是,我们开发很少用到$set,所以也很少遇到问题,但是新手成员经常干这种事,还一脸懵逼的问题,是不是vue有问题了?

继续,关于如何优化自己的代码,防止出现这种问题,往下看开发注意事项👇👇👇

开发注意事项:

1、data在定义的时候,一定要把相关的数据定义全了。 因为data代表着整个模块的处理逻辑,你在下面使用$set,代码可读性非常不好,更不要说,多了很多莫名其妙的bug。

2、业务对象使用数据模型定义

new Vue({
  el: '#app',
  data: {
    page: {
        page: 1,
        size: 10
    },
    loading: false,
    person: {}
  },
})

如上图所示,一些常规的属性,我们可以定义好,但是类似person这种业务属性,有可能几十个字段,我们不可能全部定义出来吧。

方法: 我们用的是js-model来定义业务数据模型,需要定义业务对象的时候,类似Person.parse({})就可以很好的解决问题了。

大家可以读我写的这一篇文章: 创建前端数据模型,vue开发必备

Basic.js

import Model from "js-model";

let Person = new Model({
    "id": 0,
    "description": "",
    "tags": [ 0 ],
    "companyId": "",
    "rate": {
        type: Number,
        default: 0.8
    },
    "salary": Number
});
export default Basic;
import Basic from './Person.js'
let basic = Person.parse({});

basic:

{
    "id": null,
    "source": null,
    "description": null,
    "tags": [],
    "companyId": null,
    "rate": 0.8, // use default value
    "salary": null
}

实际应用:

new Vue({
  el: '#app',
  data: {
    page: {
        page: 1,
        size: 10
    },
    loading: false,
    person: Person.parse({})
  },
})

<span style="font-size: 30px;">👍</span>

这个问题,先点到为止了,我们再继续往下看。

问题二、v-for循环一定要加key

这个问题折磨了我很久,因为我真的不想加key。

但是在系统开发中,不加key是会死的,而且死的很难看,就算这样,我们公司的代码中,还是有大量没有加key的处理,其实纯粹展示没有太大问题,只是一堆warning很不爽。

我提过一些看起来很不合理的bug,但是尤作者都是以没有加key反驳,所以我现在只能乖乖的加key了。

尤作者回复我的一些摘录:

The last <test-b> belongs to the same parent with the v-for list, but is un-keyed - this makes the list "partially-keyed" and can lead to unexpected behavior.

You are using the index as the key... which is the same as no key at all. You should give each of your data objects a unique id so that they can be keyed properly.

我们来总结一下尤作者的回答:

1、如果 belongs to the same parent 同一种组件属于同一个parent,如果不加key,lead to unexpected behavior 将会产生无法预测的行为

<template>
<div>
    <ComA></ComA>
    <ComA></ComA>
</div>
</template>

注意:所以,以上情况,也属于需要加key的范畴,更不要说是v-for了,不过一般情况下是不会出现问题的,如果你遇到未知的一些展示错误,一般加个key就可以解决(我们之前就遇到过,在渲染一个特别复杂的数据的时候,就是展示不出来,因为结构复杂,以为是代码的问题,调了整整一天,后期发现代码没有问题,加个key就解决了)。

2、You are using the index as the key... which is the same as no key at all
你使用index作为key,其实和没有使用key是一样的

<template>
<div>
    <ComA v-for="(item, index) of list" :key="index"></ComA>
</div>
</template>

注意:以上情况,其实和没有加key是一样的,key必须是根据你的数据对象相关的唯一值,就是如果你不想出现bug,可以用生成的id来替代,但是,这样修改数据的时候,整个list都会重新渲染,感人....
当然,还是建议使用数据中的id来定义key值,最方便也最安全。

在线demo: https://codepen.io/vvpvvp/pen/oZKpgE

操作步骤:

  • 点击添加*3
  • 点击第一行click Me!,变成clicked
  • 点击第二行click Me!,变成clicked
  • 点击删除第一行

发现clicked保留,最后一行的click Me!被删除

如果你为v-for使用时间戳加个key,问题就会解决。

问题三、v-for循环中,如果有数据编辑,一定要使用对象数组

其实这个问题是属于上面一个问题的衍生。

之前我们有一个数据列表,需要编辑,一开始定义的就是[String],可是v-for是需要key的吧,你只能使用String的数据作为key。

<template>
    <div id="app">
      <div v-for="(item,index) of list" :key="item">
        <p>{{item}}</p>
        <input type="text" v-model="item"> 
        <button @click="remove(index)">delete</button>
      </div>
      <button @click="add()">add</button>
    </div>
</template>
<script>
    new Vue({
      el: '#app',
      data: {
        list: []
      },
      methods: {
        add: function() {
          this.list.push("string");
        },
        remove: function(index) {
          this.list.splice(index, 1);
        }
      }
    })
</script>

too young too native

同事问我,为什么input一编辑就blur了,呵呵呵.......

你能想象吗?你改动了一个值,然后你自己被重新渲染了。

但是,我刚刚写了新版本的demo,发现没有这个问题了。

因为新版本直接error了,这样也好,告诉了大家怎么来修改代码,不会让大家一脸懵,input一编辑就blur,你知道是为什么吗?

不过,现在也还是有问题的,就是v-model已经不起作用了,希望大家能注意到error中的说明。

👍解说vue开发过程中的“深坑”,HeyUI组件库开发总结

后记

本期的总结就到这里了,后续还有其他的总结

  • vue2.0 directive如何使用
  • vue v-model 实现机制

最后

希望大家多多支持我们的组件库

HeyUI,🎉UI Toolkit for Web, Vue2.0

http://www.heyui.top

点赞
收藏
评论区
推荐文章
blmius blmius
4年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
美凌格栋栋酱 美凌格栋栋酱
7个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Jacquelyn38 Jacquelyn38
4年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
Wesley13 Wesley13
3年前
FLV文件格式
1.        FLV文件对齐方式FLV文件以大端对齐方式存放多字节整型。如存放数字无符号16位的数字300(0x012C),那么在FLV文件中存放的顺序是:|0x01|0x2C|。如果是无符号32位数字300(0x0000012C),那么在FLV文件中的存放顺序是:|0x00|0x00|0x00|0x01|0x2C。2.  
Easter79 Easter79
3年前
Twitter的分布式自增ID算法snowflake (Java版)
概述分布式系统中,有一些需要使用全局唯一ID的场景,这种时候为了防止ID冲突可以使用36位的UUID,但是UUID有一些缺点,首先他相对比较长,另外UUID一般是无序的。有些时候我们希望能使用一种简单一些的ID,并且希望ID能够按照时间有序生成。而twitter的snowflake解决了这种需求,最初Twitter把存储系统从MySQL迁移
Wesley13 Wesley13
3年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
3年前
PHP创建多级树型结构
<!lang:php<?php$areaarray(array('id'1,'pid'0,'name''中国'),array('id'5,'pid'0,'name''美国'),array('id'2,'pid'1,'name''吉林'),array('id'4,'pid'2,'n
Wesley13 Wesley13
3年前
Java日期时间API系列36
  十二时辰,古代劳动人民把一昼夜划分成十二个时段,每一个时段叫一个时辰。二十四小时和十二时辰对照表:时辰时间24时制子时深夜11:00凌晨01:0023:0001:00丑时上午01:00上午03:0001:0003:00寅时上午03:00上午0
Stella981 Stella981
3年前
Linux日志安全分析技巧
0x00前言我正在整理一个项目,收集和汇总了一些应急响应案例(不断更新中)。GitHub地址:https://github.com/Bypass007/EmergencyResponseNotes本文主要介绍Linux日志分析的技巧,更多详细信息请访问Github地址,欢迎Star。0x01日志简介Lin
Python进阶者 Python进阶者
1年前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这
迭代苔原
迭代苔原
Lv1
没资格吃的醋最酸,先动心的人最惨
文章
4
粉丝
0
获赞
0