Vue的编码技巧与规范使用详解


Posted in Javascript onAugust 28, 2019

当我们完成项目的构建,进入开发阶段的时候,除了你需要了解框架本身的知识点外,我们还需要提前掌握一些项目的编码技巧与规范,在根源上解决之后因编码缺陷而导致的项目维护困难、性能下降等常见问题,为项目多人开发提供编码的一致性。

本文将罗列项目中常用的一些编码技巧与规范来帮助大家提升代码质量,并会结合代码片段加强大家的理解与认知。当然不是所有实例都是针对 Vue.js 开发的,有些同样也适用于其他前端项目。

实例

1. 使用对象代替 if 及 switch

在很多情况下,我们经常会遇到循环判断执行赋值操作的场景,一般我们都会使用 if 及 switch 的条件判断,如果符合则执行赋值,不符合则进入下个判断,比如:

let name = 'lisi';
let age = 18;

if (name === 'zhangsan') {
 age = 21;
} else if (name === 'lisi') {
 age = 18;
} else if (name === 'wangwu') {
 age = 12;
}

// 或者
switch(name) {
 case 'zhangsan':
  age = 21;
  break
 case 'lisi':
  age = 18;
  break
 case 'wangwu':
  age = 12;
  break
}

这样的写法不仅冗余,而且代码执行效率不高,我们可以使用对象的形式简写:

let name = 'lisi';
let obj = {
 zhangsan: 21,
 lisi: 18,
 wangwu: 12
};

let age = obj[name] || 18;

以上这种技巧适用于循环判断一次赋值的情况,如果判断过后有较多处理逻辑的还需要使用 if 或 switch 等方法。

2. 使用 Array.from 快速生成数组

一般我们生成一个有规律的数组会使用循环插入的方法,比如使用时间选择插件时,我们可能需要将小时数存放在数组中:

let hours = [];

for (let i = 0; i < 24; i++) {
 hours.push(i + '时');
}

如果使用 Array.from 我们可以简写为:

let hours = Array.from({ length: 24 }, (value, index) => index + '时');

3. 使用 router.beforeEach 来处理跳转前逻辑

在某些情况下,我们需要在路由跳转前处理一些特定的业务逻辑,比如修改路由跳转、设置 title 等,代码如下:

import Vue from 'vue'
import Router from 'vue-router'

Vue.use(Router)

// 首页
const Home = (resolve => {
 require.ensure(['../views/home.vue'], () => {
  resolve(require('../views/home.vue'))
 })
})

let base = `${process.env.BASE_URL}`;

let router = new Router({
 mode: 'history',
 base: base,
 routes: [
  {
   path: '/',
   name: 'home',
   component: Home,
   meta: { title: '首页' }
  },
 ]
})

router.beforeEach((to, from, next) => {
 let title = to.meta && to.meta.title;
 
 if (title) {
  document.title = title; // 设置页面 title
 }
 
 if (to.name === 'home') {
 
  // 拦截并跳转至 page2 单页,$openRouter 方法在第 5 节中封装
  Vue.$openRouter({
   name: 'page2'
  });
 }
 
 next();
})

export default router

注意最后需要调用 next() 方法执行路由跳转。

4. 使用 v-if 来优化页面加载

在 Vue 页面中,一些模块可能需要用户主动触发才会显示,比如弹框组件等这样的子组件,那么我们可以使用 v-if 来进行按需渲染,没必要一进页面就渲染所有模块。比如:

<template>
 <div @click="showModuleB = true"></div>
 <module-b v-if="isShowModuleB"></module-b>
</template>

<script>
import moduleB from 'components/moduleB'
export default {
 data() {
  return {
   isShowModuleB: false
  } 
 },
 components: {
  moduleB
 }
}
</script>

这样当 isShowModuleB 为 false 的时候便不会加载该模块下的代码,包括一些耗时的接口调用。当然 v-if 主要适用于代码量较多、用户点击不是很频繁的模块的显示隐藏,同时如果涉及到权限问题的代码都需要使用 v-if,而不是 v-show。

5. 路由跳转尽量使用 name 而不是 path

我们前期配置的路由路径后期难免会进行修改,如果我们页面跳转的地方全是使用的 path,那么我们需要修改所有涉及该 path 的页面,这样不利于项目的维护。而相对于 path,name 使用起来就方便多了,因为其具有唯一性,即使我们修改了 path,还可以使用原来的 name 值进行跳转。

this.$router.push({ 
 name: 'page1'
});

// 而不是
this.$router.push({ 
 path: 'page1'
});

6. 使用 key 来优化 v-for 循环

v-for 是 Vue 提供的基于源数据多次渲染元素或模板块的指令。正因为是数据驱动,所以在修改列表数据的时候,Vue 内部会根据 key 值去判断某个值是否被修改,其会重新渲染修改后的值,否则复用之前的元素。

这里如果数据中存在唯一表示 id,则推荐使用 id 作为 key,如果没有则可以使用数组的下标 index 作为 key。因为如果在数组中间插入值,其之后的 index 会发生改变,即使数据没变 Vue 也会进行重新渲染,所以最好的办法是使用数组中不会变化且唯一的那一项作为 key 值。例如:

<template>
 <ul>
  <li v-for="(item, index) in arr" :key="item.id">{{ item.data }}</li>
 </ul>
</template>

<script>
export default {
 data() {
  return {
   arr: [
    {
     id: 1,
     data: 'a'
    },
    {
     id: 2,
     data: 'b'
    },
    {
     id: 3,
     data: 'c'
    }
   ]
  }
 }
}
</script>

7. 使用 computed 代替 watch

很多时候页面会出现 watch 的滥用而导致一系列问题的产生,而通常更好的办法是使用 computed 属性,首先需要区别它们有什么区别:

  • watch:当监测的属性变化时会自动执行对应的回调函数
  • computed:计算的属性只有在它的相关依赖发生改变时才会重新求值

其实它们在功能上还是有所区别的,但是有时候可以实现同样的效果,而 computed 会更胜一筹,比如:

<template>
 <div>
  <input type="text" v-model="firstName">
  <input type="text" v-model="lastName">
  <span>{{ fullName }}</span>
  <span>{{ fullName2 }}</span>
 </div>
</template>

<script>
export default {
 data() {
  reurn {
   firstName: '',
   lastName: '',
   fullName2: ''
  }
 },
 
 // 使用 computed
 computed: {
  fullName() {
   return this.firstName + ' ' + this.lastName
  }
 },
 
 // 使用 watch
 watch: {
  firstName: function(newVal, oldVal) {
   this.fullName2 = newVal + ' ' + this.lastName;
  },
  lastName: function(newVal, oldVal) {
   this.fullName2 = this.firstName + ' ' + newVal;
  },
 }
}
</script>

上方我们通过对比可以看到,在处理多数据联动的情况下,使用 computed 会更加合理一点。

Vue的编码技巧与规范使用详解

computed 监测的是依赖值,依赖值不变的情况下其会直接读取缓存进行复用,变化的情况下才会重新计算;而 watch 监测的是属性值, 只要属性值发生变化,其都会触发执行回调函数来执行一系列操作。

8. 统一管理缓存变量

在项目中或多或少会使用浏览器缓存,比如 sessionStorage 和 localStorage,当一个项目中存在很多这样的缓存存取情况的时候就会变得难以维护和管理,因为其就像全局变量一样散落在项目的各个地方,这时候我们应该将这些变量统一管理起来,放到一个或多个文件中去,比如:

/* types.js */

export const USER_NAME = 'userName';
export const TOKEN = 'token';

在需要存取的时候,直接引用:

import { USER_NAME, TOKEN } from '../types.js'

sessionStorage[USER_NAME] = '张三';
localStorage[TOKEN] = 'xxx';

使用这种方法的好处在于一旦我们需要修改变量名,直接修改管理文件中的值即可,无需修改使用它的页面,同时这也可以避免命名冲突等问题的出现,这类似于 vuex 中 mutations 变量的管理。

9. 使用 setTimeout 代替 setInterval

一般情况下我们在项目里不建议使用 setInterval,因为其会存在代码的执行间隔比预期小以及 “丢帧” 的现象,原因在于其本身的实现逻辑。很多人会认为 setInterval 中第二个时间参数的作用是经过该毫秒数执行回调方法,其实不然,其真正的作用是经过该毫秒数将回调方法放置到队列中去,但是如果队列中存在正在执行的方法,其会等待之前的方法完毕再执行,如果存在还未执行的代码实例,其不会插入到队列中去,也就产生了 “丢帧”。

而 setTimeout 并不会出现这样的现象,因为每一次调用都会产生了一个新定时器,同时在前一个定时器代码执行完之前,不会向队列插入新的定时器代码。

// 该定时器实际会在 3s 后立即触发下一次回调
setInterval(() => {
 // 执行完这里的代码需要 2s
}, 1000);

// 使用 setTimeout 改写,4秒后触发下一次回调
let doSometing = () => {
 // 执行完这里的代码需要 2s
 
 setTimeout(doSometing, 1000);
}

doSometing();

延伸阅读:对于“不用setInterval,用setTimeout”的理解

10. 不要使用 for in 循环来遍历数组

大家应该都知道 for in 循环是用于遍历对象的,但它可以用来遍历数组吗?答案是可以的,因为数组在某种意义上也是对象,但是如果用其遍历数组会存在一些隐患:其会遍历数组原型链上的属性。

let arr = [1, 2];

for (let key in arr) {
 console.log(arr[key]); // 会正常打印 1, 2
}

// 但是如果在 Array 原型链上添加一个方法
Array.prototype.test = function() {};

for (let key in arr) {
 console.log(arr[key]); // 此时会打印 1, 2, ƒ () {}
}

因为我们不能保证项目代码中不会对数组原型链进行操作,也不能保证引入的第三方库不对其进行操作,所以不要使用 for in 循环来遍历数组。

结语

本文罗列了 10 个项目开发中常见的编码技巧与规范,其实技巧和规范之间本身就是相辅相成的,所以没有分别进行罗列。当然实际的项目开发中存在着很多这样的例子需要大家自己去归纳和整理,比如使用 name 来命名你的组件等。如果你有不错的点子,也可以分享在下方的评论区域中供大家学习。

拓展阅读:前端各类规范集合

思考 & 作业

  • 可以使用哪些技巧来实现数组的循环遍历、去重等?
  • 在 Vue 项目中如何使用 ESLint 来规范 JS 代码的编写?
  • .vue 单文件组件中如何进行代码的格式化?

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
javascript中的继承实例代码
Apr 27 Javascript
js实现运动logo图片效果及运动元素对象sportBox使用方法
Dec 25 Javascript
IE6/IE7中JavaScript json提示缺少标识符、字符串或数字问题处理
Dec 16 Javascript
jQuery中ajax的load()方法用法实例
Dec 26 Javascript
assert()函数用法总结(推荐)
Jan 25 Javascript
JavaScript实现分页效果
Mar 28 Javascript
Vue键盘事件用法总结
Apr 18 Javascript
js绑定事件和解绑事件
Apr 27 Javascript
Vue之Watcher源码解析(1)
Jul 19 Javascript
JS document form表单元素操作完整示例
Jan 13 Javascript
JavaScript实现简单计算器
Mar 19 Javascript
vue配置多代理服务接口地址操作
Sep 08 Javascript
JS开发自己的类库实例分析
Aug 28 #Javascript
详解Vue 换肤方案验证
Aug 28 #Javascript
Vue项目实现换肤功能的一种方案分析
Aug 28 #Javascript
js遍历详解(forEach, map, for, for...in, for...of)
Aug 28 #Javascript
Angular6使用forRoot() 注册单一实例服务问题
Aug 27 #Javascript
jQuery - AJAX load() 实例用法详解
Aug 27 #jQuery
JS实现提示框跟随鼠标移动
Aug 27 #Javascript
You might like
PHP 开发环境配置(测试开发环境)
2010/04/28 PHP
在PHP中养成7个面向对象的好习惯
2010/07/17 PHP
解析PHP自带的进位制之间的转换函数
2013/06/08 PHP
PHP两种去掉数组重复值的方法比较
2014/06/19 PHP
PHP制作图形验证码代码分享
2014/10/23 PHP
laravel 中某一字段自增、自减的例子
2019/10/11 PHP
js 多种变量定义(对象直接量,数组直接量和函数直接量)
2010/05/24 Javascript
JS实现带缓冲效果打开、关闭、移动一个层的方法
2015/05/09 Javascript
JavaScript记录光标在编辑器中位置的实现方法
2016/04/22 Javascript
JS弹出窗口的运用与技巧大全
2016/11/01 Javascript
jquery获取input type=text中的值的各种方式(总结)
2016/12/02 Javascript
用jQuery实现优酷首页轮播图
2017/01/09 Javascript
js实现不提示直接关闭网页窗口
2017/03/30 Javascript
Vue项目webpack打包部署到服务器的实例详解
2017/07/17 Javascript
微信小程序实践之动态控制组件的显示/隐藏功能
2018/07/18 Javascript
Vue.js 中的 v-cloak 指令及使用详解
2018/11/19 Javascript
详解js根据百度地图提供经纬度计算两点距离
2019/05/13 Javascript
在Python中操作文件之read()方法的使用教程
2015/05/24 Python
Python利用matplotlib生成图片背景及图例透明的效果
2017/04/27 Python
Python语言描述随机梯度下降法
2018/01/04 Python
利用python库在局域网内传输文件的方法
2018/06/04 Python
Django教程笔记之中间件middleware详解
2018/08/01 Python
python调用百度语音REST API
2018/08/30 Python
Python类及获取对象属性方法解析
2020/06/15 Python
Python执行时间的几种计算方法
2020/07/31 Python
python opencv角点检测连线功能的实现代码
2020/11/24 Python
python3.7中安装paddleocr及paddlepaddle包的多种方法
2020/11/27 Python
HTML实现代码雨源码及效果示例
2020/02/25 HTML / CSS
党校学习思想汇报
2014/01/06 职场文书
禁毒宣传标语
2014/06/19 职场文书
我爱祖国演讲稿
2014/09/02 职场文书
2016年暑期教师培训心得体会
2016/01/09 职场文书
高三英语教学反思
2016/03/03 职场文书
2016年禁毒宣传活动总结
2016/04/05 职场文书
2019年学校消防安全责任书(2篇)
2019/10/09 职场文书
python DataFrame中stack()方法、unstack()方法和pivot()方法浅析
2022/04/06 Python