局部组件
<div id="app">
<!-- 使用自定义组件 -->
<my-com></my-com>
<my-com2></my-com2>
<my-com2></my-com2>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script>
//自定义组件
var MyCom={
template:`<div>{{msg}}</div>`,
data:function(){
return{
msg:"Hello Vue"
}
}
}
var MyCom2={
template:`<div>
{{msg}}
<button @click="onClick">点击{{num}}</button>
</div>`,
data:function(){
return{
msg:"我是自定义组件",
num:0
}
},
methods:{
onClick(){
this.num++;
}
}
}
var app=Vue.createApp({
data:function(){
return{
}
},
components: {//引入多个组件
MyCom,
MyCom2
},
});
app.mount("#app");
</script>
全局组件
app.component("MyCom",{
template:``,
data(){}
})
<div id="app">
<!-- 使用组件 -->
<my-com></my-com>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script>
var app=Vue.createApp({
data:function(){
return{
}
},
});
//全局组件
app.component("MyCom",{
template:`<button @click="onClick" class="my-com">
点击{{num}}
</button>`,
data(){
return{
num:0
}
},
methods:{
onClick(){
this.num++;
}
}
});
app.mount("#app");
</script>
组件间传值
父组件修改子组件的值
通过props实现 父组件修改子组件的值
1.父组件传给子组件的prop,prop是跟随父组件中的声明的prop名字匹配,进行传值
2.子组件不能直接修改props(子组件不能直接修改父组件的状态),单项向数据流 子组件无法修改props。
<div id="app">
<!--通过props实现 父组件修改子组件的值 -->
<my-com v-bind:msg="info"></my-com>
<my-com v-bind:msg="info2"></my-com>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script>
var app=Vue.createApp({
data:function(){
return{
info:"hello",
info2:"Hi",
}
},
});
//父组件修改子组件的值
app.component("MyCom",{
template:`<div class="my-com">
{{msg}}
</div>`,
props:['msg'],
data(){
return{
}
},
});
app.mount("#app");
</script>
子组件修改父组件的值
子组件通过$emit 触发一个自定义事件来实现修改父组件的值
3.子组件想修改父组件中的状态,需要以触发自定义事件的形式,把更新的值以事件对象的形式传递出去
4.父组件就可以监听事件的形式,接受子组件传递过来的值
<div id="app">
<!-- 子组件通过$emit 触发一个自定义事件 实现修改父元素的值 -->
<my-com2 @change="onChange"></my-com2>
<my-com2 @change="msg=$event"></my-com2>
<div>父元素的msg:{{msg}}</div>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script>
var app=Vue.createApp({
data:function(){
return{
msg:""
}
},
methods:{
onChange(e){
console.log(e);
this.msg=e;
}
}
});
//子组件修改父组件的值
app.component("MyCom2",{
template:`<div class="my-com">
<input type="text" @input="onInput" v-model="msg"/>
</div>`,
data(){
return{
msg:"hello"
}
},
methods:{
onInput(e){
//子组件通过$emit 触发一个自定义事件
//emit(自定义事件名称,需要传递的值)
console.log(e.target.value);
this.$emit("change",e.target.value);
}
}
});
app.mount("#app");
</script>
组件间传值案例
通过组件间的传值实现如下的投票系统。
css样式
<style>
.vote-item{
width: 80%;
margin: 5px auto;
border:2px solid #eee;
}
.progress{
height: 10px;
background: #eee;
border-radius: 10px;
margin: 10px;
}
.progress-bar{
height: 10px;
background: green;
border-radius: 10px;
transition: all 1s;
}
</style>
html部分:
<div id="app">
<div class="root">
{{voteTotal}}
<vote-item v-for="(item,index) in voteList" :total="voteTotal" @vote="onVote(index,$event)" :name="item.name" :vote="item.vote"></vote-item>
</div>
</div>
js部分:
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script>
var app=Vue.createApp({
data:function(){
return{
voteList:[
{name:"张三",vote:0},
{name:"李四",vote:0},
{name:"王五",vote:0},
{name:"赵六",vote:0},
]
}
},
methods: {
onVote(index,e){
this.voteList[index].vote=e;
}
},
computed: {
voteTotal() {
//prev 上次回调函数的返回值 curr代表当次遍历数组的成员
return this.voteList.reduce((prev,curr)=>((prev+=curr.vote),prev),0)
}
},
});
app.component("vote-item",{
template:`
<div class="vote-item">
<div>{{name}}:{{vote}}</div>
<div class="progress">
<div class="progress-bar" role="progressbar" :style="{width:percent}"></div>
</div>
<button @click="$emit('vote',vote+1)">投{{name}}一票</button>
</div>
`,
//一个组件能用props解决就尽量不用data
props:["name","vote","total"],
data(){
return{
}
},
methods:{
onInput(e){
this.$emit('change',e.target.value);
}
},
computed: {
percent(){
// console.log(this.total);
if(this.total==0){
return "0%";
}else{
return ((100*this.vote)/this.total).toFixed(2)+"%";
}
}
},
});
app.mount("#app");
</script>
效果:
补充:
如何在自定义事件上使用v-model,自定义事件的语法糖。
<div id="app">
<my-com :num="num" @update:num="num=$event"><my-com>
<my-com :num="num" v-model:num="num"><my-com>
{{num}}
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script>
var app=Vue.createApp({
data:function(){
return{
num:0
}
},
methods: {
},
});
app.component("MyCom",{
template:`<div class="my-com">
<button @click="$emit('update:num',num+1)">点击{{num}}</button>
</div>`,
props:{
num:{
type:Number,
require:true
}
},
});
app.mount("#app");
</script>
emits选项
<div id="app">
<my-com @click="onClick"></my-com>
</div>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/3.2.37/vue.global.js"></script>
<script>
var app=Vue.createApp({
data:function(){
return{
}
},
methods: {
onClick(e) {
console.log(e);
}
},
});
app.component("MyCom",{
template:`<div>
<button @click="$emit('click',Date.now())">点击</button>
</div>`,
data(){
return{
}
},
emits:['click'],//用来声明 当前组件的自定义事件
});
app.mount("#app");
</script>