一、Watch(熟悉)
watch的作用可以监控一个值的变换,简单点说,就是实时监听某个数据的变化。
<template>
<div class="home">
<h3>{{obj.age}}</h3>
<button @click="btnClick">按钮</button>
</div>
</template>
<script>
export default {
name: 'Home',
data(){
return {
obj: {
name: "Lucy",
age: 13
}
}
},
methods: {
btnClick(){
this.obj.age = 33;
}
},
watch: {
// 通过点语法获取对象中的属性,然后转为字符串,即是对深度监听的优化
"obj.age": { // 此时不是一个对象
handler(val, oldVal){
console.log(val.age, oldVal.age) // 33 33
},
immediate: true // 立即监听 (简单数据类型)
deep: true // 深度监听(复杂数据类型)
}
}
}
</script>
二、Mixins混入(熟悉)
mixins就是定义一部分公共的方法或者计算属性,然后混入到各个组件中使用,方便管理与统一修改。同一个生命周期,混入对象会比组件的先执行。
1、导出mixins
在src下创建 mixins/index.js
,写入:
export const MixinsFn = {
created() {
console.log("这是mixins触发的created")
}
}
2、引用mixins
<template>
<div class="about">
<h1>This is an about page</h1>
</div>
</template>
<script>
import { MixinsFn } from '@/mixins/index.js'
export default {
created(){
console.log("这是about触发的created")
},
mixins: [MixinsFn]
}
</script>
我们会发现,mixins中的created
比 about中的created
优先执行。
三、ref与$refs(掌握)
vue中获取页面里的某个元素(标签或组件),可以给它绑定ref属性,有点类似于给它添加id名。
1、简单使用
<template>
<div class="">
<h3 ref="title">{{msg}}</h3>
<button @click="btnclick">按钮</button>
</div>
</template>
<script>
export default {
data() {
return {
msg: "你好"
};
},
methods: {
btnclick() {
console.log(this.$refs.title); // 得到h3标签
console.log(this.$refs.title.innerHTML); // 得到h3标签的文本
}
}
};
</script>
2、子组件中的数据获取及方法调用
子组件:
<template>
<div class="">
<h4>{{num}}</h4>
</div>
</template>
<script>
export default {
data() {
return {
num: 100
};
},
methods: {
subFn(){
console.log('子组件中的方法')
}
}
};
</script>
父组件:
<template>
<div class="">
<Sub ref="sub" />
<button @click="btnclick">按钮</button>
</div>
</template>
<script>
import Sub from '../components/Sub'
export default {
methods: {
btnclick() {
console.log(this.$refs.sub.num); // 100
this.$refs.sub.subFn(); // '子组件中的方法'
}
},
components: {
Sub
}
};
</script>
四、KeepAlive
<keep-alive>
是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
KeepAlive用于处理组件缓存。有什么用呢?想象一个业务场景:
在Login页面填写完手机号,发现未注册,需要跳去Register页面完成注册,再返回Login页面填写密码,进行登录,此时如果在Login页面没有保存好手机号,那么跳回来时,用户又得重新输入手机号。为了解决这样的需求,我们需要借助keep-alive。
1、keep-alive结合component
首先,创建 a.vue
、b.vue
和 c.vue
三个组件,内容大致如下:
<template>
<li>a组件 <input type="text"></li>
</template>
在某个页面(如:about.vue)中引入:
<template>
<div class="about">
<button @click="mycom='acom'">a组件</button>
<button @click="mycom='bcom'">b组件</button>
<button @click="mycom='ccom'">c组件</button>
<ul>
<component :is="mycom"></component>
</ul>
</div>
</template>
<script>
import acom from '../components/a'
import bcom from '../components/b'
import ccom from '../components/c'
export default {
data(){
return {
mycom: "acom"
}
},
components: {
acom, bcom, ccom
}
}
</script>
到目前为止,我们可以切换组件,但是在切换时却无法缓存组件内容,因此我们给 component 组件套一个 keep-alive
:
// 这样我们在三个组件的 input 中输入的东西就会被缓存。
<keep-alive>
<component :is="mycom"></component>
</keep-alive>
2、include与 exclude
如果我们想缓存指定的组件,可以使用include:
<keep-alive :include="['acom', 'bcom']">
<component :is="mycom"></component>
</keep-alive>
如果我们想排出部分组件的缓存,可以使用exclude:
<keep-alive :exclude="['ccom']">
<component :is="mycom"></component>
</keep-alive>
3、keep-alive生命周期
Keep-alive 生命周期包含:actived
和 deactivated
找到 a.vue
,写入:
<script>
export default {
created(){
console.log('a组件的created')
},
mounted(){
console.log('a组件的mounted')
},
activated(){
console.log('actived: 进入当前组件时触发')
},
deactivated(){
console.log('deactivated:离开当前组件时触发')
}
}
</script>
我们可以观察到两个现象:
- actived在created和mounted之后调用
- deactivated在离开组件时会触发,无论第几次进入组件,actived都会触发,但created和mounted只会触发一次
五、NextTick
1、数据更新延迟的问题
当侦听到你的数据发生变化时, Vue将开启一个队列(该队列被Vue官方称为异步更新队列)。视图需要等队列中所有数据变化完成之后,再统一进行更新。
2、NextTick使用方法
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
NextTick有两种基本使用方法:
// 1、CallBack形式
this.$nextTick(()=>{
console.log(this.$refs.title.innerHTML);
})
// 2、Promise形式
this.$nextTick().then(()=>{
console.log(this.$refs.title.innerHTML);
})
// 案例
<template>
<div class="">
<h2 ref="title">{{num}}</h2>
<button @click="btnClick">按钮</button>
</div>
</template>
<script>
export default {
data() {
return {
num: 1
};
},
methods: {
btnClick() {
this.num++;
console.log(this.$refs.title.innerHTML); // 1
// this.$nextTick(()=>{
// console.log(this.$refs.title.innerHTML); // 2
// })
this.$nextTick().then(()=>{
console.log(this.$refs.title.innerHTML); // 2
})
}
}
};
</script>
3、应用场景
1、如果要在created()
钩子函数中进行的DOM
操作,由于created()
钩子函数中还未对DOM进行任何渲染,所以无法直接操作dom,需要通过$nextTick()
来完成。
created () {
this.$nextTick(()=>{
this.$refs.ptag.innerText = "一个p标签"
})
}
注:在created()
钩子函数中进行的DOM
操作,不使用$nextTick()
会报错:
// Error in created hook: "TypeError: Cannot set property 'innerText' of undefined"
created(){
this.$refs.ptag.innerText = "一个p标签"
}
六、Transition
<transition>
元素作为单个元素/组件的过渡效果。<transition>
只会把过渡效果应用到其包裹的内容上,而不会额外渲染 DOM 元素,也不会出现在可被检查的组件层级中。
<button @click="flag = !flag">切换h3显示</button>
<transition name="fade">
<h3 v-show="flag">你好,标题</h3>
</transition>
export default {
data() {
return {
flag:false
};
},
<style lang="less" scoped>
// 完整写法 需自己修改
.fade-enter, .fade-leave-to{
opacity: 0;
}
.fade-enter-active, .fade-leave-active{
transition: opacity 1s;
}
.fade-enter-to, .fade-leave{
opacity: 1;
}
</style>
一个完整的transiton组件的class类,有6个,通过指定不同的class来添加样式来达到过渡的CSS效果。
- v-enter:定义进入过渡的开始状态。
- v-enter-active:定义进入过渡生效时的状态。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数。
- v-enter-to: 定义进入过渡的结束状态。
- v-leave: 定义离开过渡的开始状态。
- v-leave-active:定义离开过渡生效时的状态。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
- v-leave-to: 定义离开过渡的结束状态。
默认类名是以上6个,如果在transition标签中指定了name=’xxx’,那么6个类名将会变成xxx开头的,例如xxx-enter-active。
七、图片懒加载
1、安装
yarn add vue-lazyload
// 或者
npm i vue-lazyload -S
2、全局引入与配置
import VueLazyload from 'vue-lazyload'
// 配置项
Vue.use(VueLazyload, {
preLoad: 1.3,
// error: 'dist/error.png',
// 这里注意,不能写相对路径,因此打包上线也需要修改这个地址
loading: 'http://codesohigh.com/store-pc/img/img_loading.gif',
attempt: 1
})
3、设定loading大小
在 App.vue
中:
img[lazy="loading"] {
display: block;
width: 30% !important;
height: 30% !important;
margin: 0 auto;
}
4、:src --> v-lazy
<img v-lazy="item...">
八、设置title与favicon.ico
当我们完成项目后,想要在webpack修改 index.html
的title标签,可以在 vue.config.js
中:
module.exports = {
chainWebpack: (config) => {
config.plugin("html").tap((args) => {
args[0].title = "百度";
return args;
});
},
publicPath: "./",
};
如果想改favicon.ico,可以在网上扒一个你想要的,然后替换 public
下的favicon.ico即可。
九、生命周期
// beforeCreate(初始化界面前)
// created(初始化界面后)
// beforeMount(渲染dom前)
// mounted(渲染dom后)
// beforeUpdate(更新数据前)
// updated(更新数据后)
// beforeDestroy(卸载组件前)
// destroyed(卸载组件后)
十、插槽(slot)
作用域插槽的多种写法
// 1、基本写法
<one-comp>
<button slot="btn" slot-scope="scope">按钮{{scope.msg}}</button>
</one-comp>
// 2、基本写法之模板写法
<one-comp>
<template slot="btn" slot-scope="scope">
<button>按钮{{scope.msg}}</button>
</template>
</one-comp>
// 3、指令写法
<one-comp v-slot:btn="scope">
<button>按钮{{scope.msg}}</button>
</one-comp>
// 4、指令写法之模板写法
<one-comp>
<template v-slot:btn="scope">
<button>按钮{{scope.msg}}</button>
</template>
</one-comp>