vue 作为目前前端三大框架之一,对于前端开发者可以说是必备技能。那么怎么系统地学习和掌握 vue 呢?为此,我做了简单的知识体系体系总结,不足之处请各位大佬多多包涵和指正,如果喜欢的可以点个小赞!本文主要讲述一些vue开发中的实用技巧。

相关推荐

监听组件的生命周期

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

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

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

<Child @hook:mounted="doSomething" />
<Child @hook:updated="doSomething" />
复制代码

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

watch 的初始立即执行

观察和响应 Vue 实例上的数据变动。类似于某些数据的监听回调 ,每当监听的数据变化时都会执行回调进行后续操作。

但是当 watch 一个变量的时候,初始化时并不会执行,如下面的例子,你需要在 created 的时候手动调用一次。

created() {
this.getList();
},
watch: {
keyWord: 'getList',
}

上面这样的做法可以使用,但很麻烦,我们可以添加 immediate 属性,这样初始化的时候就会自动触发(不用再写 created 去调用了),然后上面的代码就能简化为:

watch: {
keyWord: {
handler: 'getList',
immediate: true
}
}

watch 有三个参数

  • handler:其值是一个回调函数。即监听到变化时应该执行的函数
  • deep:其值是 true 或 false;确认是否深入监听。
  • immediate:其值是 true 或 false,确认是否以当前的初始值执行 handler 的函数

路由参数变化组件不更新

同一path的页面跳转时路由参数变化,但是组件没有对应的更新。

原因:主要是因为获取参数写在了created或者mounted路由钩子函数中,路由参数变化的时候,这个生命周期不会重新执行。

解决方案1:watch监听路由

watch: {
// 方法1 //监听路由是否变化
'$route' (to, from) {
if(to.query.id !== from.query.id){
this.id = to.query.id;
this.init();//重新加载数据
}
}
}
//方法 2 设置路径变化时的处理函数
watch: {
'$route': {
handler: 'init',
immediate: true
}
}

解决方案2 :为了实现这样的效果可以给router-view添加一个不同的key,这样即使是公用组件,只要url变化了,就一定会重新创建这个组件。

<router-view :key="$route.fullpath"></router-view>

路由懒加载

Vue 项目中实现路由按需加载(路由懒加载)的 3 中方式:

// 1、Vue异步组件技术:
{
path: '/home',
name: 'Home',
component: resolve => reqire(['path路径'], resolve)
} // 2、es6提案的import()
const Home = () => import('path路径') // 3、webpack提供的require.ensure()
{
path: '/home',
name: 'Home',
component: r => require.ensure([],() => r(require('path路径')), 'demo')
}

require.context()

require.context(directory,useSubdirectories,regExp)

  • directory:说明需要检索的目录
  • useSubdirectories:是否检索子目录
  • regExp: 匹配文件的正则表达式,一般是文件名

场景:如页面需要导入多个组件,原始写法:

import titleCom from '@/components/home/titleCom'
import bannerCom from '@/components/home/bannerCom'
import cellCom from '@/components/home/cellCom'
components: {
titleCom, bannerCom, cellCom
}

这样就写了大量重复的代码,利用 require.context 可以写成

const path = require('path')
const files = require.context('@/components/home', false, /\.vue$/)
const modules = {}
files.keys().forEach(key => {
const name = path.basename(key, '.vue')
modules[name] = files(key).default || files(key)
})
components: modules

递归组件

  • 递归组件: 组件在它的模板内可以递归的调用自己,只要给组件设置 name 组件就可以了。
  • 不过需要注意的是,必须给一个条件来限制数量,否则会抛出错误: max stack size exceeded
  • 组件递归用来开发一些具体有未知层级关系的独立组件。比如:联级选择器和树形控件
<template>
<div v-for="(item,index) in treeArr"> {{index}} <br/>
<tree :item="item.arr" v-if="item.flag"></tree>
</div>
</template>
<script>
export default {
// 必须定义name,组件内部才能递归调用
name: 'tree',
data(){
return {}
},
// 接收外部传入的值
props: {
item: {
type:Array,
default: ()=>[]
}
}
}
</script>

清除定时器或者事件监听

由于项目中有些页面难免会碰到需要定时器或者事件监听。但是在离开当前页面的时候,定时器如果不及时合理地清除,会造成业务逻辑混乱甚至应用卡死的情况,这个时就需要清除定时器事件监听,即在页面卸载(关闭)的生命周期函数里,清除定时器。

methods:{
resizeFun () {
this.tableHeight = window.innerHeight - document.getElementById('table').offsetTop - 128
},
setTimer() {
this.timer = setInterval(() => { })
},
clearTimer() {//清除定时器
clearInterval(this.timer)
this.timer = null
}
},
mounted() {
this.setTimer()
window.addEventListener('resize', this.resizeFun)
},
beforeDestroy() {
window.removeEventListener('resize', this.resizeFun)
this.clearTimer()
}

自定义路径别名

我们也可以在基础配置文件中添加自己的路径别名

resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
'assets': resolve('src/assets')
}
}

然后我们导入组件的时候就可以这样写:

// import YourComponent from '/src/assets/YourComponent'
import YourComponent from 'assets/YourComponent'
复制代码

这样既解决了路径过长的麻烦,又解决了相对路径的烦恼。

动态给修改dom的样式

原因:因为我们在写.vue文件中的样式都会追加scoped。这样针对模板dom中的样式就可以生效,但其生效后的最终样式并不是我们写的样式名,而是编码后的。比如:

<template>
<div class="box">dom</div>
</template>
<style lang="scss" scoped>
.box {
background: red;
}
</style>

vue 将代码转译成如下,所以我们在js中拼接上的dom结构样式并不会生效。

.box[data-v-11c6864c]{ background:red; }
<template>
<div class="box" data-v-11c6864c>dom</div>
</template>

解决方法:将要改变的样式写在非scoped样式标签中。

长列表性能优化

我们应该都知道 vue 会通过 object.defineProperty 对数据进行劫持,来实现视图响应数据的变化,然而有些时候我们的组件就是纯粹的数据展示,不会有任何改变,我们就不需要 vue 来劫持我们的数据,在大量数据展示的情况下,这能够很明显的减少组件初始化的时间。

所以,我们可以通过 object.freeze 方法来冻结一个对象,这个对象一旦被冻结,vue就不会对数据进行劫持了。

export default {
data: () => ({
list: []
}),
async created() {
const list = await axios.get('xxxx')
this.list = Object.freeze(list)
},
methods: {
// 此处做的操作都不能改变list的值
}
}

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

内容分发(slot)

插槽 slot,也是组件的一块 HTML 模板,这一块模板显示不显示、以及怎样显示由父组件来决定。实际上,一个 slot 最核心的两个问题在这里就点出来了,是显示不显示和怎样显示。

默认插槽

又名单个插槽、匿名插槽,这类插槽没有具体名字,一个组件只能有一个该类插槽。

<!-- 父组件 parent.vue -->
<template>
<div class="parent">
<h1>父容器</h1>
<child>
<div class="tmpl">
<span>菜单1</span>
</div>
</child>
</div>
</template> <!-- 子组件 child.vue -->
<template>
<div class="child">
<h1>子组件</h1>
<slot></slot>
</div>
</template>

具名插槽

匿名插槽没有 name 属性,所以叫匿名插槽。那么,插槽加了 name 属性,就变成了具名插槽。具名插槽可以在一个组件中出现 N 次,出现在不同的位置,只需要使用不同的 name 属性区分即可。

<!-- 父组件 parent.vue -->
<template>
<div class="parent">
<h1>父容器</h1>
<child>
<div class="tmpl" slot="up">
<span>菜单up-1</span>
</div>
<div class="tmpl" slot="down">
<span>菜单down-1</span>
</div>
<div class="tmpl">
<span>菜单->1</span>
</div>
</child>
</div>
</template> <!-- 子组件 child.vue -->
<template>
<div class="child">
<!-- 具名插槽 -->
<slot name="up"></slot>
<h3>这里是子组件</h3>
<!-- 具名插槽 -->
<slot name="down"></slot>
<!-- 匿名插槽 -->
<slot></slot>
</div>
</template>

作用域插槽

作用域插槽可以是默认插槽,也可以是具名插槽,不一样的地方是,作用域插槽可以为 slot 标签绑定数据,让其父组件可以获取到子组件的数据。

<!-- parent.vue -->
<template>
<div class="parent">
<h1>这是父组件</h1>
<child
>>
<template slot="default" slot-scope="slotProps">
{{ slotProps.user.name }}
</template> </child
>>
</div>
</template> <!-- 子组件 child.vue -->
<template>
<div class="child">
<h1>这是子组件</h1>
<slot :user="user"></slot>
</div>
</template>
<script>
export default {
data() {
return {
user: {
name: '小赵'
}
}
}
}
</script>

推荐文章

总结vue知识体系之实用技巧的更多相关文章

  1. 2018 我要告诉你的 Vue 知识大全

    Vue ,React ,Angular 三大主流框架,最后我选择学习 Vue ,接触过 React ,自己感觉学习曲线有些陡峭,进而我选择了学习 Vue ,他的学习曲线平稳很多:不管选择什么框架,除了 ...

  2. VUE基础实用技巧

    Vue以前听说过,有了解过一点.当时还在热衷于原生JavaScript去写一些方法的封装,不是为啥,就感觉这样很帅,后面多多少少接触了一些JQuery的用法,到现在为止,JavaScript原生封装的 ...

  3. Vue大概知识体系和学习参考

    Vue大概知识体系和学习参考文档 官方文档学习,参考,借鉴地址:https://cn.vuejs.org/v2/guide/installation.html 菜鸟教程:https://www.run ...

  4. github上最全的资源教程-前端涉及的所有知识体系

    前面分享了前端入门资源汇总,今天分享下前端所有的知识体系. 个人站长对个人综合素质要求还是比较高的,要想打造多拉斯自媒体网站,不花点心血是很难成功的,学习前端是必不可少的一个环节, 当然你不一定要成为 ...

  5. github上最全的资源教程-前端涉及的所有知识体系【转】

    github上最全的资源教程-前端涉及的所有知识体系[转自:蓝猫的博客] 综合类 综合类 地址 前端知识体系 http://www.cnblogs.com/sb19871023/p/3894452.h ...

  6. 一位ML工程师构建深度神经网络的实用技巧

    一位ML工程师构建深度神经网络的实用技巧 https://mp.weixin.qq.com/s/2gKYtona0Z6szsjaj8c9Vg 作者| Matt H/Daniel R 译者| 婉清 编辑 ...

  7. 从输入URL到页面加载的过程?如何由一道题完善自己的前端知识体系!

    前言 见解有限,如有描述不当之处,请帮忙指出,如有错误,会及时修正. 为什么要梳理这篇文章? 最近恰好被问到这方面的问题,尝试整理后发现,这道题的覆盖面可以非常广,很适合作为一道承载知识体系的题目. ...

  8. 本人AI知识体系导航 - AI menu

    Relevant Readable Links Name Interesting topic Comment Edwin Chen 非参贝叶斯   徐亦达老板 Dirichlet Process 学习 ...

  9. JavaScript 实用技巧和写法建议

    1.前言 从大学到现在,接触前端已经有几年了,感想方面,就是对于程序员而言,想要提高自己的技术水平和编写易于阅读和维护的代码,我觉得不能每天都是平庸的写代码,更要去推敲,去摸索和优化代码,总结当中的技 ...

随机推荐

  1. Spring中异步注解@Async的使用、原理及使用时可能导致的问题

    前言 其实最近都在研究事务相关的内容,之所以写这么一篇文章是因为前面写了一篇关于循环依赖的文章: <面试必杀技,讲一讲Spring中的循环依赖> 然后,很多同学碰到了下面这个问题,添加了S ...

  2. MySQL 高级性能优化架构 千万级高并发交易一致性系统基础

    一.MySQL体系架构 由图,可以看出MySQL最上层是连接组件.下面服务器是由连接池.管理服务和工具组件.SQL接口.查询解析器.查询优化器.缓存.存储引擎.文件系统组成. 1.连接池 管理.缓冲用 ...

  3. 超简单的jq图片上传

    <label class="file_img" for="file_imgs"> <input class="file_imgs&q ...

  4. Python编程之美:最佳实践指南PDF高清完整版免费下载|百度云盘|Python新手到进阶

    百度云盘:Python编程之美:最佳实践指南PDF高清完整版免费下载 提取码:1py6 内容简介 <Python编程之美:最佳实践指南>是Python用户的一本百科式学习指南,由Pytho ...

  5. Linux企业运维人员最常用命令汇总

    本文目录 线上查询及帮助命令 文件和目录操作命令 查看文件及内容处理命令 文件压缩及解压缩命令 信息显示命令 搜索文件命令 用户管理命令 基础网络操作命令 深入网络操作命令 有关磁盘与文件系统的命令 ...

  6. Cobbler 部署

    环境介绍 Cobbler 操作系统: Centos-7.2-x86_64 Cobbler服务器地址: 10.90.0.10 部署 Cobbler 安装 Centos epel 原 [root@node ...

  7. Pandas 复习2

    import pandas as pd import numpy as np food_info = pd.read_csv('food_info.csv') 1.处理缺失值(可使用平均数,众数填充) ...

  8. 5-Pandas之常用的描述性统计函数、汇总函数

    一.常用的描述性统计函数  函数 作用 函数 作用 count 非缺失样本的数量 sum 求和 mean 均值 mad 平均绝对偏差(Mean absolute deviation) median 中 ...

  9. Virtuoso 中 display.drf、techfile.tf、tech.db 之间的关系,以及 Packet 在它们之间的作用

    https://www.cnblogs.com/yeungchie/ 一般工艺库下的"技术文件"有 tech.db 和 techfile.tf , Packet 是 display ...

  10. log4j2 自动删除过期日志文件配置及实现原理解析

    日志文件自动删除功能必不可少,当然你可以让运维去做这事,只是这不地道.而日志组件是一个必备组件,让其多做一件删除的工作,无可厚非.本文就来探讨下 log4j 的日志文件自动删除实现吧. 0. 自动删除 ...