Vue实战中的经验总结(不定期更新)

一、服务器尽量返回一维数组

比如,一个商品列表,每个商品又属于不同的大类,甚至又属于不同的小类,可能你的一个选择是,让服务器返回一个二维(甚至三维)数组,但是这里面问题很大,我慢慢说:

二维数组问题很大

  1. goodsList有可能要放在vuex里,因为它会被多个页面调用或者修改。没错吧?

  2. 这个goodsList是个二维(或者三维)数组。没错吧?(下文为简单描述起见,只说是二维数组。)

  3. 列表页UI中,每个商品占一定空间,然后从上到下排列,没错吧?从优化上说,每个商品一定要做一个组件,比如叫goods-item。没错吧?(如果你不同意提炼出子组件,我负责任地说,你根本不懂Vue和虚拟DOM。)

  4. 这时候涉及到向<goods-item>组件传递数据,用于渲染,这时候如果直接传一个对象,比如{goodsId: 323, goodsName: '咸鸭蛋', currnetPrice: 23.5},这里注意,这个对象是非响应式的,虽然只用于渲染是足够了,但是,如果要修改数据,比如修改saleVolume(即购买量),那么显然,直接修改是非响应式的。没错吧?所以还是要去vuex里修改。

  5. 那么,修改vuex的state,必然只能使用mutation(或者action),所以这就需要调用mutation(或Action),还要给它传递到底修改哪个商品,以及修改成多少,所以我们就要先在goodsList里定位这个商品,然后再修改这个商品。怎么定位呢?你需要根据categoryId和goodsId,先外循环category列表,再内循环goods列表,结果只为修改一个saleVolume,这很蠢,对吧?

那么应该怎么做?

goodsList

服务器返回一维数组,叫goodsList,存入state里。这个goodsList必须至少有categoryId字段。

categoryList
选择一:服务器直接发送

categoryList可以由服务器直接发送,形式是:

    [
      {
        categoryId: 1,
        categoryName: '糕点坊',
        goodsList: [], // 原始数据里没有这个字段,需要拿到数据之后本地JS给加上空数组
      },
      {
        categoryId: 2,
        categoryName: '炒货铺',
        goodsList: [], // 原始数据里没有这个字段,需要拿到数据之后本地JS给加上空数组
      },
    ]

计算categoryList里每一个category的goodsList,把每一个goods分别push进去,就OK了!

选择二:本地计算

我们也可以本地计算,本地计算的话,goodsList里就必须带足够多的category的信息,比如至少有categoryName字段。

在vuex中新建一个getter叫categoryList,由state.goodsList计算categoryList,这是一个由一维数组变成二维数组的过程。计算细节就不多说了。

最终我们有一个一维的goodsList,和一个二维的categoryList,它每项有一个键是goodsList,用于存放自己的所有goods。

两套数据有什么好处?

  1. 一维的goodsList用于vuex修改数据,修改数据的时候只需要向mutation传递该goods在整个数组的下标即可,根本不用传递goodsId,因为很显然,用下标定位数组元素是最方便也是最快的。对吧?

  2. 一维的goodsList也可以用于渲染一些定制化的列表,比如搜索结果,搜索结果里通常不需要按照category分类。如果真的需要按照category分类,你还有一个categoryList可以用,对吧?

  3. 如果你真的需要二维数组去渲染UI,而且还要数组内容能修改,那么,在刚请求到一维goodsList的时候,就给每个goods加上个index属性。将来修改数据的时候,依然只需要给vuex传入下标就行了。

总之,想修改数据,就传下标,想渲染数据,我有一维和二维两套数据,你随便用,这样还有问题吗?并且,后端的操作也简化,毕竟后端不用先计算二维数组,你也不用跟后端约定数据结构,对不对?

二、不要把vuex的getter当做state的影分身

包括一些牛人的开源代码中,依然可以见到这样的代码:

export default {
  state: {
    a: 1,
  },
  getter: {
    a: (state) => state.a,
  }
}

然后getter可能会写出几十个,全是state的影分身,全是x: (state) => state.x这种写法。调用都是mapGetters。胡闹么这不是?不用mapState留着下崽?

官方文档对getter说的很清楚:

有时候我们需要从 store 中的 state 中派生出一些状态。

Vuex 允许我们在 store 中定义“getter”(可以认为是 store 的计算属性)。就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来,且只有当它的依赖值发生了改变才会被重新计算。

所以:

  1. 不要做影分身!state原则上跟getter不要有重复,除非有某种必要。

  2. getter要发挥“监听”的特点,比如说,某商品的saleVolume发生了变化,它会影响一系列的数据,比如购物车数量、购物车总价、是否达到起送价(如果是外卖APP的话),等等,那么怎么做?购物车数量我应该设为一个getter,同理,购物车总价我设为getter,是否达到起送价我设为getter,全部由goodsList开始计算,当goodsList发生了变化,这些计算属性全都会重新计算。
    如果不设为getter,只设为state,那么我们就只能写面向过程的代码,也就是,修改saleVolume的语句下面要跟上一大串的计算购物车数量、购物车总价、是否达到起送价的代码,是不是很蠢?

  3. 影分身的省事的地方在于只用写mapGetters,不用写mapState。我只能说,请别偷懒,偷懒不是这么偷的。state是有mutation操作的数据,getters是不会被直接操作的数据,区别很大,不要混淆!

三、用户触发的事件回调函数应使用onClick...、onChange...这类方法名

一个Vue实例方法,通常有2种用途:

  1. 作为用户事件的回调

用户事件的回调,比如点击按钮,播放视频,那么,我在元素上绑定的事件就可以叫onClickPlayButton

  1. 作为业务逻辑的一部分

点击播放按钮,当然是播放视频,那么我就可以定义一个方法叫playVideo

OK,这里有个问题是,为何用途1函数名不叫playVideo

这就是我的用意:

  • 事件驱动,用onClick打头,类似onClickPlayButton这种

  • 业务驱动,用play这种写法,类似playVideo这种

原因:

这符合“一个函数只做一件事”的原则,我点击按钮,可能除了播放本视频外还要干别的,比如记录日志,比如暂停其他的视频,等等。因此,playVideo可能是事件回调的全部逻辑,又可能是onClickPlayButton的一部分逻辑。

题外话:

你可能会说“千篇一律用onClick很烦”。但是浏览器事件可不只是click事件,原生事件就不知道有多少,再加上自定义事件就多了去了,代码写多了你就发现这种写法的优势。

四、props接收的数据如果需要修改,且没必要告诉父组件,则可以深克隆一份

父组件传给子组件的复杂数据类型,也就是数组和对象,往往需要在子组件中进行修改,并且,这种修改不需要告诉父组件。比如一个可视化图表组件,你传入的数据不符合图表需要的数据格式,那么图表组件就需要把数据加工一下,这种加工并不需要反馈给父组件,此时就可以把数据深克隆一份,赋值给data,然后想怎么改就怎么改就好了。

首先,图表组件默认是不初始化的,因为需要等待传入数据,而数据一般来说需要ajax,所以一般会使用监听,监听props。

然后,一旦监听到,就this.xxx = JSON.parse(JSON.stringify(newVal));,然后对xxx一通修改,最后执行图表初始化命令就行了。

五、如何科学的合并data中的Object数据

合并Object我们使用Object.assign(),现在假设this.form{},ajax了一套数据,准备合并到this.form

错误用法

Object.assign(this.form, response.data);

这会将this.form由响应式变成非响应式。同样的,这样也不行:

this.form = Object.assign(this.form, response.data);

正确用法

this.form = Object.assign({}, this.form, response.data);

这里面注意数据覆盖问题,覆盖原则一句话说就是:重名属性,以最后的包含该属性的对象为准。

另外,还有更骚的方法是:

this.form = {...this.form, ...response.data};

六、v-for的:key到底用id还是index

当我们在使用v-for进行渲染时,尽可能使用渲染元素自身属性的id给渲染的元素绑定一个key值,这样在当前渲染元素的DOM结构发生变化时,能够单独响应该元素而不触发所有元素的渲染。

实在没有id的时候,应考察item是否有其他的唯一属性,比如item.name,如果有,也可以用。

如果item本身是数字或者字符串,如果你确定item值是唯一的,也可以拿item本身当做:key。

最下策是用index。

七、在某生命周期监听另外生命周期

比如想在mounted监听beforeMounted周期的发生,怎么做?

mounted() {
    this.$once('hook:beforeDestroy', () => {
      // ...
    })
  },

八、组件外监听组件内部生命周期

举个例子,一个组件是第三方的,没提供数据变化的钩子,你也不知道组件内什么时候发生了data变化,但是业务需要得知什么时候组件有数据变化,怎么办?

可以通过@hook:updated监听组件的updated生命钩子函数。事实上,组件的所有生命周期钩子都可以通过@hook:钩子函数名来监听触发,只不过用的最多的还是@hook:updated。比如:

<template>
  <custom-select @hook:updated="xx自定义事件名" />
</template>

九、

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,295评论 6 512
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,928评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,682评论 0 357
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,209评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,237评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,965评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,586评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,487评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,016评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,136评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,271评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,948评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,619评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,139评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,252评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,598评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,267评论 2 358

推荐阅读更多精彩内容