Vue项目优化(代码实现层面)

1.0、v-if 和 v-show 区分使用场景
v-if 是 真正 的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;也是惰性的:如果在初始渲染时条件为假,则什么也不做——直到条件第一次变为真时,才会开始渲染条件块。

v-show 就简单得多, 不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 的 display 属性进行切换。

所以,v-if 适用于在运行时很少改变条件,不需要频繁切换条件的场景;v-show 则适用于需要非常频繁切换条件的场景。

 

2.0、computed 和 watch 区分使用场景
computed: 是计算属性,依赖其它属性值,并且 computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会重新计算 computed 的值;

watch: 更多的是「观察」的作用,类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作;

运用场景:

当我们需要进行数值计算,并且依赖于其它数据时,应该使用 computed,因为可以利用 computed 的缓存特性,避免每次获取值时,都要重新计算;

当我们需要在数据变化时执行异步或开销较大的操作时,应该使用 watch,使用 watch 选项允许我们执行异步操作 ( 访问一个 API ),限制我们执行该操作的频率,并在我们得到最终结果前,设置中间状态。这些都是计算属性无法做到的。


3.0 v-for 遍历必须为 item 添加 key,且避免同时使用 v-if

(1)v-for 遍历必须为 item 添加 key

在列表数据进行遍历渲染时,需要为每一项 item 设置唯一 key 值,方便 Vue.js 内部机制精准找到该条列表数据。当 state 更新时,新的状态值和旧的状态值对比,较快地定位到 diff 。

(2)v-for 遍历避免同时使用 v-if

v-for 比 v-if 优先级高,如果每一次都需要遍历整个数组,将会影响速度,尤其是当之需要渲染很小一部分的时候,必要情况下应该替换成 computed 属性。

4.0 长列表性能优化

在data中定义的数据默认都会被Object.defineProperty 直接劫持,可以响应变化,实际的使用场景中长列表数据如果只是作为展示,不需要Vue来劫持数据,就需要用到Object.freeze来冻结对象,被冻结的对象不可以被修改

export default {
  data: () => ({
    users: {}
  }),
  async created() {
    const users = await axios.get("/api/users");
    this.users = Object.freeze(users);
  }
};

5.0 事件的销毁

Vue的组件销毁时会自动清理与其连接的实例,解绑他的全部指令和内部事件,但是仅限于内部的事件,js内置如

created() {
  addEventListener('click', this.click, false)
},
beforeDestroy() {
  removeEventListener('click', this.click, false)
}

就需要自行在beforeDestory中进行销毁

6.0 图片资源懒加载

对于图片过多的页面,为了加速页面加载速度,所以需要将页面内未出现在可视区域的图片先不做加载,等到滚动到可视区域内再加载,这样对于页面加载性能有很大的提升,提高用户体验,推荐使用vue-lazyload插件:

第一步:安装插件  npm install vue-lazyload --save -dev

第二步:在入口文件main.js中引入使用

import VueLazyload from 'vue-lazyload'
Vue.use(VueLazyload)

第三步: 在使用图片懒加载的组件中v-lazy使用

<img v-lazy="/static/img/1.png">

 

7.0 路由懒加载

Vue 是单页面应用,可能会有很多的路由引入 ,这样使用 webpcak 打包后的文件很大,当进入首页时,加载的资源过多,页面会出现白屏的情况,不利于用户体验。如果我们能把不同路由对应的组件分割成不同的代码块,然后当路由被访问的时候才加载对应的组件,这样就更加高效了。这样会大大提高首屏显示的速度,但是可能其他的页面的速度就会降下来。

const Foo = () => import('./Foo.vue')
const router = new VueRouter({
  routes: [
    { path: '/foo', component: Foo }
  ]
})

 

8.0 第三方插件的按需引入

以element-ui的按需引入为例子

第一步:独立一个js文件按需引入element-ui组件

import {
    Select,
    Option,
    OptionGroup,
    Input,
    InputNumber,
    Radio,
    Tree,
    Dialog,
    Row,
    Col,
    Checkbox,
    CheckboxButton,
    CheckboxGroup,
    Cascader,
    Switch,
    Slider,
    TimeSelect,
    TimePicker,
    DatePicker,
    Upload,
    Rate,
    ColorPicker,
    Transfer,
    Form,
    FormItem,
    Table,
    TableColumn,
    Tag,
    Button,
    Progress,
    Pagination,
    Badge,
    Avatar,
    Alert,
    Loading,
    Message,
    MessageBox,
    Notification,
    Menu,
    Card,
    MenuItemGroup,
    MenuItem,
    Submenu,
    RadioGroup,
    RadioButton,
    Container,
    Header,
    Aside,
    Main
} from 'element-ui'
const element = {
    install: function(Vue) {
        Vue.use(Container)
        Vue.use(Card)
        Vue.use(Header)
        Vue.use(Aside)
        Vue.use(Main)
        Vue.use(Select)
        Vue.use(Option)
        Vue.use(OptionGroup)
        Vue.use(Input)
        Vue.use(InputNumber)
        Vue.use(Radio)
        Vue.use(Tree)
        Vue.use(Dialog)
        Vue.use(Row)
        Vue.use(Col)
        Vue.use(Checkbox)
        Vue.use(CheckboxButton)
        Vue.use(CheckboxGroup)
        Vue.use(Cascader)
        Vue.use(Switch)
        Vue.use(Slider)
        Vue.use(TimePicker)
        Vue.use(TimeSelect)
        Vue.use(DatePicker)
        Vue.use(Upload)
        Vue.use(Rate)
        Vue.use(ColorPicker)
        Vue.use(Transfer)
        Vue.use(Form)
        Vue.use(FormItem)
        Vue.use(Table)
        Vue.use(TableColumn)
        Vue.use(Tag)
        Vue.use(Button)
        Vue.use(Progress)
        Vue.use(Pagination)
        Vue.use(Badge)
        // Vue.use(Avatar)
        Vue.use(Alert)
        Vue.use(Loading)
        Vue.use(Menu)
        Vue.use(MenuItem)
        Vue.use(MenuItemGroup)
        Vue.use(Submenu)
        Vue.use(RadioGroup)
        Vue.use(RadioButton)
        Vue.prototype.$message = Message;
        Vue.prototype.$confirm = MessageBox.confirm;
        Vue.prototype.$alert = MessageBox.alert;
        Vue.prototype.$notify = Notification;

    }
}

export default element

第二步:在main.js中引入即可

 

 9.0  SSR服务端渲染或者预渲染

服务端渲染是指 Vue 在客户端将标签渲染成的整个 html 片段的工作在服务端完成,服务端形成的 html 片段直接返回给客户端这个过程就叫做服务端渲染。

(1)服务端渲染的优点:

更好的 SEO:因为 SPA 页面的内容是通过 Ajax 获取,而搜索引擎爬取工具并不会等待 Ajax 异步完成后再抓取页面内容,所以在 SPA 中是抓取不到页面通过 Ajax 获取到的内容;而 SSR 是直接由服务端返回已经渲染好的页面(数据已经包含在页面中),所以搜索引擎爬取工具可以抓取渲染好的页面;

更快的内容到达时间(首屏加载更快):SPA 会等待所有 Vue 编译后的 js 文件都下载完成后,才开始进行页面的渲染,文件下载等需要一定的时间等,所以首屏渲染需要一定的时间;SSR 直接由服务端渲染好页面直接返回显示,无需等待下载 js 文件及再去渲染等,所以 SSR 有更快的内容到达时间;

(2)服务端渲染的缺点:

更多的开发条件限制:例如服务端渲染只支持 beforCreate 和 created 两个钩子函数,这会导致一些外部扩展库需要特殊处理,才能在服务端渲染应用程序中运行;并且与可以部署在任何静态文件服务器上的完全静态单页面应用程序 SPA 不同,服务端渲染应用程序,需要处于 Node.js server 运行环境;

更多的服务器负载:在 Node.js 中渲染完整的应用程序,显然会比仅仅提供静态文件的 server 更加大量占用CPU 资源,因此如果你预料在高流量环境下使用,请准备相应的服务器负载,并明智地采用缓存策略。

如果你的项目的 SEO 和 首屏渲染是评价项目的关键指标,那么你的项目就需要服务端渲染来帮助你实现最佳的初始加载性能和 SEO。如果你的 Vue 项目只需改善少数营销页面(例如 /, /about, /contact 等)的 SEO,那么你可能需要预渲染,在构建时 (build time) 简单地生成针对特定路由的静态 HTML 文件。优点是设置预渲染更简单,并可以将你的前端作为一个完全静态的站点,具体你可以使用 prerender-spa-plugin 就可以轻松地添加预渲染 。

 

posted on 2021-09-14 11:21  还是种田踏实  阅读(131)  评论(0编辑  收藏  举报