vue组件、动画、生命周期

Vue.js是一个构建数据驱动的web界面的库,是一套用于构建用户界面的渐进式框架. 目标是通过尽可能简单的API实现响应的数据绑定和组合的视图组件。核心是一个响应的数据绑定系统,它让数据与DOM保持同步非常简单。

vue组件

vue中组件是组件是一组可被复用的具有一定功能,独立的完整的代码片段,这个代码片段可以渲染一个完整的视图结构,每一个组件都是一个vue实例对象,都会包含vue实例的所有属性和方法

vue组件分类:

  • vue-router对应的每一个.vue页面组件
  • 不包含业务的、独立的基础功能组件如UI组件,具有通用性可以在不同项目中使用
  • 只包含某个功能的业务组件、只在当前项目中使用不具有通用性

vue组件的三个API: prop、event、slot

一个再复杂的组件,都是由三部分组成的:prop、event、slot,它们构成了 Vue.js 组件的 API

  • 属性props定义了有哪些可配置的属性,写通用组件时,props最好用对象的写法,便于设置每个属性的类型、默认值和校验属性的值

组件使用步骤 1. 引入组件 2. 注册组件 3. 使用组件
组件

  • 全局组件 可以在任何模板中使用,使用之前需要先注册

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    // 注册 Vue.component(‘组件名’,选项对象)
    // Vue.component(‘my-component’,{})
    // 使用 <my-component></my-component>
    <div id='app'><Counter /></div>
    Vue.component('Counter', {
    template: '<span>{{text}}</span>',
    data () {
    return {
    text: '全局组件'
    }
    }
    })
  • 局部组件 在组件实例中通过选项对象注册,只在所注册的作用域中使用

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    // 注册 components:{ 组件名:选项对象 }
    // 子组件中的data必须是函数
    // 每个组件都是相互独立的,如果共用一个对象,产生引用关系,在更改一个的时候,会影响其他组件.
    // 但如果是函数,每个组件都有自己独立的作用域,不会互相影响
    new Vue({
    el: '#app',
    components: {
    'Counter': {
    template: '<span>{{text}}</span>',
    data () {
    return {
    text: '全局组件'
    }
    }
    }
    }
    })
  • 组件可多次使用
    组件多次使用

  • 不希望Vue重复利用的问题,可以给对应的组件添加不同的key,key的作用主要是为了高效的更新虚拟DOM。

动态组件

多个组件可以使用同一个挂载点,动态地在他们之间切换,使用保留的<component>元素,使用is特性进行动态绑定
可以使用keep-active把切出去的组件保留在内存中,这样还可以保留它的状态及样式,避免重新渲染或者使用 v-once
<component :is="组件名称"></component>
组件多次使用

vue 单向数据流

数据从父组件流向(传递)给子组件.只能单向绑定,在子组件内部不应该修改父组件传递过来的数据 会报错
解决办法:

  • props作为子组件data中局部数据的初始值使用 克隆一份数据改变自己的
    组件多次使用
  • 作为子组件中的computed属性
    组件多次使用

slot插槽

使用一种方式混合父组件的内容与子组件自己的模板,这个过程被称为内容分发
在子组件中使用元素作为内容测插槽,这样会使组件的可扩展性更强

  • 单个slot

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    // 1. 在子组件模板中有slot标签,被视为备用内容,在父组件不提供内容的情况下使用`
    <div id='app'>
    <h2>自定义组件</h2>
    <myslot></myslot>
    </div>
    Vue.component('myslot', {
    template: `
    <div>
    <slot>我是默认的slot</slot>
    <p>这是一个提醒</p>
    </div>`
    })
    /*
    自定义组件
    我是默认的slot
    这是一个提醒
    */
    // 2. 如果父组件提供内容,则把整个内容插入到slot所在的位置,并替换掉slot本身
    <div id='app'>
    <h2>自定义组件</h2>
    <myslot>
    <div>我是父组件的内容</div>
    </myslot>
    </div>
    Vue.component('myslot', {
    template: `
    <div>
    <slot>我是默认的slot</slot>
    <p>这是一个提醒</p>
    </div>`
    })
    /*
    自定义组件
    我是父组件的内容
    这是一个提醒
    */
    // 3. 子组件模板中没有solt标签,父组件提供的内容会被抛弃
    <div id='app'>
    <h2>自定义组件</h2>
    <myslot>
    <div>我是父组件的内容</div>
    </myslot>
    </div>
    Vue.component('myslot', {
    template: `
    <div>
    <p>这是一个提醒</p>
    </div>`
    })
    /*
    自定义组件
    这是一个提醒
    */
  • 具名slot插槽
    <slot>元素可以用一个特殊的属性name来配置如何发布内容.可以使用匿名的的slot,处理那些没有对应的slot的内容
    具名slot插槽

  • slot-scope作用域插槽
    父组件替换插槽的标签,父组件决定怎么展示,但是内容由子组件来提供。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    // 子组件中包括一组数据,比如:pLanguages: ['JavaScript', 'Python', 'Swift', 'Go', 'C++']
    Vue.component('MySlot',{
    template: `<div :data="pLanguages"></div>`,
    data () {
    return {
    pLanguages: ['JavaScript', 'Python', 'Swift']
    }
    }
    })
    // 需要在多个界面进行展示:某些界面是以水平方向展示的,某些界面是以列表形式展示的
    // 内容在子组件,希望父组件告诉我们如何展示
    // 在父组件使用我们的子组件时,从子组件中拿到数据:
    // 我们通过<template slot-scope="slotProps">获取到slotProps属性
    // 在通过slotProps.data就可以获取到刚才我们传入的data了
    // 父组件
    <div id="app">
    <!-- 列表展示 -->
    <MySlot>
    <template slot-scope="slotProps">
    <ul>
    <li v-for="(item,index) of slotProps.data">{{item}}</li>
    </ul>
    </template>
    </MySlot>
    </div>
    /*
    . JavaScript
    . Python
    . Swift
    */
    <div id="app">
    <!-- 水平展示 -->
    <MySlot>
    <template slot-scope="slotProps">
    <span v-for="(item,index) of slotProps.data">{{item}} </span>
    </template>
    </MySlot>
    </div>
    /*
    JavaScript Python Swift
    */
  • 编译作用域
    父组件的模板的内容在父组件作用域内编译
    子组件的模板的内容在子组件作用域内编译
    具名slot插槽

Vue动画

  • 单元素/组件的过渡

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    <!-- <transition name="fade" appear> appear 设置初始渲染就有过渡效果  -->
    <transition name="fade">
    <p v-if="show">hello</p>
    </transition>
    <style>
    /* 过渡类名
    name="fade" 过渡类名的前缀可自定义 默认前缀 v-
    v-enter:定义进入过渡的开始状态。在元素被插入之前生效,在元素被插入之后的下一帧移除
    v-enter-active:定义进入过渡生效时的状态。在整个进入过渡的阶段中应用,在元素被插入之前生效,
    在过渡/动画完成之后移除。这个类可以被用来定义进入过渡的过程时间,延迟和曲线函数
    v-leave-active:定义离开过渡生效时的状态。在整个离开过渡的阶段中应用,在离开过渡被触发时立刻生效,
    在过渡/动画完成之后移除。这个类可以被用来定义离开过渡的过程时间,延迟和曲线函数。
    v-leave:定义离开过渡的开始状态。在离开过渡被触发时立刻生效,下一帧被移除。
    */
    .fade-enter-active, .fade-leave-active {
    transition: opacity .5s;
    }
    .fade-enter, .fade-leave-to {
    opacity: 0;
    }
    </style>
    <script>
    /* 动画过渡钩子函数
    v-on:before-enter="beforeEnter" 动画执行之前
    v-on:enter="enter" 动画执行过程中
    v-on:after-enter="afterEnter" 动画执行之后
    v-on:before-leave="beforeLeave" 动画执行完成之前
    v-on:leave="leave" 动画执行完成过程中
    v-on:after-leave="afterLeave" 动画执行完成之后
    // 回调函数 done 是可选的
    enter: function (el, done) {
    // ...
    done()
    },
    // 回调函数 done 是可选的
    leave: function (el, done) {
    // ...
    done()
    },
    */
    </script>
  • 过渡模式 mode="out-in或in-out"

    1
    2
    3
    4
    5
    6
    7
    8
    <!-- 1. 当有相同标签名的元素切换动画时,需要加上key区分,否则动画会有问题
    2. in-out: 新元素先进行过渡,完成之后当前元素过渡离开 (不常用)
    3. out-in: 当前元素先进行过渡,完成之后新元素过渡进入 -->
    <transition name="fade" mode="out-in" appear>
    <p v-if="show" key="hello">hello</p>
    <p v-else key="world">world</p>
    </transition>
    <button @click="show = !show">sasas</button>
  • 列表过渡

    1
    2
    3
    4
    5
    6
    <!-- transition-group 会渲染成真实DOM元素 默认为span 可通过tag更换为其他元素  -->
    <transition-group tag="ul" name="slide">
    <li v-for="item in items" :key="item.id">
    {{ item.text }}
    </li>
    </transition-group>
  • Vue动画详情

Vue生命周期函数

生命周期函数就是vue实例在某一个时间点会自动执行的函数
挂载阶段 更新阶段 销毁阶段

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
//vue实例部分初始化的时候 组件实例刚刚被创建 属性都没有
beforeCreate:function(){
console.log('beforeCreate')
},
//vue实例初始化完成 属性已经绑定
created:function(){
console.log('created')
},
//页面渲染之前 模板编译之前 dom还未显示
beforeMount:function(){
console.log('beforeMount')
},
//页面渲染完毕 (才有$el对象) dom显示完成
mounted:function(){
console.log('mounted');
},
//vue实例被销毁之前 组件销毁前 操作: 解除绑定 销毁子组件及事件监听器
beforeDestroy:function(){
console.log('beforeDestroy')
},
//vue实例被销毁 组件销毁后
destroyed:function(){
console.log('destroyed')
},
//数据发生改变未渲染之前
beforeUpdate:function(){
console.log('beforeUpdate')
},
//数据发生改变渲染完毕
updated:function(){
console.log('updated')
}
// 组件使用keep-alive专有
activated: function(){
console.log('activated')
}
deactivated: function(){
console.log('deactivated')
}

Runtime-Compiler和Runtime-only的区别

vue有两种形式的代码 compiler(模板)模式和runtime模式(运行时)
如果在之后的开发中,你依然使用template,就需要选择Runtime-Compiler
如果你之后的开发中,使用的是.vue文件夹开发,那么可以选择Runtime-only
Runtime-only 性能更好 体积更小
vue模块的package.json的main字段默认为runtime模式, 指向了”vue/dist/vue.runtime.common.js”位置。
如要使用template修改vue指向 vue/dist/vue.esm.js

1
2
3
4
5
6
7
8
9
10
11
// Runtime-Compiler
new Vue({
el: '#app',
component: { App },
template: '<App />'
})
// Runtime-Only
new Vue({
el: '#app',
render: h => h(App)
})

-------------本文结束感谢您的阅读-------------
0%