实用的Vue开发技巧


Posted in Javascript onMay 30, 2019

1 状态共享

随着组件的细化,就会遇到多组件状态共享的情况,Vuex当然可以解决这类问题,不过就像Vuex官方文档所说的,如果应用不够大,为避免代码繁琐冗余,最好不要使用它,今天我们介绍的是vue.js 2.6新增加的Observable API ,通过使用这个api我们可以应对一些简单的跨组件数据状态共享的情况。

如下这个例子,我们将在组件外创建一个store,然后在App.vue组件里面使用store.js提供的store和mutation方法,同理其它组件也可以这样使用,从而实现多个组件共享数据状态。

首先创建一个store.js,包含一个store和一个mutations,分别用来指向数据和处理方法。

import Vue from "vue";
export const store = Vue.observable({ count: 0 });
export const mutations = {
setCount(count) {
store.count = count;
}
};

然后在App.vue里面引入这个store.js,在组件里面使用引入的数据和方法

<template>
<div id="app">
<img width="25%" src="./assets/logo.png">
<p>count:{{count}}</p>
<button @click="setCount(count+1)">+1</button>
<button @click="setCount(count-1)">-1</button>
</div>
</template>
<script>
import { store, mutations } from "./store";
export default {
name: "App",
computed: {
count() {
return store.count;
}
},
methods: {
setCount: mutations.setCount
}
};
</script>
<style>

你可以点击在线DEMO查看最终效果

2 长列表性能优化

我们应该都知道vue会通过object.defineProperty对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要vue来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间,那如何禁止vue劫持我们的数据呢?可以通过object.freeze方法来冻结一个对象,一旦被冻结的对象就再也不能被修改了。

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

另外需要说明的是,这里只是冻结了users的值,引用不会被冻结,当我们需要reactive数据的时候,我们可以重新给users赋值。

export default {
data: () => ({
users: []
}),
async created() {
const users = await axios.get("/api/users");
this.users = Object.freeze(users);
},
methods:{
// 改变值不会触发视图响应
this.users[0] = newValue
// 改变引用依然会触发视图响应
this.users = newArray
}
};

3 去除多余的样式

随着项目越来越大,书写的不注意,不自然的就会产生一些多余的css,小项目还好,一旦项目大了以后,多余的css会越来越多,导致包越来越大,从而影响项目运行性能,所以有必要在正式环境去除掉这些多余的css,这里推荐一个库purgecss,支持CLI、JavascriptApi、Webpack等多种方式使用,通过这个库,我们可以很容易的去除掉多余的css。

我做了一个测试,在线DEMO

<h1>Hello Vanilla!</h1>
<div>
We use Parcel to bundle this sandbox, you can find more info about Parcel
<a href="https://parceljs.org" rel="external nofollow" target="_blank" rel="noopener noreferrer">here</a>.
</div>
body {
font-family: sans-serif;
}
a {
color: red;
}
ul {
li {
list-style: none;
}
}
import Purgecss from "purgecss";
const purgecss = new Purgecss({
content: ["**/*.html"],
css: ["**/*.css"]
});
const purgecssResult = purgecss.purge();

最终产生的purgecssResult结果如下,可以看到多余的a和ul标签的样式都没了

实用的Vue开发技巧

4 作用域插槽

利用好作用域插槽可以做一些很有意思的事情,比如定义一个基础布局组件A,只负责布局,不管数据逻辑,然后另外定义一个组件B负责数据处理,布局组件A需要数据的时候就去B里面去取。假设,某一天我们的布局变了,我们只需要去修改组件A就行,而不用去修改组件B,从而就能充分复用组件B的数据处理逻辑,关于这块我之前写过一篇实际案例,可以点击这里查看。

这里涉及到的一个最重要的点就是父组件要去获取子组件里面的数据,之前是利用slot-scope,自vue 2.6.0起,提供了更好的支持 slot 和 slot-scope 特性的 API 替代方案。
比如,我们定一个名为current-user的组件:

<span>
<slot>{{ user.lastName }}</slot>
</span>

父组件引用current-user的组件,但想用名替代姓(老外名字第一个单词是名,后一个单词是姓):

<current-user>
{{ user.firstName }}
</current-user>

这种方式不会生效,因为user对象是子组件的数据,在父组件里面我们获取不到,这个时候我们就可以通过v-slot
来实现。

首先在子组件里面,将user作为一个<slot>元素的特性绑定上去:

<span>
<slot v-bind:user="user">
{{ user.lastName }}
</slot>
</span>

之后,我们就可以在父组件引用的时候,给v-slot带一个值来定义我们提供的插槽 prop 的名字:

<current-user>
<template v-slot:default="slotProps">
{{ slotProps.user.firstName }}
</template>
</current-user>

这种方式还有缩写语法,可以查看独占默认插槽的缩写语法,最终我们引用的方式如下:

<current-user v-slot="slotProps">
{{ slotProps.user.firstName }}
</current-user>

相比之前slot-scope代码更清晰,更好理解。

5 属性事件传递

写过高阶组件的童鞋可能都会碰到过将加工过的属性向下传递的情况,如果碰到属性较多时,需要一个个去传递,非常不友好并且费时,有没有一次性传递的呢(比如react里面的{...this.props})?答案就是v-bind和v-on。
举个例子,假如有一个基础组件BaseList,只有基础的列表展示功能,现在我们想在这基础上增加排序功能,这个时候我们就可以创建一个高阶组件SortList。

<!-- SortList -->
<template>
<BaseList v-bind="$props" v-on="$listeners"> <!-- ... --> </BaseList>
</template>
<script>
import BaseList from "./BaseList";
// 包含了基础的属性定义
import BaseListMixin from "./BaseListMixin";
// 封装了排序的逻辑
import sort from "./sort.js";
export default {
props: BaseListMixin.props,
components: {
BaseList
}
};
</script>

可以看到传递属性和事件的方便性,而不用一个个去传递

6 函数式组件

函数式组件,即无状态,无法实例化,内部没有任何生命周期处理方法,非常轻量,因而渲染性能高,特别适合用来只依赖外部数据传递而变化的组件。

写法如下:

1.在template标签里面标明functional

2.只接受props值

3.不需要script标签

<!-- App.vue -->
<template>
<div id="app">
<List
:items="['Wonderwoman', 'Ironman']"
:item-click="item => (clicked = item)"
/>
<p>Clicked hero: {{ clicked }}</p>
</div>
</template>
<script>
import List from "./List";
export default {
name: "App",
data: () => ({ clicked: "" }),
components: { List }
};
</script>
<!-- List.vue 函数式组件 -->
<template functional>
<div>
<p v-for="item in props.items" @click="props.itemClick(item);">
{{ item }}
</p>
</div>
</template>

7 监听组件的生命周期

比如有父组件Parent和子组件Child,如果父组件监听到子组件挂载mounted就做一些逻辑处理,常规的写法可能如下:

// Parent.vue
<Child @mounted="doSomething"/>
// Child.vue
mounted() {
this.$emit("mounted");
}

这里提供一种特别简单的方式,子组件不需要任何处理,只需要在父组件引用的时候通过@hook来监听即可,代码重写如下:

<Child @hook:mounted="doSomething"/>

当然这里不仅仅是可以监听mounted,其它的生命周期事件,例如:created,updated等都可以,是不是特别方便~

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

Javascript 相关文章推荐
JavaScript入门教程(12) js对象化编程
Jan 31 Javascript
firefox firebug中文入门教程 脚本之家新年特别版
Jan 02 Javascript
优化javascript的执行速度
Jan 23 Javascript
jQuery中的val()示例应用
Feb 26 Javascript
jQuery性能优化的38个建议
Mar 04 Javascript
js网页滚动条滚动事件实例分析
May 05 Javascript
jQuery实现ctrl+enter(回车)提交表单
Oct 19 Javascript
jQuery实现文章图片弹出放大效果
Apr 06 jQuery
Angular2中如何使用ngx-translate进行国际化
May 21 Javascript
el-input 标签中密码的显示和隐藏功能的实例代码
Jul 19 Javascript
JQuery省市联动效果实现过程详解
May 08 jQuery
在vue中import()语法不能传入变量的问题及解决
Apr 01 Vue.js
vue-router的两种模式的区别
May 30 #Javascript
详解小程序中h5页面onShow实现及跨页面通信方案
May 30 #Javascript
JS通过ajax + 多列布局 + 自动加载实现瀑布流效果
May 30 #Javascript
全面分析JavaScript 继承
May 30 #Javascript
浅谈Express.js解析Post数据类型的正确姿势
May 30 #Javascript
vue组件三大核心概念图文详解
May 30 #Javascript
详解一次Vue低版本安卓白屏问题的解决过程
May 30 #Javascript
You might like
header()函数使用说明
2006/11/23 PHP
深入php常用函数的使用汇总
2013/06/08 PHP
PHP+Mysql基于事务处理实现转账功能的方法
2015/07/08 PHP
PHP使用trim函数去除字符串左右空格及特殊字符实例
2016/01/07 PHP
PHP类与对象后期静态绑定操作实例详解
2018/12/20 PHP
jquery实现瀑布流效果分享
2014/03/26 Javascript
JQuery做的一个简单的点灯游戏分享
2014/07/16 Javascript
AngularJS通过$http和服务器通信详解
2016/09/21 Javascript
Bootstrap3下拉菜单的实现
2017/02/22 Javascript
angular中使用Socket.io实例代码
2017/06/03 Javascript
zTree获取当前节点的下一级子节点数实例
2017/09/05 Javascript
vue父组件中获取子组件中的数据(实例讲解)
2017/09/27 Javascript
通过jquery的ajax请求本地的json文件方法
2018/08/08 jQuery
详解Vue+Element的动态表单,动态表格(后端发送配置,前端动态生成)
2019/04/20 Javascript
javascript json对象小技巧之键名作为变量用法分析
2019/11/11 Javascript
使用nodeJS中的fs模块对文件及目录进行读写,删除,追加,等操作详解
2020/02/06 NodeJs
python操作xml文件详细介绍
2014/06/09 Python
Python极简代码实现杨辉三角示例代码
2016/11/15 Python
python正则实现提取电话功能
2018/02/24 Python
python模块smtplib学习
2018/05/22 Python
Django后台获取前端post上传的文件方法
2018/05/28 Python
django.db.utils.ProgrammingError: (1146, u“Table‘’ doesn’t exist”)问题的解决
2018/07/13 Python
Python框架Flask的基本数据库操作方法分析
2018/07/13 Python
python 读取摄像头数据并保存的实例
2018/08/03 Python
Python Django框架实现应用添加logging日志操作示例
2019/05/17 Python
django框架自定义模板标签(template tag)操作示例
2019/06/24 Python
pandas的qcut()方法详解
2019/07/06 Python
Python Celery多队列配置代码实例
2019/11/22 Python
python 中的9个实用技巧,助你提高开发效率
2020/08/30 Python
Cpython解释器中的GIL全局解释器锁
2020/11/09 Python
亚洲航空公司官方网站:AirAsia
2019/11/25 全球购物
小学新教师培训方案
2014/02/03 职场文书
英语投诉信范文
2015/07/03 职场文书
自书遗嘱范文
2015/08/07 职场文书
一波干货,会议主持词开场白范文
2019/05/06 职场文书
Pytorch中TensorBoard及torchsummary的使用详解
2021/05/12 Python