vue动画及组件
vue动画
transition

示例
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
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="./animate.min.css"> <style lang="scope"> .box{ width: 200px; height: 200px; background-color: pink; }
.v-enter,.v-leave{ transition: 1s all; } </style> </head>
<body>
<div id="app"> <h1>你好 {{names}}</h1> <button @click="isShow=!isShow">button</button> <transition enter-to-class="animated fadeInLeft" leave-to-class="animated fadeOutRight"> <div class="box" v-show="isShow">div</div> </transition> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false
const vm = new Vue({ el: '#app', data: { names: '袁同学!', isShow: true, } }) </script> </body>
</html>
|
动态添加li的缓动效果
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <link rel="stylesheet" href="./animate.min.css"> </head> <body> <div id="app"> <h1>你好 {{names}}</h1> <input type="text" v-model="item" @keydown.enter="add"> <ul> <transition-group duration="1000" enter-to-class="animated fadeInLeft" leave-to-class="animated fadeOutRight" appear> <li v-for="(v,index) in arr" :key="index">{{v}}</li> </transition-group> </ul> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false const vm = new Vue({ el: '#app', data: { names: '袁同学!', arr:[3,2,3,4,5], item:'' }, methods: { add(){ if(this.item){ this.arr.push(this.item) } this.item = '' } }, }) </script> </body> </html>
|
Vue中的组件
概述
组件是一个对象,是模块化的体现,包含了html,css,js,组件的设计是为了复用
全局组件
示例
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
| <div id="app"> <first-component></first-component> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false let firstComponent = Vue.component('firstComponent',{ template:` <h3>{{msg}}</h3> `, data(){ return { msg:'你好!' } } })
const vm = new Vue({ el: '#app', data: { names: '袁同学!', } }) </script>
|
局部组件
示例
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
| <div id="app"> <last-component></last-component> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false
let lastComponent = { name:'lastComponent', template:` <h3>{{msg}}</h3> `, data(){ return{ msg:'hello' } }, } const vm = new Vue({ el: '#app', data: { names: '袁同学!', }, components:{ lastComponent } }) </script>
|
组件使用的注意事项
- 组件内部的属性和vue实例的属性是一致的(Vue实例是最大的组件)
- 组件内部的data是一个函数,通过对象的形式返回数据(如果是对象的形式可能会和其他组件的data产生冲突,导致对象覆盖问题,从而造成全局污染)
- 组件内的显示利用template属性,template对外暴露的元素根节点只能有一个,否则会报错
- 组件的使用直接把组件名当做标签名(不能使用驼峰命名法,使用-来分割驼峰)
- 组件的使用可以是单标签也可以是双标签
组件切换
利用内置组件component中的is来切换
示例
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
| <div id="app"> <h1>你好 {{names}}</h1> <button @click="name=(name=='one'?'two':'one')">toggle</button> <component :is="name"></component> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false let one = { name: 'one', template: ` <div>组件one</div> ` } let two = { name: 'two', template: ` <div>组件two</div> ` } const vm = new Vue({ el: '#app', data: { names: '袁同学!', name: 'one' }, components: { one, two } }) </script>
|
组件之间的关系
主要关系
组件之间的通信
父传子(props)
利用子组件的props属性,可以接受父组件所有的属性
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 54 55 56 57 58 59 60
| <div id="app"> <parent></parent> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false
let child = { template:` <h5> {{msg}} {{message}} </h5> `, data(){ return{ msg:'子组件' } },
props:{ message:{ default:'这是默认值default', type:String } } } let parent = { template:` <h3> {{msg}} <child :message='message'></child> </h3> `, data(){ return{ msg:'父组件', message:'来自父组件的数据' } }, components:{ child } }
const vm = new Vue({ el: '#app', data: {
}, components:{ parent } }) </script>
|
子传父($emit)
- 在子组件通过$emit来派发对应的事件,并传入数据
- 父组件通过监听对应的事件执行,来获取数据
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 54 55 56 57 58 59 60 61 62 63 64
| <div id="app"> <parent></parent> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false
let child = { template:` <div> {{msg}} <button @click="handler">click</button> </div> `, data(){ return{ msg:'子组件', message:'来自子组件的数据' } }, methods: { handler(){ this.$emit('sendMsg',this.message) } }, } let parent = { template:` <div> {{msg}} <child @sendMsg="handler"></child>{{args}} </div> `, data(){ return{ msg:'父组件', args:'' } }, methods:{ handler(arg){ console.log(arg); this.args = arg } }, components:{ child } }
const vm = new Vue({ el: '#app', data: {
}, components:{ parent } }) </script>
|
总结
- 父传子,利用属性进行传值,子组件利用props来接收
- 如果父组件传递的是一个对象,子组件最好是利用工厂函数来返回一个新对象
- 如果传值过程中,不希望数据被更改,则最好是利用深拷贝,传递一个全新的对象
- 子传父,是利用观察者模式进行传值,通过$emit触发发布事件,父组件通过监听事件来获取对应的数据
兄弟组件通信(bus)
方案一:子传父,再父传子(不建议使用)
方案二:bus传值
- 创建一个公共的bus对象(Vue实例对象)
- 在需要传值的组件触发 bus.$emit(‘事件名’,数据)
- 在需要数据的组件监听并接收 bus.$on(‘事件名’,(传来的数据)=>{})
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
| <div id="app"> <first></first> <last></last> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false let bus = new Vue() let first = { template: `<div>first组件:<button @click="handler">给last组件传值</button></div>`, data() { return { msg: 'first组件的数据' } }, methods: { handler(){ bus.$emit('send',this.msg) } }, } let last = { template: `<div>last组件:{{arg}}</div>`, data(){ return{ arg:'' } }, created(){ bus.$on('send',(arg)=>{ this.arg = arg console.log(arg); }) } }
const vm = new Vue({ el: '#app', data: { }, components: { first, last } }) </script>
|
provide inject传值
主要是为高阶组件/组件库提供用例,可以用于跨组件传值〈不建议使用),必须基于父子关系〈不管嵌套多少级都传值)。
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
| <div id="app"> <parent>
</parent> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false
let child = { template: `<div>child:{{msg}}</div>`, inject: ['msg'] } let parent = { template: `<div>parent<child></child></div>`, components: { child }
} const vm = new Vue({ el: '#app', data: { msg: 'hello' }, components: { parent }, provide() { return { msg: this.msg, getValue:function(){
} } } }) </script>
|
ref传值
ref传值主要传递的是当前的组件
ref如果是用于普通的dom元素,那么接受的就是普通的dom对象,如果是组件,则接受的是组件
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
| <div id="app"> <child ref="child"></child> <p ref="ele"></p> </div> <script src="./lib/vue.js"></script> <script> Vue.config.productionTip = false let child = { template:`<div>child组件</div>`, data(){ return{ msg:'传递的数据', } } } const vm = new Vue({ el: '#app', data: { names: '袁同学!', value:'' }, components:{ child }, mounted() { console.log(this.$refs.child.msg,this.$refs.ele); }, }) </script>
|