自学Vue 11天!!!
自学Vue 11天!!!既昨天的内容继续往下。四、Watch(熟悉)watch的作用可以监控一个值的变换,并调用因为变化需要执行的方法。可以通过watch动态改变关联的状态。简单点说,就是实时监听某个数据的变化。1、普通监听<template><div class="home"><input type="text" v-model="msg"><h3>
既昨天的内容继续往下。
四、Watch(熟悉)
watch的作用可以监控一个值的变换,并调用因为变化需要执行的方法。可以通过watch动态改变关联的状态。
简单点说,就是实时监听某个数据的变化。
1、普通监听
<template>
<div class="home">
<input type="text" v-model="msg">
<h3>{{msg}}</h3>
</div>
</template>
<script>
export default {
name: 'Home',
data(){
return {
msg: "你好,世界"
}
},
watch: {
msg(val, oldVal){
console.log(val, oldVal)
}
}
}
</script>
2、立即监听
如果我们需要在最初绑定值的时候也执行函数,则就需要用到immediate属性。
<template>
<div class="home">
<input type="text" v-model="num">
</div>
</template>
<script>
export default {
name: "Home",
data() {
return {
num: 20
};
},
watch: {
num: {
handler(val, oldVal) {
console.log(val, oldVal);
},
// 组件注入页面时就立即监听
immediate: true
}
}
};
</script>
immediate需要搭配handler一起使用,其在最初绑定时,调用的函数也就是这个handler函数。
3、深度监听
当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听。
<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: {
handler(val, oldVal){
console.log(val.age, oldVal.age) // 33 33
},
deep: true
}
}
}
</script>
注意:
1、如果监听的数据是一个对象,那么
immediate: true
失效;2、一般使用于对引用类型的监听,深度监听,如监听一个Object,只要Object里面的任何一个字段发生变化都会被监听,但是比较消耗性能,根据需求使用,能不用则不用。
3、因为上面代码obj是引用数据类型,val, oldVal指向一致,导致看到的结果一样。
4、deep优化
<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, oldVal);
},
deep: true,
immediate: true, // 此时监听的数据不是一个对象,可以使用immediate
}
}
};
</script>
5、Watch与Computed的区别
-
watch中的函数是不需要调用的,computed内部的函数调用的时候不需要加()
-
watch(属性监听),监听的是属性的变化,而computed(计算属性),是通过计算而得来的数据
-
watch需要在数据变化时执行异步或开销较大的操作时使用,而对于任何复杂逻辑或一个数据属性,在它所依赖的属性发生变化时,也要发生变化,这种情况下,我们最好使用计算属性computed。
-
computed 属性的结果会被缓存,且computed中的函数必须用return返回最终的结果
-
watch 一个对象,键是需要观察的表达式,值是对应回调函数。主要用来监听某些特定数据的变化,从而进行某些具体的业务逻辑操作;
6、Watch与Computed的使用场景
-
computed
-
当一个结果受多个属性影响的时候就需要用到computed
-
最典型的例子: 购物车商品结算的时候
-
-
watch
-
当一个数据的变化需要有往外操作的时候就需要用watch
-
搜索数据
-
-
总结:
-
一个值的结果受其他值的影响,用computed
-
一个值的变化将时刻影响其他值,用watch
-
五、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名。然后通过refs来进行绑定这个元素
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标签
}
}
};
</script>
<style lang = "less" scoped>
</style>
2、子组件中的数据获取及方法调用
子组件:
<template>
<div class="">
<h4>{{num}}</h4>
</div>
</template>
<script>
export default {
data() {
return {
num: 100
};
},
methods: {
subFn(){
console.log('子组件中的方法')
}
}
};
</script>
<style lang = "less" scoped>
</style>
父组件:
<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>
<style lang = "less" scoped>
</style>
七、(重点)KeepAlive
<keep-alive>
是Vue的内置组件,能在组件切换过程中将状态保留在内存中,防止重复渲染DOM。
KeepAlive用于处理组件缓存。有什么用呢?想象一个业务场景:
在Login页面填写完手机号,发现未注册,需要跳去Register页面完成注册,再返回Login页面填写密码,进行登录,此时如果在Login页面没有保存好手机号,那么跳回来时,用户又得重新输入手机号。为了解决这样的需求,我们需要借助keep-alive。
这里,我们新创建两个页面, You.vue
和 Me.vue
,并且都实现累加功能。
1、修改App.vue
// 将原本的:
<router-view/>
// 修改为:
<keep-alive>
<router-view/>
</keep-alive>
这样,我们实现了整个项目中每个页面的缓存,显然我们不想这么做,我们只想针对某些页面,这时,我们修改一下:
<keep-alive>
<router-view v-if="$route.meta.keepAlive" />
</keep-alive>
<router-view v-if="!$route.meta.keepAlive" />
注意:
<keep-alive>
是用在其一个直属的子组件被开关的情形。如果你在其中有v-for
则不会工作。
那这里的 $route.meta.keepAlive
存在于哪里呢?
2、Router中的meta
这是写在路由文件中的字段,我们去 router/index.js
中,将我们要缓存的 Me.vue
页面加上meta:
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue'
Vue.use(VueRouter)
const routes = [
...,
{
path: '/me',
name: 'Me',
component: () => import('../views/Me.vue'),
meta: {
keepAlive: true
}
},
{
path: '/you',
name: 'You',
component: () => import('../views/You.vue')
}
]
const router = new VueRouter({
mode: 'history',
base: process.env.BASE_URL,
routes
})
export default router
八、Vue生命周期
什么是生命周期: 从Vue创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期。
生命周期钩子函数:就是生命周期事件的别名;
初始
beforeCreate:实例刚刚在内存中被创建出来,此时还没有初始化 data
和 methods
属性。
created:实例已经在内存中创建好,此时 data
和methods
已经创建好,此时还没有开始编译模板
挂载
beforeMount:此时已经完成了模板编译,但是还没有挂载到页面中;
mounted:这个时候已经把编译好的模板挂载到页面指定的容器里;
beforeMount:
data
的数据可以访问和修改,而且此时的模板已经编译好了,还没有更新到页面中
mounted:
此时编译的模板更新到页面中了
更新
beforeUpdate:状态更新之前执行此函数,此时的 data
中的数据是最新,但是界面上显示的还是旧的,因为此时还没有开始重新渲染DOM节点;
updated:实例更新完毕之后调用此函数,此时data
中的状态值和界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了;
beforeUpdate: 此时修改输入框的内容,
data
中的数据已经更新了,但是页面上显示的还是旧数据;updated:此时
data
的内容已经更新,页面显示的也是最新的数据。
<template>
<div>
<p ref="run">{{ num }}</p>
<button @click="num++">按钮</button>
</div>
</template>
<script>
import Comp from "@/components/Comp7Ch.vue";
export default {
data() {
return {
num: 20,
isC: true,
};
},
components: {
},
methods: {
fn() {
console.log("这是函数");
},
},
beforeCreate() {
// 组件创建之前执行的函数,(数据、方法、标签都获取不到)
console.log("1.1--beforeCreate", this.num, this.fn, this.$refs.run);
},
created() {
// 发起异步请求,获取数据
// 组件创建之后执行的函数,(数据、方法已经可以获取,标签获取不到)
console.log("1.2--created", this.num, this.fn, this.$refs.run);
},
beforeMount() {
// 组件挂载数据之前执行的函数,(数据、方法已经可以获取,标签获取不到)
console.log("2.1--beforeMount", this.num, this.fn, this.$refs.run);
},
mounted() {
// 组件挂载数据之后执行的函数,(数据、方法、标签都可以获取得到)
console.log("2.2--mounted", this.num, this.fn, this.$refs.run);
},
beforeUpdate() {
// 界面更新之前的函数
console.log("3.1--beforeUpdate", this.num, this.fn, this.$refs.run);
},
updated() {
// 界面更新之后的函数
console.log("3.2--update", this.num, this.fn, this.$refs.run);
},
};
</script>
<style lang = "less" scoped>
</style>
销毁
beforeDestroy:实例销毁之前调用,在这一步,实例让然完全可用。
destroyed:实例销毁后调用,调用后,Vue实例指向的所以东西会被解绑,所有的事件监听器会被移除,所有的子实力也会被销毁。
新建一个名为:Comp7Ch.vue
的子页面:
<template>
<div>
这是comp7的子组件
</div>
</template>
<script>
export default {
data () {
return {
}
},
beforeDestroy() {
// 组件销毁之前执行这个函数, 回收 和清理工作, 比如清除定时器,清除全局事件
console.log("4.1---beforeDestroy");
},
destroyed() {
console.log("4.2---destroyed");
},
}
</script>
<style lang = "less" scoped>
</style>
在刚刚那个页面进行引入,观察他的页面销毁时执行的顺序与内容:
<template>
<div>
<p ref="run">{{ num }}</p>
<button @click="num++">按钮</button>
<Comp v-if="isC" />
<button @click="isC = !isC">按钮2</button>
</div>
</template>
<script>
import Comp from "@/components/Comp7Ch.vue";
export default {
data() {
return {
num: 20,
isC: true,
};
},
components: {
Comp,
},
......
更多推荐
所有评论(0)