看到赚到!重读vue2.0风格指南,我整理了这些关键规则

又是一个阳光明媚,风和日丽的周末,有人陪女神去逛街,有人陪女神去看电影,小编却默默的拿出电脑。哈哈哈,不是小编屌丝,女神正坐在旁边玩手机(感觉不是屌丝才怪)。

这两天小编重读了一遍vue2.0官网的风格指南,整理了这九条关键规则。

v-for设置键值

提到v-for需要设置键值,许多人第一反应会从diff算法的角度去讲原因,我更喜欢举一个例子来演示一下原因

假设有这样的一个页面,页面的列表是通过遍历数组得来的,如下图所示

示例图片

示例代码如下

<!--模板部分-->
<div id="app">
    <div v-for="item in arr">
        {{item}}
        <input/>
    </div>

    <button @click="deleteData">删除第二个元素</button>
</div>
// js 部分
new Vue({
    el: '#app',
    data() {
        return {
            arr: [1,2,3]
        }
    },
    methods:{
        deleteData() {
            this.arr.splice(1,1)
        }
    }
})

现在需要删除第二个元素。下面我们分别在渲染列表是 不使用key,使用索引作为key, 使用唯一值id作为key,看三种场景删除第二个元素之后的效果


可以看到,不使用key,删除第二个元素之后,输入框前面的数字显示正确的,但是数字3后面的输入框的内容显示错了,应该显示 我是第三个

  • v-for 使用索引作为key 点击查看代码演示

    可以看到,使用索引作为key之后,与不使用key的效果一样,删除第二个元素之后,输入框前面的数字显示正确的,但是数字3后面的输入框的内容显示错了,应该显示 我是第三个
  • v-for 使用唯一值id作为key 点击查看代码演示

使用id作为key,显示正确

为什么v-for需要设置key,原因很简单。
对比数组 [1,2,3]和[1,3],我们很容易发现删掉了2,但是计算机不是这样的逻辑

  1. 计算机对比新旧数组,发现1===1,保持不变
  2. 然后再对比2,发现2变成了3,那么就把2修改为3,原来第二行的元素都可以复用,只把数字改一下就可以了
  3. 然后在对比3与undefined,发现3被删了,索引把第三行的元素删掉

那么为什么不能用索引作为key呢?
当删掉[1,2,3]中的2之后,数组的长度由3变成了2,那么原来数字3的索引就变成了数字2的索引了。

  1. 计算机对比key为0的值,发现都是1,保持不变
  2. 计算机对比key为1的值,发现从2变成了3,元素复用, 修改元素上面的文字
  3. 计算机对比key为2的值,发现被删掉了,所以删掉第三行元素

而对于使用id作为key,那么每条数据都有了唯一的标识,当删掉[{id:'1',value: 1},{id: '2',value: 2}, {id: '3', value:3}]中的第二个,整个过程如下

  1. 计算机取出新数据第一项的id,然后在原来数据里面寻找,发现存在相同id的数据,而且数据没有变化,所以保持不变
  2. 计算机继续取第二项的id,发现是3,然后从原来数据里面也找到了3,所以3保留
  3. 这时候旧数据里面剩了id为2的数据,而新的里面没有了,所以删掉。

没得问题嘛!!!!

模板中的复杂逻辑使用计算属性代替

vue在模板可以使用表达式是非常方便的,但表达式在设计之初是为了进行简单逻辑处理的,如果在模板中使用太多或太复杂的逻辑,会让模板的可读性和可维护性变得很差,整个模板显得很臃肿。

B a d \color{red}{Bad} Bad

<!--v-if使用了一连串的条件判断,可读性比较差-->
 <button
    v-if="
      user.roles &&
        user.roles.includes('Workflowbeheer') &&
        data.userId === user.id &&
        data.status === 1
    "
  >
    删除
  </button>

G o o d \color{green}{Good} Good

<template>
  <button v-if="deletable">
    删除
  </button>
</template>
<script>
export default {
  computed: {
    // 判断是否可以删除
    deletable() {
      const { data, user } = this
      // 如果当前用户不是流程管理员,则不能编辑
      if (user.roles && user.roles.includes('Workflowbeheer')) {
        // 如果当前用户为流程发起者且状态为未启动,则可以删除
        return data.userId === user.id && data.status === 1
      }
      return false
    }
  }
}
</script>

避免v-for与v-if混用

永 远 不 要 将 v − f o r 和 v − i f 同 时 用 在 同 一 个 元 素 上 。 \color{red}{永远不要将v-for和v-if同时用在同一个元素上。} vforvif

在开发vue项目中,大家可能会遇到这样的代码

 <ul>
    <li v-for="item in list" v-if="item.visible" :key="item.id">
        {{ item.name }}
    </li>
 </ul>

如果在项目中启用了eslint,则可能会看到下面这样的异常提示(需要启用eslint vue/no-use-v-if-with-v-for 规则)

The 'list' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'.

在vue处理指令的时候,v-forv-if会有更高的优先级,那么上述的代码用js可以模拟为

list.map(item => {
    if(item.visible) {
        return item.name
    }
})

通过上述代码可以看到,即使大部分数据的visible都是false,也会将整个list全部遍历一次。如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候。

对于上述的问题,可以使用计算属性来处理

 <ul>
    <li v-for="item in getList" :key="item.id">
        {{ item.name }}
    </li>
 </ul>
 
 computed: {
    getList() {
      return this.list.filter(item => {
        return item.visible
      })
    }
  }

通过上述的代码,我们可以获得以下好处

  • 过滤后的列表只会在 list 数组发生相关变化时才被重新运算,过滤更高效。
  • 使用 v-for=“item in list” 之后,我们在渲染的时候只遍历需要显示的数据,渲染更高效。
  • 解耦渲染层的逻辑,可维护性比较高。

尽量使用私有属性/方法

在开发vue组件的时候,我们可以通过组件的ref来调用组件对外提供的方法,但是一个组件内部有些方法是内部私有的,不应该被外部调用,但实际上js中并没有像其他语言一样有私有方法(比如javaprivate),所以在js中一般约定使用_开头的属性或者方法表示私有的。

 {
    // 公共的
    selectRows(rows) {},
    // 私有的 外部虽然可以调用到,但是因为是`_`开头,所以按照约定不应该去调用
    _select(rows){}
 }

在vue中定义私有属性/方法又与js常规约定有所不同。在Vue内部,已经使用了_开头去定义Vue原型上面的私有属性/方法,如果在组件内上面继续使用_开头去定义私有属性/方法可能会出现覆盖实例上面属性/方法的情况,比如下面这种情况:

methods: {
    // 初始化组件的数据方法
  _init() {
    fetch().then(data => {
      
    })
  }
}

上面的代码看似没有问题,实际上运行的时候会报错,因为_init方法会覆盖Vue.prototype上面的同名方法,如下图为Vue原型链的方法,第一个便是_init

在Vue2.0风格指南中,建议使用$_来定义私有方法,可以确保不会和Vue自身发生冲突。修改上例为

methods: {
    // 初始化组件的数据方法
  $_init() {
    fetch().then(data => {
      
    })
  }
}

组件数据必须是一个函数,并返回一个对象

在说为什么组件的数据必须返回一个函数之前,我们先来了解一下js中的基本类型与引用类型。

  1. 基本类型

在es2020发布了bigint类型之后,js中的基本类型一种包含七种,分别是

  • string 字符类型
  • number 数值类型
  • boolean 布尔类型
  • undefined
  • null
  • Symbol
  • Bigint

基本类型的特点包括

  • 基本类型的值是存放到栈内存里面的
  • 基本类型的比较是它们的值的比较
  • 基本类型的值是不可变的,对值的修改会在栈内存中开辟新的空间
  • 基本类型上面不能挂载新的属性
let a = 2
let b = a
// 对a的值的修改,会在栈内存开辟新的空间,所以不会影响到b的值
a = 3
// 输出 3 2
console.log(a,b)

// 不能给基本类型上面挂载新的属性
a.testProp = '挂载的属性'
// 输出undefined
console.log(a.testProp)
  1. 引用类型
    在js中,除了八种基本类型,其他都属于引用类型,像Object,Array,Function,RegExp,Date等等

引用类型的特点包括

  • 引用类型的值保存在堆内存中,而引用保存到栈内存中
  • 引用类型的值是按引用访问的
  • 引用类型的值是可变的(在堆内存中直接修改)
  • 引用类型上面可以挂载新的属性
let obj1 = {a: 1, b: 2}
let obj2 = obj1
// 因为引用类型的值是保存到堆内存的,obj1与obj2引用的是同一块堆内存空间,所以对obj1的值进行
// 修改,会直接影响到obj2的值
obj1.a = 3
// 输出 3
console.log(obj2.a)

// 挂载新的属性
obj1.testProp = '挂载的新属性值'
// 输出 "挂载的新属性值"
console.log(obj1.testProp)

通过上面的对比,我想大家其实也清楚了为什么vue的数据必须返回一个函数了。

假设我们现在开发了一个组件,组件上面的data是一个普通的对象,那么当我们实例化多个组件的时候,所有的实例将共享引用同一个数据对象,任何一个实例对数据的修改都会影响到其他实例。而将组件上面的数据定义为一个函数之后,当实例化多个组件的时候,每个实例通过调用 data 函数,从而返回初始数据的一个全新副本数据对象,这时候就避免了对象引用。

为组件样式设置作用域

在前端发展日新月异的今天,所有的一切都在飞速的发展,前端项目规模越来越大,而css作为一个只有全局作用域的语言,样式冲突会带来很多麻烦。JS语言模块已经标准化,CSS还是在不断探索,同时这也是一个急需解决的问题。现在人们提出了许多为css添加作用域的解决方法,比如BEM样式规范,比如css module。

在Vue中,使用了通过给元素添加scoped attribute的方式为css添加作用域,具体代码如下

<template>
  <button class="button">按钮</button>
</template>
<!--给style标签添加scoped属性-->
<style scoped>
.button {
  width: 50px;
  height: 40px;
}
</style>

编译之后的结果如下

<!--html 添加了一个新属性 data-v-039c5b43,对于组件内的所有元素,都会添加同一个属性data-v-039c5b43,这样保证了同一个组件内所有元素都在同一个作用域内-->
<button data-v-039c5b43="" class="button">按钮</button>
/*通过为样式添加属性选择器,去限制样式的作用域*/
.button[data-v-039c5b43] {
    width: 50px;
    height: 40px;
}

虽然我们建议为组件样式添加作用域,但是不一定必须使用vue提供的attribute scoped,对于组件库之类可能需要在外部覆盖样式,如果使用attribute scoped,因为属性名不确定,且样式权重较高,导致样式覆盖很困难.

这时候更建议使用类似BEM之类的命名规范来约束,这让覆写内部样式更容易,使用了常人可理解的 class 名称且没有太高的选择器优先级,而且不太会导致冲突。比如element ui 和 vant 均使用了BEM

将复杂页面拆分成多个多个组件文件

你有没有见过一个Vue文件里面有一大坨密密麻麻的模板代码,模板代码里面还加载了大量的v-if,v-for,v-show之类的指令,我不知道你看到之后感觉怎么样,对于小编来说,这无疑是地狱,各种逻辑耦合到一起,改bug比蜀道还要难
对于一个复杂的页面,我们建议将页面按照模块/功能进行拆分,然后写成多个小的,单一的组件,然后在主入口文件中引用。比如,对于一个复杂的页面,我们可以拆分成

header.vue main.vue footer.vue

三个文件,然后在三个文件内完成各自的逻辑,最后通过将三个组件都引入主入口文件,来实现页面的拼装。
这样做的好处包括

  • 将复杂的逻辑进行解耦,代码结构更清晰,逻辑更简单,可读性更强
  • 对功能进行组件化抽取抽象,组件复用变得更简单
  • 便于多人协作开发,不同的人可以同时开发一个复杂的页面

prop应该尽量详细

对比下面的两段代码

// 第一段
export default {
  props:['status','data']
}
// 第二段
export default {
  props:{
    status: {
      type: Boolean,
      default: true
    },
    data:{
      type: Array,
      required: true
    }
  }
}

对比上面两段代码,通过第二段代码我们可以很清楚的知道组件需要什么属性,属性的类型是什么,默认值是什么,是否是必须的,这样做的好处包括:

  • 详细的定义了属性的各方面信息,所以很容易看懂组件的用法;
  • 在开发环境下,如果向一个组件提供格式不正确的 prop,Vue将会得到警告,可以更快的发现潜在的问题。

组件名应该由多个单词组成

对于组件名应该由多个单词组成的必要性,我想到了自己曾经见过的一段代码

<header class="header">
    <!--栏目-->
    <ul>
      <li>首页</li>
      <li>关于</li>
    </ul>
</header>

看到这段代码,然后感觉很正常,没啥毛病,然后我看了一眼界面,诶,为什么header左侧有一个logo呢?我笑着说,这一定是样式里面加的咯,然后看了一眼样式,wtf,什么鬼,样式里面也没有加啊,这是怎么做到的,好神奇。后来就看到了这样的一段代码

import Header from '@/components/header'
export default {
    components: {
        Header
    }
}

我的四十米长大砍刀呢!!!!!!

为什么组件名应该又多个单词组成,因为这样做可以避免跟现有的以及未来的 HTML 元素相冲突。更关键的是,这样做不会被打,当然你也可以做,祝你好运,(手动调皮)。

本文主要参考了:

https://cn.vuejs.org/v2/style-guide/

https://juejin.im/post/5edcc259f265da76d9261a20?utm_source=gold_browser_extension

感谢作者,如侵权立即删除。如果您觉得本文对您有帮助,希望您可以给小编一个赞,不胜感激。小手一赞,艳遇不断,哈哈哈哈哈

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Vue 3.0是Vue.js框架的最新版本,与Vue 2.0相比有一些重要的改进和变化。要将Vue 2.0项目迁移到Vue 3.0,需要进行以下步骤: 1. 更新依赖项:首先,需要将项目中的Vue.js依赖项更新为最新的3.0版本。这包括Vue核心库以及其他可能使用的Vue插件或扩展。 2. 代码适配:Vue 3.0引入了一些新的语法和API,与Vue 2.0有一些不兼容的变化。因此,需要对项目中的代码进行适配。例如,Vue 3.0使用了新的Composition API,可以取代2.0版本中的Options API,需要对组件进行适配以使用新的API。另外,一些特性,如slot和transition,也有一些变化,需要根据Vue 3.0的文档进行修改。 3. 构建工具更新:Vue 3.0对应的构建工具也有所改变。如果你的项目使用了Vue CLI或其他构建工具,需要将它们更新为最新的版本以支持Vue 3.0。 4. 运行测试:完成代码适配后,需要进行测试以确保项目在Vue 3.0下能够正常运行。可以使用Vue官方提供的测试工具或其他适用的测试框架进行测试。 5. 性能优化:Vue 3.0在性能方面进行了一些改进,因此可以考虑对项目进行性能优化。这包括使用新的编译优化、按需引入和缓存等。 总之,迁移到Vue 3.0需要更新依赖项、适配代码、更新构建工具、进行测试和性能优化等步骤。通过认真阅读Vue 3.0的文档和指南,并根据项目的具体情况进行相应的修改和调整,可以顺利完成迁移过程。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值