一、props参数验证
约束组件调用者所传递的 props 参数的数据类型,props 是单向数据流,不能在组件内部尝试修改 props 传递props的细节
props: {
name: {
type: String,
},
score: {
type: Number,
required: true, //要求必传
},
hobby: {
type: String,
default: "唱跳",//默认
},
status: {
type: String,
validator(value) {
//value就是用户传入的status
// 优秀、及格、不及格
return ["优秀", "及格", "不及格"].includes(value); //return结果为true,代表验证通过
},
},
},
二、$emit子父通信
2.1 子组件绑定事件
<h3>这是子组件,银行卡余额:{{money}}</h3>
<button @click="handleChild">问候</button>
2.2 子组件在事件函数中通过this.$emit自定义事件
methods: {
handleChild() {
// 触发父级自定义事件give-me-money
this.$emit("give-me-money", {
msg: "最近天气比较热,注意避暑,顺便打点钱",
n: 10000,
});
this.money += 10000;
},
},
2.3 父级在调用子组件的时候,需要绑定对应的子组件定义的事件
<h1>父级空间,银行卡余额:{{money}}</h1>
<my-child @give-me-money="handleFather"></my-child>
2.4 父级在事件函数中可以得到子组件传递的参数,进行后续操作
methods: {
handleFather(obj) {
// console.log(obj);
let { msg, n } = obj; //解构赋值
console.log(msg);
this.money -= n;
},
},
<div id="app">
<h1>父级空间,银行卡余额:{{money}}</h1>
<my-child @give-me-money="handleFather"></my-child>
</div>
<script>
let app = Vue.createApp({
//创建vue应用
data() {
//数据包
return {
money: 1000000000,
};
},
methods: {
handleFather(obj) {
// console.log(obj);
let { msg, n } = obj; //解构赋值
console.log(msg);
this.money -= n;
},
},
});
app.component("my-child", {
template: `<div>
<h3>这是子组件,银行卡余额:{{money}}</h3>
<button @click="handleChild">问候</button>
</div>`,
data() {
return {
money: 10,
};
},
methods: {
handleChild() {
// 触发父级自定义事件
this.$emit("give-me-money", {
msg: "最近天气比较热,注意避暑,顺便打点钱",
n: 10000,
});
this.money += 10000;
},
},
});
app.mount("#app");
</script
三、组件的v-model
参考文档 v-model本身做了两件事<my-comp :modelValue="msg" @update:modelValue="直接修改msg">
3.1 子组件通过props: ["modelValue"]接收v-model传递的数据
<my-comp v-model="msg"></my-comp>
props: ["modelValue"], //接收组件通过v-model传递的数据
3.2 子组件通过子父通信this.$emit("update:modelValue", v)将数据传递给父级
this.$emit("update:modelValue", v); //通过子父通信将组件内的值传给父级
<body>
<div id="app">
<h1>{{msg}}</h1>
<!-- v-model本身做了两件事
<my-comp :modelValue="msg" @update:modelValue="直接修改msg"></my-comp>
-->
<my-comp v-model="msg"></my-comp>
</div>
</body>
<script>
let app = Vue.createApp({
data() {
return {
msg: "Hello Vue",
};
},
});
app.component("my-comp", {
props: ["modelValue"], //接收组件通过v-model传递的数据
template: `<div>
演示组件中使用v-model,
<input type="text" :value="modelValue" @input="handleInput"/>
</div>`,
methods: {
handleInput(ev) {
console.log(ev);
let v = ev.target.value; //实时获取输入框的值
this.$emit("update:modelValue", v); //通过子父通信将组件内的值传给父级
},
},
});
app.mount("#app");
</script>
四、插槽
让组件调用者,可以向组件内部传递 HTML 结构
4.1 匿名插槽
<div id="app">
<my-comp>
<p>匿名插槽</p>
</my-comp>
</div>
<script>
let app = Vue.createApp({
})
app.component("my-comp",{
template:`<div>
演示插槽
<slot></slot>
</div>`
})
app.mount("#app")
</script>
4.2 具名插槽
<div id="app">
<my-comp>
<template v-slot:s1>
<h1>具名插槽1{{msg}}</h1>
</template>
<template #s2>
<h1>具名插槽2{{msg2}}</h1>
</template>
</my-comp>
</div>
<script>
let app = Vue.createApp({
data() {
return {
msg:"父级作用域"
}
},
})
app.component("my-comp",{
template:`<div>
<slot name="s2"></slot>
具名插槽
<slot name="s1"></slot>
</div>`,
data() {
return {
msg2: "数据2"
}
},
})
app.mount("#app")
</script>
4.3 作用域插槽
在组件内插槽中向组件外传递数据,解决插槽的内容无法访问到子组件的状态问题
<div id="app">
<!-- 方法一 -->
<!-- <my-comp v-slot="slotProps">
<h1>作用域插槽1,{{msg}}</h1>
<h1>作用域插槽2,{{slotProps.count}}</h1>
</my-comp> -->
<!-- 方法二 解构赋值的写法 -->
<my-comp v-slot="{count}">
<h1>作用域插槽1,{{msg}}</h1>
<h1>作用域插槽2,{{count}}</h1>
</my-comp>
</div>
<script>
let app = Vue.createApp({
data(){
return{
msg:"11111"
}
}
})
app.component("my-comp",{
data(){
return {
num:200
}
},
template:`<div>
作用域插槽
<slot :count="num"></slot>
</div>`
})
app.mount("#app")
</script>
五、$refs 实现组件通信
- 获取并操作 DOM、组件对象
- 应用场景:
- 操作焦点
- 多媒体操作(音频、视频)
- 集成第三方库 (地图、图表)
<div id="app">
<button @click="handleFn">按钮</button>
<h1 ref="myH1">内容</h1>
<input type="text" ref="myInput">
<my-comp ref="myComp"></my-comp>
</div>
<script>
let app = Vue.createApp({
methods:{
handleFn(){
this.$refs.myH1.style.border="1px solid pink";
this.$refs.myH1.style.transform="rotate(50deg)";
this.$refs.myInput.focus();
this.$refs.myComp.num++;
}
},
mounted(){
this.$refs.myInput.focus();
}
})
app.component("my-comp",{
data(){
return{
num:800
}
},
template:`<div>
{{num}}
</div>`,
})
app.mount("#app")
</script>
六、单页面应用(SPA --- Single Page Application)
- 整个项目只有一个 html 文件
- 视觉上的页面切换,本质是组件的切换 (.vue 单文件组件)