1. 组件缓存 keep-aive 属性 exclude
include - 字符串或正则表达式。只有名称匹配的组件会被缓存
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。
<keep-alive exclude="Detail"> <router-view /> </keep-alive>
2. es6加载路由组件
const Detail = () => import('../views/detail/Detail.vue');
3.避免路由跳转报错
//replace 避免报错 const VueRouterReplace = VueRouter.prototype.replace VueRouter.prototype.replace = function replace(to) { return VueRouterReplace.call(this, to).catch(err => err) } //push 避免报错 const VueRouterPush = VueRouter.prototype.push VueRouter.prototype.push = function push(to) { return VueRouterPush.call(this, to).catch(err => err) }
4.声明组件名 , 避免通俗语义化 例如 Footer ,需改为FooterView
5.组件点击 @click.native
<back-top @click.native="backClick" v-show="isBackShow"></back-top>
6.this.$refs获取子组件相关 , 改变子组件数据
<tab-control :titles="[{ title: '流行' }, { title: '精选' }, { title: '新款' }]" @itemClick="tabClick" ref="tabControl1" v-show="isFixed" ></tab-control> //子组件 this.$refs.tabControl1.courrentIndex = index; //改变子组件数据 this.$refs.tabControl1.$el.getBoundingClientRect() .top //获取子组件距离顶部高度
7.具名插槽 , 类名不要用 中划线 来间隔
8.Vuex,每次调用mutation之后向localstorage存值,防止刷新丢失
9.vue.config.js 每次更改完之后需要重新启动项目
10. 用样式穿透来解决ui框架后引入导致样式覆盖问题 .home >>> .children
11.vue使用this.$refs.xx在mounted中获取DOM元素为undefined
12.使用 @hook 即可监听组件生命周期,组件内无需做任何改变
<template> <List @hook:mounted="listenMounted" /> </template>
13.手动挂载组件
import vue from 'vue' import Message from './Message.vue' // 构造子类 let Messageconstructor = vue.extend(Message) // 实例化组件 let messageInstance = new Messageconstructor() // $mount可以传入选择器字符串,表示挂载到该选择器 // 如果不传入选择器,将渲染为文档之外的的元素,你可以想象成 document.createElement()在内存中生成dom messageInstance.$mount() // messageInstance.$el获取的是dom元素 document.body.appendChild(messageInstance.$el)
14.wacth高阶使用
14-1.在组件创建后 watch 属性immediate设置为true 能够立即执行
export default { data() { return { name: 'Joe' } }, watch: { name: { handler: 'sayName', immediate: true } }, methods: { sayName() { console.log(this.name) } } }
14-2.在监听对象时,对象内部的属性被改变时无法触发 watch , 设置属性deep为true , 为其设置深度监听
export default { data: { studen: { name: 'Joe', skill: { run: { speed: 'fast' } } } }, watch: { studen: { handler: 'sayName', deep: true } }, methods: { sayName() { console.log(this.studen) } } }
14-3 触发监听执行多个方法
export default { data: { name: 'Joe' }, watch: { name: [ 'sayName1', //字符串形式 function(newVal, oldVal) { //函数形式 this.sayName2() }, { //对象形式 handler: 'sayName3', immaediate: true } ] }, methods: { sayName1() { console.log('sayName1==>', this.name) }, sayName2() { console.log('sayName2==>', this.name) }, sayName3() { console.log('sayName3==>', this.name) } } }
14-4 wacth监听多个变量
watch本身无法监听多个变量。但我们可以将需要监听的多个变量通过计算属性返回对象,再监听这个对象来实现“监听多个变量”
export default { data() { return { msg1: 'apple', msg2: 'banana' } }, compouted: { msgObj() { const { msg1, msg2 } = this return { msg1, msg2 } } }, watch: { msgObj: { handler(newVal, oldVal) { if (newVal.msg1 != oldVal.msg1) { console.log('msg1 is change') } if (newVal.msg2 != oldVal.msg2) { console.log('msg2 is change') } }, deep: true } } }
14-4 注销 watch
const unWatch = app.$watch('text', (newVal, oldVal) => {
console.log(`${newVal} : ${oldVal}`);
})
3.如何注销?
const unWatch = app.$watch('text', (newVal, oldVal) => {
console.log(`${newVal} : ${oldVal}`);
})
unWatch(); // 手动注销watch
app.$watch
调用后会返回一个值,就是unWatch
方法,你要注销 watch 只要调用unWatch
方法就可以了。
15.函数式组件:
一般适合只依赖于外部数据的变化而变化的组件,因其轻量,渲染性能也会有所提高。
创建函数式组件也很简单,只需要在模板添加 functional 声明即可
子组件
<template functional>
<div class="list">
<div class="item" v-for="item in props.list" :key="item.id" @click="props.itemClick(item)">
<p>{{item.title}}</p>
<p>{{item.content}}</p>
</div>
</div>
</template>
父组件
<template> <div> <List :list="list" :itemClick="item => (currentItem = item)" /> </div> </template>
import List from '@/components/List.vue' export default { components: { List }, data() { return { list: [{ title: 'title', content: 'content' }], currentItem: '' } } }
16.路由参数解耦
将路由的 props 属性设置为 true 后,组件内可通过 props 接收到 params 参数
const router = new vueRouter({ routes: [{ path: '/user/:id', component: User, props: true }] })
另外还可以通过函数模式来返回 props
const router = new vueRouter({ routes: [{ path: '/user/:id', component: User, props: (route) => ({ id: route.query.id }) }] })
可通过 props 接收参数
export default { props: ['id'], methods: { getParamsId() { return this.id } } }
16.params传参问题
params传参时,如果没有在路由中定义参数,也是可以传过去的,同时也能接收到,但是一旦刷新页面,这个参数就不存在了。
这对于需要依赖参数进行某些操作的行为是行不通的.
// 定义的路由中,只定义一个id参数 { path: 'detail/:id', name: 'Detail', components: Detail } // template中的路由传参, // 传了一个id参数和一个token参数 // id是在路由中已经定义的参数,而token没有定义 <router-link :to="{name: 'Detail', params: { id: 1, token: '123456' }}">前往Detail页面</router-link> // 在详情页接收 created () { // 以下都可以正常获取到 // 但是页面刷新后,id依然可以获取,而token此时就不存在了 const id = this.$route.params.id; const token = this.$route.params.token; }
17.定时器问题
通过$once这个事件侦听器器在定义完定时器之后的位置来清除定时器
const timer = setInterval(() =>{ // 某些定时器操作 }, 500); // 通过$once来监听定时器,在beforeDestroy钩子可以被清除。 this.$once('hook:beforeDestroy', () => { clearInterval(timer); })
18.props验证
props: { status: { type: String, //数据类型 required: true, //是否验证 validator: function (value) { //验证函数 return [ //验证结果 'success', 'error', ].indexOf(value) !== -1 } } }
19.路由组件复用
在开发当中,有时候我们不同的路由复用同一个组件,默认情况下,我们切换组件,Vue
出于性能考虑可能不会重复渲染。
但是我们可以通过给router-view
绑定一个key
属性来进行切换的时候路由重复渲染。
<template> <router-view :key="$route.fullPath"></router-view> </template>
20批量属性继承
使用$props
将父组件的所有的props
传递到子组件
场景 : 从父组件接收传递下来的数据使用props
接收,再将这些props
数据传递到子组件
<template> <!-- 将从父组件接收到的props数据传递到子组件 使用v-bind="$props" 批量传递 --> <childComponent v-bind="$props" /> </template> <script> export default { // 从父组件接收到的props数据 props: ['value1','value2','value3','value4','value5'], data() { return {....} ..... } } // childComponent.vue <script> export default { props: ['value1','value2','value3','value4','value5'], data() { return {....} ..... }, mounted() { // 子组件可以接收到数据 console.log(this.value1) console.log(this.value2) console.log(this.value3) console.log(this.value4) console.log(this.value5) } } </scrript>
属性继承在开发表单组件时,使用$props
就可以很好的解决批量属性传递问题。
21.组件懒加载(异步加载组件)
1.为什么要用
所有的组件代码都会在首次渲染是下载 , 体验不佳
2.什么场景用
比如后台管理页面,在多个tab之间切换的时候,其余tab里面的组件就可以在需要的时候再异步加载~
有多个子路由的页面必用
3.如何用?
components: { test: () => import("./Test.vue") },
给加载js命名
components: { test: () => import(/* webpackChunkName:'test' */ "./Test.vue"), //给加载js命名 },
处理加载状态的写法
异步组件工程函数
const AsyncTest = () => ({ component: import(/* webpackChunkName:'test' */ "./Test.vue"), loading: LoadingComponent, //加载时显示的组件 error: ErrorComponent, //超时或错误时显示的组件 delay: 200, //延迟 timeout: 3000, //超时 });
22.解决async/await异步问题
使用 await 1; 解决异步
例子:
async created(){ try { //捕获await错误信息 this.couponArr = await this.getData({form_id:11,pageSize:9}).then(res=>{ if(res.length>8){ res.pop(); this.couponBtn=true; return res; } return res; }); this.storeArr1[this.currentIndex]= await this.getData({form_id:8,position_ename:'nav1-1',pageSize:4}); this.currentArr = this.storeArr1[this.currentIndex]; this.storeArr2 = await this.getData({form_id:18,pageSize:5}).then(res=>{ if(res.length>4){ res.pop(); this.bandanBtn=true; return res; } return res; }); this.storeArr3 = await this.getData({form_id:8,position_ename:'nav3'}); } catch (e) { console.log(e) } await 1; //解决异步 this.gundong() this.navFixed({ navParent: '.nav_box', nav: '.nav', navItem: '.nav li', itemParent: '.tit', active: 'active', fixedTop: '0', deviation: parseFloat($('.nav').height()), animateTime: 500, flag: 0 }) this.tab() this.xuanran(); this.videoHandle(); this.gtOrltVisible() this.swiperHandle() this.staticImg() },
23.滚动节流
passive: 是告诉浏览器,监听器不会调用e.preventDefault()函数,不用来检查,可以提前生成手势,从而提高流畅性,通常用在move事件中
例子:
<template> <div class="scroll"> <div class="containers" @scroll.passive="scrollHandle"> <div class="content"> <ul> <li v-for="item in 100">{{ item }}</li> </ul> </div> </div> </div> </template> <script> export default { name: "Scroll", components: {}, data() { return { scrollHandle: () => {}, }; }, created() { this.scrollHandle = this.throttle(this.scrollHandle2, 200); }, methods: { scrollHandle2(e) { console.log(456); }, throttle(func, delay = 800) { let lock = false; return (...args) => { if (lock) { return; } func(...args); lock = true; setTimeout(() => { lock = false; }, delay); }; }, }, }; </script> <style scoped > .containers { height: 500px; border: 1px solid #000; overflow: scroll; } </style>
24.$destroy()方法问题
某种业务场景下,我们期望缓存的页面可以被销毁,就会调用$destroy方法,这回导致被销毁的页面,虽然会触发activated钩子函数,但是页面实际上没有被缓存,重新进入是初始dom结构的状态。
24.数据更新,update()/beforeUpdate()未触发问题
页面使用到的数据改变时才会更新 updated 和 beforedate钩子函数
...