实用的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 相关文章推荐
JS 弹出层 定位至屏幕居中示例
May 21 Javascript
js获取浏览器基本信息大全
Nov 27 Javascript
javascript实现根据3原色制作颜色选择器的方法
Jul 17 Javascript
JavaScript操作select元素和option的实例代码
Jan 29 Javascript
jQuery属性选择器用法示例
Sep 09 Javascript
Bootstrap面板(Panels)的简单实现代码
Mar 17 Javascript
axios全局请求参数设置,请求及返回拦截器的方法
Mar 05 Javascript
详解JavaScript中typeof与instanceof用法
Oct 24 Javascript
JavaScript HTML DOM元素 节点操作汇总
Jul 29 Javascript
原生js实现可兼容PC和移动端的拖动滑块功能详解【测试可用】
Aug 15 Javascript
JSX在render函数中的应用详解
Sep 04 Javascript
javascript实现滚动条效果
Mar 24 Javascript
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
动画 《Pokemon Sword·Shield》系列WEB动画《薄明之翼》第2话声优阵容公开!
2020/03/06 日漫
php实现的支持断点续传的文件下载类
2014/09/23 PHP
javascript实现表格排序 编辑 拖拽 缩放
2015/01/02 Javascript
ECMAScript 6即将带给我们新的数组操作方法前瞻
2015/01/06 Javascript
实例解析JS布尔对象的toString()方法和valueOf()方法
2015/10/25 Javascript
angularJS 如何读写缓冲的方法(推荐)
2016/08/06 Javascript
轻松掌握JavaScript状态模式
2016/09/07 Javascript
Jquery UI实现一次拖拽多个选中的元素操作
2020/12/01 Javascript
AngularJS 中使用Swiper制作滚动图不能滑动的解决方法
2016/11/15 Javascript
JS+html5制作简单音乐播放器
2020/09/13 Javascript
[js高手之路]从原型链开始图解继承到组合继承的产生详解
2017/08/28 Javascript
什么是Vue.js框架 为什么选择它?
2017/10/17 Javascript
vue-cli2.x项目优化之引入本地静态库文件的方法
2018/06/19 Javascript
JavaScript模拟实现自由落体效果
2018/08/28 Javascript
JavaScript 判断iPhone X Series机型的方法
2019/01/28 Javascript
jquery简单实现纵向的无缝滚动代码实例
2019/04/01 jQuery
javascript实现前端input密码输入强度验证
2020/06/24 Javascript
jquery实现异步文件上传ajaxfileupload.js
2020/10/23 jQuery
[01:06:39]DOTA2上海特级锦标赛主赛事日 - 1 胜者组第一轮#1Liquid VS Alliance第三局
2016/03/02 DOTA
Python的Flask框架与数据库连接的教程
2015/04/20 Python
PyCharm代码整体缩进,反向缩进的方法
2018/06/25 Python
Python实现计算文件MD5和SHA1的方法示例
2019/06/11 Python
Python3 Tkinter选择路径功能的实现方法
2019/06/14 Python
用python生成与调用cntk模型代码演示方法
2019/08/26 Python
Django serializer优化类视图的实现示例
2020/07/16 Python
Python类型转换的魔术方法详解
2020/12/23 Python
浅谈Html5多线程开发之WebWorkers
2018/05/02 HTML / CSS
HTML5 video 上传预览图片视频如何设置、预览视频某秒的海报帧
2018/08/28 HTML / CSS
Ralph Lauren法国官网:美国高品味时装品牌
2017/12/08 全球购物
微软台湾官方网站:Microsoft台湾
2018/08/15 全球购物
UNOde50美国官网:西班牙珠宝品牌
2020/08/15 全球购物
高级销售员求职信
2013/10/25 职场文书
省级优秀班集体申报材料
2014/05/25 职场文书
党员反对四风思想汇报范文
2014/10/25 职场文书
2014年护理部工作总结
2014/11/14 职场文书
Python使用pandas导入xlsx格式的excel文件内容操作代码
2022/12/24 Python