1.组件的定义及复用性,局部组件和全局组件
组件的定义:分部分进行维护。
app.component('world',{
template:`<div>world</div>`
});
复用性:组件内的数据是独享的。
const app = Vue.createApp({
template:`
<div>
<counter/>
<counter/>
<counter/>
</div>
`
});
app.component('counter',{
data(){
return{
count:1
}
},
template:`<div @click="count+=1">{{count}}</div>`
});
当点击时,并不会全部都发生改变,由于组件的复用性
局部组件:定义一个常量,在父组件中首先用components进行声明,然后在模板中使用。建议首字母大写。局部组件使用时,要做一个名字和组件之间的映射对象,不写映射,Vue底层也会自动帮做映射。
const HelloWorld={
template:`<div>hello world</div>`
};
const app = Vue.createApp({
components:{
HelloWorld,
},
template:`
<div>
<hello-world/>
</div>
`
});
全局组件:只要定义了,处处都可以用。
2.组件间传值及传值校验
组件间传值:
const app = Vue.createApp({
data(){
return{
sum1:10
}
},
template:`
<div><test :content="sum1"/></div>
`
});
app.component('test',{
data(){
return{
sum : 0,
sum2:10,
show:false
}
},
props:['content'],
methods:{
handleSum(content,sum2){
this.sum = content+sum2;
this.show = true;
}
},
template:`
<div>sum1:{{content}}</div>
<div>sum2:{{sum2}}</div>
<button @click="handleSum(content,sum2)">求和</button>
<div v-if="show">和:{{sum}}</div>
`
})
上述示例父组件通过:content="sum1"向子组件传递了一个变量名为content,值为sum1的变量,首先在子组件中要通过 props:[‘content’]进行接收,才可以进行使用。
传值校验:
type:String,Boolean,Array,Object,Function,Symbol required:必填 default:默认值
props:{
content:{
type:Number,
required:true,
default:()=>{
return 456
}
}
},
3.单向数据流的理解
单向数据流的理解:子组件可以使用父组件传递过来的数据,但绝对不能修改传递过来的数据
4.Non-Props属性
Non-Props属性:父组件给子组件传递内容时,子组件不通过props接收
const app = Vue.createApp({
template:`
<div>
<test message1="hello" message2="world" style="color:red"/>
</div>
`
});
app.component('test',{
template:`
<div v-bind="$attrs">Counter</div>
<div :msg1="$attrs.message1">Counter</div>
<div>Counter</div>
`
})
inheritAttrs:false,表示不接受父组件传递的Non-Props属性
5.父子组件通过事件进行通信
第一种写法:
const app = Vue.createApp({
data(){
return{
count:1
}
},
methods:{
handleAdd(count){
this.count = count;
}
},
template:`
<test :counter="count" @add-one="handleAdd"></test>
`
});
app.component('test',{
props:['counter'],
emits:{
addOne:(count)=>{
if(count < 20) return true;
return false;
}
},
methods:{
handleAdd(){
this.$emit('addOne',this.counter+3);
}
},
template:`
<div @click="handleAdd">{{counter}}</div>
`
})
子组件this.$emit(‘addOne’,this.counter+3)会向往外触发一个addOne的事件,this.counter+3为Value,在父组件中通过 @add-one进行监听,若触发,则调用handleAdd方法
第二种写法:
const Add={
props:['modelValue'],
methods:{
handleAdd(){
this.$emit('update:modelValue',this.modelValue+3);
},
},
template:`
<div @click="handleAdd">{{modelValue}}</div>
`
};
const app = Vue.createApp({
components:{
Add
},
data(){
return{
count:1
}
},
methods:{
handleAdd(count){
this.count = count;
}
},
template:`
<add v-model="count"/>
`
});
6.使用插槽和具名插槽解决组件内容传递问题
使用插槽
const app = Vue.createApp({
components:{
Layout,List
},
data(){
return{
text:"提交"
}
},
template:`
<div>
<myform>
<div>{{text}}</div>
</myform>
<myform>
<button>{{text}}</button>
</myform>
</div>
`
});
app.component('myform',{
methods:{
handleClick(){
alert('123')
}
},
template:`
<div>
<input/>
<span @click="handleClick">
<slot></slot>
</span>
</div>
`
})
slot插槽无法绑定事件:解决方法在外层加上一层span标签在span标签中进行绑定。
具名插槽
const Layout={
template:`
<div>
<slot name="header"></slot>
<div>content</div>
<slot name="footer"></slot>
</div>
`
};
const app = Vue.createApp({
components:{
Layout
},
template:`
<layout>
<template v-slot:header>
<div >header</div>
</template>
<template v-slot:footer>
<div >footer</div>
</template>
</layout>
`
});
父组件中将插槽名定义在template标签上,v-slot:header等价于#header,子组件中通过name进行引用。
作用域插槽
const List={
data(){
return{
list:[1,2,3],
}
},
template:`
<div>
<slot v-for="item in list" :item="item"></slot>
</div>
`
}
const app = Vue.createApp({
components:{
List
},
template:`
<list v-slot="slotProps">
<div>{{slotProps.item}}</div>
</list>
`
});
通过ES6解构语法可以将 v-slot=“slotProps"写成v-slot=”{item}",{{slotProps.item}}写成{item}
7.动态组件和异步组件
动态组件:通过数据改变,结合component这个标签,来随时动态切换组件的实现。
const Layout={
template:`
<div>
<input/>
</div>
`
};
const List={
template:`
<div>
<span>hello world</span>
</div>
`
}
const app = Vue.createApp({
components:{
Layout,List
},
data(){
return{
currentItem:'list'
}
},
methods:{
handleClick() {
if(this.currentItem == 'list'){
this.currentItem = 'layout';
}else{
this.currentItem = 'list';
}
}
},
template:`
<div>
<keep-alive>
<component :is="currentItem"/>
</keep-alive>
<button @click="handleClick">切换</button>
</div>
`
});
动态组件通过 component :is="currentItem"进行实现,keep-alive用于保存切换的缓存
异步组件:异步执行某些组件的逻辑
const app = Vue.createApp({
template:`
<async-common-item1/>
<async-common-item2/>
`
});
app.component('async-common-item1',Vue.defineAsyncComponent(()=>{
return new Promise((resolve,reject) =>{
setTimeout(() => {
resolve({
template:'<div>4秒延迟的异步组件</div>'
})
}, 4000);
})
}));
app.component('async-common-item2',Vue.defineAsyncComponent(()=>{
return new Promise((resolve,reject) =>{
setTimeout(() => {
resolve({
template:'<div>5秒延迟的异步组件</div>'
})
}, 5000);
})
}));
8.基础知识点查漏补缺
1.v-once
v-once:让某个元素标签只进行一次渲染
const app = Vue.createApp({
data(){
return{
count:1,
}
},
template:`
<div>
<div @click="count += 1" v-once>{{count}}</div>
</div>
`
});
通过点击事件可以发显示无法自增,但实际count元素已发生自增
2.ref
ref实际上是获取dom节点/组件的语法
const app = Vue.createApp({
data(){
return{
count:1,
}
},
mounted(){
console.log(this.$refs.count1);
this.$refs.count2.sayHi();
},
template:`
<div>
<div ref="count1">{{count}}</div>
<common-item ref="count2"></ommon-item>
</div>
`
});
app.component('common-item',{
methods:{
sayHi(){
alert('hello');
}
},
template:'<div>hello</div>'
});
mounted(),Vue中的生命周期函数,在组件渲染到页面之后立即执行的函数
3.provide/inject
provide/inject:提供数据/接收数据
const app = Vue.createApp({
data(){
return{
count:1,
}
},
provide(){
return{
count:this.count
}
},
template:`
<div>
<child-child></child-child>
<button @click="count+=1">Add</button>
</div>
`
});
app.component('child-child',{
inject:['count'],
template:'<div>{{count}}</div>'
});
注意:provide只进行一次传值
|