二、Vue重要知识点-概述

126 阅读2分钟

1、计算属性 vs 监听器

1.1、监听器更通用 理论上计算属性能实现的侦听器也能实现 处理数据的场景不同,

1.2、监听器适合一个数据影响多个数据,计算属性适合一个数据受多个数据影响

1.3、计算属性有缓存性 计算所得的值如果没有变化不会重复执行

1.4、监听器适合执行异步操作或较大开销操作的情况

watch:

选项:deep

为了发现对象内部值的变化,可以在选项参数中指定 deep: true注意监听数组的变更不需要这么做。

选项:immediate

在选项参数中指定 immediate: true 将立即以表达式的当前值触发回调。

2、神奇的模板语法是如何实现的

在底层的实现上,Vue 将模板编译成虚拟 DOM 渲染函数。结合响应系统,Vue 能够智能地计算出最少 需要重新渲染多少组件,并把 DOM 操作次数减到最少。

// 输出vue替我们生成的渲染函数一窥究竟
console.log(app.$options.render)

// 它长这个样子
(function anonymous(
){
with(this){return _c('div',{attrs:{"id":"app"}},[_c('h2',{attrs: {"title":title}},[_v("\n "+_s(title)+"\n ")]),_v(" "),_c('input',{directives:[{name:"model",rawName:"v-model",value: (course),expression:"course"}],attrs:{"type":"text"},domProps:{"value": (course)},on:{"keydown":function($event) {if(!$event.type.indexOf('key')&&_k($event.keyCode,"enter",13,$event.key,"Enter" ))return null;return addCourse($event)},"input":function($event) {if($event.target.composing)return;course=$event.target.value}}}),_v(" "),_c('button',{on:{"click":addCourse}},[_v("新增课程")]),_v(" "),(courses.length == 0)?_c('p',[_v("没有任何课程信息")]):_e(),_v(" "),_c('ul',_l((courses),function(c){return _c('li',{class:{active: (selectedCourse === c)},on:{"click":function($event){selectedCourse = c}}}, [_v(_s(c))])}),0)])}
})

改写为渲染函数版本试试,02-cart-render.html,功能一模一样

const app = new Vue({
// 引入上面的render函数 render() {
with (this) { return ... } }
})

结论:Vue通过它的编译器将模板编译成渲染函数,在数据发生变化的时候再次执行渲染函数,通过对 比两次执行结果得出要做的dom操作,模板中的神奇魔法得以实现。

如果你熟悉虚拟 DOM 并且偏爱 JavaScript 的原始力量,也可以不用模板,直接写渲染 (render) 函数

这些功能到底是怎么实现的,我们将继续探究.....

3、探讨生命周期

3.1、从一道面试题开始

关于Vue的生命周期,下列哪项是不正确的?()[单选题]

A、Vue 实例从创建到销毁的过程,就是生命周期。

B、页面首次加载会触发beforeCreate, created, beforeMount, mounted, beforeUpdate, updated。

C、created表示完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来。

D、DOM渲染在mounted中就已经完成了。

3.2、结论:

三个阶段:初始化、更新、销毁

初始化:beforeCreate、created、beforeMount、mounted

更新:beforeUpdate、updated

销毁:beforeDestroy、destroyed

也有常用:

3.3、使用场景分析:通常使用:带上before的用的少

{
    beforeCreate(){} // 执行时组件实例还未创建,通常用于插件开发中执行一些初始化任务 
    created(){} // 组件初始化完毕,各种数据可以使用,常用于异步数据获取 

    beforeMount(){} // 未执行渲染、更新,dom未创建
    mounted(){} // 初始化结束,dom已创建,可用于获取访问数据和dom元素 

    beforeUpdate(){} // 更新前,可用于获取更新前各种状态
    updated(){} // 更新后,所有状态已是最新

    beforeDestroy(){} // 销毁前,可用于一些定时器或订阅的取消,组件实例还在
    destroyed(){} // 组件已销毁,作用同上,组件实例不在了
}

4、组件

0、为什么组件化:!!!软件工程化:高内聚、低耦合。

1、推荐引入组件也是羊肉串命名法。减少引入是驼峰,(ele中使用是羊肉串)的转换和混淆。组件自定义事件也是羊肉串命名,同理。

2、props:传入数据,最好都是约定好的类型,对象key:value/default,让程序更健壮。

3、组件内的data: 必须是函数式的return {}。原因很简单:组件可能是多实例的应用,要保证每个实例的data互不影响,没有引用相同的数据源。

4、vue组件/react组件 都是《单根元素》。

4.1、父级组件收到子级组件事件的数据,减少写冗余的事件函数, 可以直接使用 $event 拿到值。

<message :show="show" @close="show=$event"></message>

4.2、新出了 .sync 语法糖,减少老爹的冗余事件函数

// 父组件
// 类似show.sync="show" @update:show="xxxxx"
<message :show.sync="show"></message>
  
  
// 子组件,约定死了自定义事件名称 'update:show'。

Vue.component('message', { props: ['show'], template: `
<div class="message-box" v-if="show"> 
	...
        <span @click="$emit('update:show',false)">x</span>
</div>	

5、组件上使用 v-model 只是一个语法糖 (让组件内部无状态,更依赖父级组件,变得更复用)

方法1、(常用)

<!-- 自定义组件支持v-model需要实现内部input的:value和@input -->
props: ['value'],
methods:{
    onXxx(e){
        this.$emit('input',e.target.value);
    }
}

方法2、 (推荐) 2.2.0+ 新增

v-model默认转换是:value和@input,如果想要修改这个行为,可以通过定义model选项

Vue.component('base-checkbox', {
  model: {
    prop: 'checked',
    event: 'change'
  },
  props: {
    checked: Boolean
  },
  template: `
    <input
      type="checkbox"
      v-bind:checked="checked"
      v-on:change="$emit('change', $event.target.checked)"
    >
  `
})

5、通过插槽分发内容

原因:(让组件内部无状态,更依赖父级组件,变得更复用) ),类似:厕所留下几个坑位,将来谁来,我不管!

1、通过使用vue提供的 元素可以给组件传递内容。 具名插槽、默认插槽、作用域插槽

<message :show.sync="show">
	<template v-slot:title>{{titleText}}</template> 
 	<template>新增课程成功!</template>
</message>
...
data:{titleText:'恭喜'}

// 具名插槽、默认插槽

Vue.component('message', { props: ['show'], template: `
<div class="message-box" v-if="show"> 
    <slot name="title"></slot>
    <slot></slot>
</div>	
`
})

// 作用域插槽
// 插槽内容里面的变量 又来自子组件中,需要临时的改变上下文

// 父级
<message :show.sync="show">
    <template v-slot:title="slotSelf">{{slotSelf.titleText}}</template> 
</message>

// 子级
Vue.component('message', { props: ['show'], template: `
<div class="message-box" v-if="show"> 
    <slot name="title" titleText="子级自己的变量哦">默认标题</slot>
</div>