02 Vue组件
组件
- 组件的定义
- 组件具备复用性
- 全局组件,只要定义了,处处可以使用,性能不高,但是使用起来简单,名字建议 小写字母单词,中间用横线间隔
- 局部组件,定义了,要注册之后才能使用,性能比较高,使用起来有些麻烦,建议大些字母开头,驼峰命名
- 局部组件使用时,要做一个名字和组件间的映射对象,你不写映射,Vue 底层也会自动尝试帮你做映射
全局组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const app = Vue.createApp({ template: ` <div> <counter-parent /> <counter /> </div> ` }); app.component('counter-parent', { template: `<counter />` }) app.component('counter', { data() { return { count: 1 } }, template: `<div @click="count += 1">{{count}}</div>` }) const vm = app.mount('#app');
|
局部组件
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
|
const Counter = { data() { return { count: 1 } }, template: `<div @click="count += 1">{{count}}</div>` } const HelloWorld = { template: `<div>hello world</div>` } const app = Vue.createApp({ components: { Counter, HelloWorld, }, template: ` <div> <hello-world /> <counter /> </div> ` }); const vm = app.mount('#root');
|
组件传值
父->子
1 2 3 4 5 6 7
| const app = Vue.createApp({ template: ` <div><test content="123" /></div>` }); app.component('test', { props: ['content'], template: `<div>{{content}}</div>` });
|
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
| const app = Vue.createApp({ data() { return { num: 1234 } }, template: ` <div><test :content="num" /></div> ` }); app.component('test', { props: { content: { type: Number, validator: function(value) { return value < 1000; }, default: function() { return 456; } } }, template: `<div>{{content}}</div>` });
|
多参数
传接变量
单项数据流
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| const app = Vue.createApp({ data() { return { num: 1 } }, template: ` <div> <counter :count="num" /> <counter :count="num" /> <counter :count="num" /> </div> ` }); app.component('counter', { props: ['count'], template: `<div @click="count += 1">{{count}}</div>` });
|
None-prop
- 子组件不适用props接受父组件的传值,子组件渲染时,直接把传值放在标签上,显示在DOM里
- 子组件不用props时,可以用
v-bind="$attrs"获取值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const app = Vue.createApp({ template: ` <div> <counter msg="hello" msg1="hello1" /> </div> ` }); app.component('counter', { mounted() { console.log(this.$attrs.msg); }, template: ` <div :msg="$attrs.msg">Counter</div> <div v-bind="$attrs">Counter</div> <div :msg1="$attrs.msg1">Counter</div> ` });
|
事件通信
触发事件驼峰,监听事件-
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
| const app = Vue.createApp({ data() { return { count: 1 } }, methods: { handleAddOne() { this.count++ } }, template: ` <counter v:count="count" @add-one="handleAddOne"/> ` }); app.component('counter', { props: ['count'], emits:['addOne','add2','update'], methods: { handleClick() { this.$emit('addOne'); } }, template: ` <div @click="handleClick">{{count}}</div> ` });
|
v-model 双向数据绑定来实现通信
来回入参命名固定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const app = Vue.createApp({ data() { return { count: 1 } }, template: ` <counter v-model="count" /> ` }); app.component('counter', { props: ['modelValue'], methods: { handleClick() { this.$emit('update:modelValue', this.modelValue + 3); } }, template: ` <div @click="handleClick">{{modelValue}}</div> ` });
|
给别名:app,多个值给多个别名
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| const app = Vue.createApp({ data() { return { count: 1 } }, template: ` <counter v-model:app="count" /> ` }); app.component('counter', { props: ['app'], methods: { handleClick() { this.$emit('update:app', this.modelValue + 3); } }, template: ` <div @click="handleClick">{{app}}</div> ` });
|
给v-model添加自定义修饰符
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
| const app = Vue.createApp({ data() { return { count: 'a', } }, template: ` <counter v-model.uppercase="count" /> ` }); app.component('counter', { props: { 'modelValue': String, 'modelModifiers': { default: ()=> ({}) } }, methods: { handleClick() { let newValue = this.modelValue + 'b'; if(this.modelModifiers.uppercase) { newValue = newValue.toUpperCase(); } this.$emit('update:modelValue', newValue); }, }, template: ` <div @click="handleClick">{{modelValue}}</div> ` });
|
插槽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
| const app = Vue.createApp({ template: ` <layout> <div>slot</div> </layout> <layout2> <template v-slot:header> <div>header</div> </template> <template v-slot:footer> <div>footer</div> </template> </layout2> ` }); app.component('layout', { template: ` <div> <slot></slot> </div> ` }); app.component('layout2', { template: ` <div> <slot name="header"></slot> <div>content</div> <slot name="footer"></slot> </div> ` });
|
作用域插槽
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| const app = Vue.createApp({ template: ` <list v-slot="{item}"> <div>{{item}}</div> </list> ` }); app.component('list', { data() {return {list: [1, 2, 3]}}, template: ` <div> <slot v-for="item in list" :item="item" /> </div> ` });
|
动态组件和异步组件
动态组件:根据数据的变化,结合component标签来随时动态切换组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| const app = Vue.createApp({ data(){ return{ currentItem:"input-item" } }, template: ` //缓存 <keep-alive> <component :is="input-item"> </keep-alive> ` }); app.component('word-item', { template: ` hello ` }); app.component('input-item', { template: ` <input/> ` });
|
异步组件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| const app = Vue.createApp({ template: ` <div> <common-item /> <async-common-item /> </div> ` }); app.component('common-item', { template: `<div>hello world</div>` }); app.component('async-common-item', Vue.defineAsyncComponent(() => { return new Promise((resolve, reject) => { setTimeout(() => { resolve({ template: `<div>this is an async component</div>` }) }, 4000) }) }))
|