天天看点

Vue的学习总结自测(四)——v-model的原理,组件data为什么是一个函数,keep-alive,父组件监听子组件的生命周期11、父组件监听子组件的生命周期12.keep-alive13、组件中 data 为什么是一个函数14、v-model 的原理?

继上一篇:

Vue的学习总结自测(三)——computed 和 watch 的区别、vue不能检测到数组、对象的变动

本文目录:

  • 父组件监听子组件的生命周期
  • keep-alive
  • 组件中 data 为什么是一个函数?
  • v-model 的原理

11、父组件监听子组件的生命周期

比如有父组件 Parent 和子组件 Child,如果父组件监听到子组件挂载 mounted 就做一些逻辑处理,可以通过以下写法实现:

// Parent.vue
<Child @mounted="doSomething"/>

// Child.vue
mounted() {
  this.$emit("mounted");
}
           

以上需要手动通过 $emit 触发父组件的事件,更简单的方式可以在父组件引用子组件时通过 @hook 来监听即可,如下所示:

//  Parent.vue
<Child @hook:mounted="doSomething" ></Child>

doSomething() {
   console.log('父组件监听到 mounted 钩子函数 ...');
},

//  Child.vue
mounted(){
   console.log('子组件触发 mounted 钩子函数 ...');
},    

// 以上输出顺序为:
// 子组件触发 mounted 钩子函数 ...
// 父组件监听到 mounted 钩子函数 ...
           

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

12.keep-alive

keep-alive 是 Vue 内置的一个组件,可以使被包含的组件保留状态,避免重新渲染 ,其有以下特性:

  • 一般结合路由和动态组件一起使用,用于缓存组件;
  • 提供 include 和 exclude 属性,两者都支持字符串或正则表达式, include 表示只有名称匹配的组件会被缓存,exclude 表示任何名称匹配的组件都不会被缓存 ,其中 exclude 的优先级比 include 高;
  • 对应两个钩子函数 activated 和 deactivated ,当组件被激活时,触发钩子函数 activated,当组件被移除时,触发钩子函数 deactivated。
<keep-alive>
    <loading></loading>
</keep-laive>
           
被keep-alive包裹的动态组件或router-view会缓存不活动的实例,再次被调用这些被缓存的实例会被再次复用,对于我们的某些不是需要实时更新的页面来说大大减少了性能上的消耗,不需要再次发送HTTP请求,但是同样也存在一个问题就是被keep-alive包裹的组件我们请求获取的数据不会再重新渲染页面,这也就出现了例如我们使用动态路由做匹配的话页面只会保持第一次请求数据的渲染结果,所以需要我们在特定的情况下强制刷新某些组件
           

1.利用include、exclude属性

<keep-alive include="bookLists,bookLists">
      <router-view></router-view>
</keep-alive>
<keep-alive exclude="indexLists">
      <router-view></router-view>
</keep-alive>
           

2.官方提出的解决方案响应路由参数的变化

3.利用meta属性

export default[
 {
  path:'/',
  name:'home',
  components:Home,
  meta:{
    keepAlive:true //需要被缓存的组件
 },
 {
  path:'/book',
  name:'book',
  components:Book,
  meta:{
     keepAlive:false //不需要被缓存的组件
 } 
]
           
<keep-alive>
  <router-view v-if="this.$route.meta.keepAlive"></router-view>
  <!--这里是会被缓存的组件-->
</keep-alive>
<keep-alive v-if="!this.$router.meta.keepAlive"></keep-alive>
<!--这里是不会被缓存的组件-->
           

13、组件中 data 为什么是一个函数

为什么组件中的 data 必须是一个函数,然后 return 一个对象,而 new Vue 实例里,data 可以直接是一个对象?
// data
data() {
  return {
    message: "子组件",
    childName:this.name
  }
}

// new Vue
new Vue({
  el: '#app',
  router,
  template: '<App/>',
  components: {App}
})
           

因为组件是用来复用的,且 JS 里对象是引用关系。

  • 如果组件中 data 是一个对象,那么这样作用域没有隔离,子组件中的 data 属性值会相互影响。
  • 如果组件中 data 选项是一个函数,那么每个实例可以维护一份被返回对象的独立的拷贝,组件实例之间的 data 属性值不会互相影响;而 new Vue 的实例,是不会被复用的,因此不存在引用对象的问题。

14、v-model 的原理?

我们在 vue 项目中主要使用 v-model 指令在表单 input、textarea、select 等元素上创建双向数据绑定,我们知道 v-model 本质上不过是语法糖,v-model 在内部为不同的输入元素使用不同的属性并抛出不同的事件:

  • text和textarea元素使用value属性和input时间;
  • checkbox和radio使用checked属性和change事件;
  • select字段将value作为prop并且将change作为事件
以input表单元素为例:
<input v-model = 'something'>
相当于
<input v-bind:value='something' v-on:input='something = $event.target.value'>
           

如果在自定义组件中,v-model 默认会利用名为 value 的 prop 和名为 input 的事件,如下所示:

父组件:
<ModelChild v-model="message"></ModelChild>

子组件:
<div>{{value}}</div>

props:{
    value: String
},
methods: {
  test1(){
     this.$emit('input', '小红')
  },
},
           

继续阅读