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-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
*/编译作用域
父组件的模板的内容在父组件作用域内编译
子组件的模板的内容在子组件作用域内编译
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实例在某一个时间点会自动执行的函数
挂载阶段 更新阶段 销毁阶段
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.js1
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)
})