【Vue】从实际开发出发,浅谈vue的最佳实践

前言

我从接触 Vue 框架,到开发实战,再到深入学习源码思想,至今已有4年的时间。今天主要从实际开发出发,通过“编码风格、性能、安全”3个方面来聊聊 Vue的最佳实践!

参考官网:cn.vuejs.org/v2/style-gu…

image.png

编码风格

平时开发编码时,我们需要多注意提升代码可读性。因为同一个项目可能有多个开发童鞋在维护,挖坑太多会被吐槽哦~

下面我根据官网再结合实战开发总结了几个好的编码风格:

  1. 命名组件时用多个单词,避免跟现有及未来的 HTML 元素相冲突
  2. prop 属性定义应尽量详细,至少要指定类型
// 好例子
props: {
  status: String
}

// 更好的做法!
props: {
  status: {
    type: String,
    required: true,
    validator: function (value) {
      return [
        'syncing',
        'synced',
        'version-conflict',
        'error'
      ].indexOf(value) !== -1
    }
  }
}
复制代码
  1. 组件 data 必须是个函数,避免多个组件数据互相影响
// 好例子
export default {
  data () {
    return {
      foo: 'bar'
    }
  }
}
复制代码
  1. 使用 v-for 务必加上 key,且避免和 v-if 写在一起
// 好例子
<ul v-if="shouldShowUsers">
  <li
    v-for="user in users"
    :key="user.id"
  >
    {{ user.name }}
  </li>
</ul>
复制代码
  1. 为组件样式设置作用域
  • 使用 scoped 属性
<template>
  <button class="button button-close">X</button>
</template>

<!-- 使用 `scoped` attribute -->
<style scoped>
.button {
  border: none;
  border-radius: 2px;
}

.button-close {
  background-color: red;
}
</style>
复制代码
<template>
  <button :class="[$style.button, $style.buttonClose]">X</button>
</template>

<!-- 使用 CSS Modules -->
<style module>
.button {
  border: none;
  border-radius: 2px;
}

.buttonClose {
  background-color: red;
}
</style>
复制代码

image.png

JavaScript 还可以访问到类名:

<script>
export default {
  created () {
    // 获取button编译后的类名:
    // _1mB1nfbAEqzAETAbkaBZDV_0
    console.log(this.$style.button)
  }
}
</script>
复制代码
  • BEM 的策略:组件库推荐使用
<template>
  <button class="c-Button c-Button--close">X</button>
</template>

<!-- 使用 BEM 约定(Block独立的页面、Element元素标签、Modifier修饰符:元素处于的一种状态 -->
<style>
.c-Button {
  border: none;
  border-radius: 2px;
}

.c-Button--close {
  background-color: red;
}
</style>
复制代码
  1. 私有 property 名,使用 $_ 前缀,避免产生冲突
// 好例子
var myGreatMixin = {
  // ...
  methods: {
    $_myGreatMixin_update: function () {
      // ...
    }
  }
}
复制代码

更多好的编码风格指南,可参考官网

性能

当项目业务代码不断剧增时,项目运行开销变大,构建速度变慢,我们就需要考虑性能优化。从vue编码的角度来看,我们可以从以下几个方面来着手优化:

1. 组件按需加载

路由懒加载(使用import)

当打包构建时,JavaScript包变得非常大,影响页面加载,我们可以把不同路由对应的组件分割成不同的代码块,当路由被访问的时候才加载对应组件。使用 import 动态导入,配合 webpack tree-shaking 摇树功能,没有用到的组件就不会打包到 chunk,从而提升加载性能。

const Home = () => import('@/components/home')
const Index = () => import('@/components/index')
const About = () => import('@/components/about')
复制代码

2. 提升首屏加载速度

webpack体积优化

如今商业化前端项目大多都是工程化应用,vue/react/angular等框架编码,webpack 打包构建编译,页面首屏加载慢,主要原因是打包构建的 chunk 体积过大。要提升首屏加载速度,首先需要优化 webpack 打包后的体积,优化措施可参考之前整理的技术博文:

做webpack性能优化的一段经历|项目复盘

可改造成SSR,减少首屏加载时间

使用SSR服务端渲染,将组件或是页面通过服务器生成html字符串,再发送到浏览器,这样可以加快首屏加载渲染的速度,提前显示文档内容。

可参考:SSR-完全指南

3. 不需要更新的内容静态化

利用 vuev-once 指令一次性插值的功能,可以将不需要更新的节点内容静态化,这样可以优化更新性能。

4. 尽量减少DOM层级嵌套

DOM 渲染需要的性能开销比较大,我们在开发过程中尽量简化 div 结构,可以减少不必要的 DOM 层级嵌套。对于组件来说,我们应该尽量减少不必要的组件抽象,不必要的组件抽象无疑会增加 DOM 层级嵌套。

5. 大数据量的渲染优化

长列表采用虚拟滚动加载

长列表的数量一般在几百条范围内不会出现意外的效果,浏览器本身足以支撑。可一旦数量级达到上千,页面渲染过程会出现明显的卡顿。数量突破上万甚至十几万时,网页可能直接崩溃了。

为了解决长列表造成的浏览器渲染压力,出现了相应的应对技术——虚拟滚动

实现原理:

虚拟滚动的实现,实际上就是在首屏加载时,只加载可视区域的列表项,当滚动发生时,动态计算获取可视区域内的列表项,并将非可视区域的列表项删除。

image.png

可参考:「前端进阶」高性能渲染十万条数据(虚拟列表)

不活动的组件,可用<keep-alive>缓存

<keep-alive> 是 Vue 的内置组件,用它来包裹动态组件时,会缓存不活动的组件实例。和 <transition> 相似,<keep-alive> 是一个抽象组件:它自身不会渲染一个DOM元素,也不会出现在父组件链中。

// 基本使用
<keep-alive>
  <component :is="view"></component>
</keep-alive>
复制代码

<keep-alive> 主要用于保留组件状态或是避免重新渲染。

安全

XSS防御

  • 不使用不可信的模板直接渲染,可用变量动态拼接模板再渲染
<template>
  <div>{{ msg }}</div>
</template>
复制代码
  • 小心使用 v-html:url:style等,避免 htmlurl样式等发生 xss 注入。对于后端返回的数据可进行转义解析,校验不配对的 DOM 标签。
  • 等等......

CSRF防御

  • token验证
    • 第一步:后端随机生成一个 token 值,把这个 token 保存到 session 状态中;同时后端把这个 token 传给前端页面;
    • 第二步:前端页面提交请求时,把 token 加到请求入参或是头信息中,一起传给后端;
    • 最后一步:后端验证前端传来的 tokensession 中的是否一致,一致则合法,否则是非法请求。
  • referer验证

验证 referer 请求来源,这种方法成本最低,但是并不能保证100%有效,因为服务器并不是什么时候都能取到 referer,而且低版本的浏览器存在伪造 referer 的风险。

  • 验证码

强制用户必须与页面应用交互,成功验证验证码才能完成最终的请求。这种方式很好的遏制 csrf,但用户体验比较差。

总结

上述主要从 “编码风格、性能、安全” 3个方面总结了一些vue开发的实战经验,希望能对开发小伙伴有所帮助~~

猜你喜欢

转载自juejin.im/post/7080096273956601864
今日推荐