Vue-组件
**作用:**在不同的组件共同应用时数据会相互干扰 , 因此要为该组件单独开辟一个单独data的地址
关键字: components
(局部使用) / component
(全局使用)
组件命名:
- 组件的命名不支持 驼峰命名
- 传递 属性/方法 也不能使用 驼峰命名
- 驼峰命名 的应用替换至短横线分隔命名
步骤:
定义 局部/全局 Vue组件
局部 Vue组件 (在components选项中
components:{ <Vue组件名> : { template: <根元素>, data() { return{ <key>:<value> } } } [, <Vue组件名2> : {...}] }
全局 Vue组件
Vue.component(<Vue组件名>,{ template: <根元素>, data() { return{ <key>:<value> } } );
在 Vue容器中 添加 Vue组件
<Vue组件名></Vue组件名>
模板应用方式
Js代码中
let tmp = '<div>...</div>'; ... Vue.component(...,{ template: tmp })
script标签中
<script id="info"> <div>...</div> </script> ... Vue.component(...,{ template: "#info" })
template标签中
<template id="info"> <div>...</div> </template> ... Vue.component(...,{ template: "#info" })
Vue组件 与 Vue实例 的区别:
- Vue组件 data需要函数返回值 . 而且只能返回一个对象
- Vue组件 没有 el选项 , 但有 template选项 代表页面结构(自要一个根元素
- Vue组件之间的数据都是相互独立的 , 运行的 作用域、数据、逻辑 没有关联
示例:
<div id="app">
<h3>组件复用</h3>
<button-count></button-count>
<button-count></button-count>
<button-count></button-count>
<br> <h3>组件共用</h3>
<button @click="count++">按钮 {{count}}</button>
<button @click="count++">按钮 {{count}}</button>
<button @click="count++">按钮 {{count}}</button>
</div>
<script src="vue.js"></script>
<script>
Vue.component('button-count', {
data: function() {
return {count : 0}
},
template:'<button @click="count++">按钮 {{count}}</button>'
});
new Vue({
el: '#app',
data:{
count: 0
}
})
</script>
示例2:
<div id="app">
<component-a></component-a>
<component-b></component-b>
</div>
<script src="vue.js"></script>
<script>
// 全局
Vue.component("component-a",{
template: '<div>\n' +
' <button @click="cut"><</button>\n' +
' <span>{{count}}</span>\n' +
' <button @click="add">></button>\n' +
' </div>',
data() {
return{
count: 0
}
},
methods:{
add() {
console.log("add")
this.count++;
},
cut() {
console.log("cut")
this.count--;
}
}
});
new Vue({
el:"#app",
data:{},
// 局部
components:{
"component-b" : {
template: '<div>\n' +
' <button @click="cut">减</button>\n' +
' <span>{{count}}</span>\n' +
' <button @click="add">加</button>\n' +
' </div>',
data() {
return{
count: 0
}
},
methods:{
add() {
console.log("add")
this.count++;
},
cut() {
console.log("cut")
this.count--;
}
}
}
}
});
</script>
# 组件嵌套
嵌套情况: (其他方式嵌套不可用
- 全局 套 全局
- 局部 套 全局
示例
<div id="app">
<h1>全局 套 全局</h1>
<parent-all-a></parent-all-a>
<!--<h1>局部 套 局部</h1>-->
<h1>局部 套 全局</h1>
<parent-part-b></parent-part-b>
</div>
...
<script>
// 全局
Vue.component("child-all-a",{
template:'<p>child-part-a</p>'
});
Vue.component("child-all-b",{
template:'<p>child-part-b</p>'
});
// 全局 套 全局
Vue.component("parent-all-a",{
template:'<div>\n' +
' 全局\n' +
' <child-all-a></child-all-a>\n' +
' <child-all-b></child-all-b>\n' +
' </div>'
})
// 局部
new Vue({
el:"#app",
data:{},
components: {
"child-part-a":{
template:'<p>child-part-a</p>'
},
"child-part-b":{
template:'<p>child-part-b</p>'
},
"parent-part-b":{ // 局部 套 全局
template:'<div>\n' +
' 局部\n' +
' <child-all-a></child-all-a>\n' +
' <child-all-b></child-all-b>\n' +
' </div>'
}
}
});
</script>
# 组件通信
由于组件之间的数据都是相互独立互不干扰 , 如果组件之间的数据需要交互情况可应用 props
选项 绑定属性传递即可获取
组件之间的通信是根据关系划分为:
- 父组件通信
- 子组件通信
- 同胞组件通信
关键字:props
(数据传递) / emit
(方法传递)
# 数据通信
关键字:props
步骤: (应用前提 Vue容器 data 包含有 msg属性
创建 Vue组件
添加 props选项 增加绑定属性(任意)
==props : [<自定义属性名>]== (数组形式可写多个绑定属性)
在引用 Vue组件 的标签 中添加绑定属性 对应的 父组件属性/Vue属性
==<<组件名> :<绑定属性名>="<父组件属性名>"></<组件名>>==
注意
- 子组件的 props选项 值是一个数组
- 数组中的值是 绑定子组件上的属性 用于接收父组件的传值
- 子组件的 template选项 可直接使用 绑定好的属性 , 从而实现获取父组件传递的值
- 子组件 更变绑定的属性值 , 不会对其父组件的 data数据有任何影响
示例
<div id="app">
<child-a :msg="msgParent"></child-a>
<p>父组件msgParent:{{msgParent}}</p>
</div>
...
<script>
Vue.component("child-a",{
template:'<div>\n' +
' <p>子组件 data.count = {{count}}</p>\n' +
' <p>父容器 data.msgParent = {{msg}}</p>\n' +
' <button @click="add">++</button>\n' +
' </div>',
data() {
return{
count : 100
}
},
methods:{
add() {
this.count++;
this.msg++;
}
},
// 绑定 指定的data
props:['msg']
});
new Vue({
el:"#app",
data:{
msgParent : 200
}
})
</script>
# 方法通信
步骤: (前提父组件已经有方法 且可直观的呈现
父组件模板中的子类标签 添加 ==@<自定义名称>: "方法名"== (用于传递方法
<template id="Father"> <div> ... <!-- 传递方法 <自定义名称 parentsay> --> <son @parentsay="say"></son> </div> </template>
子类添加自定义方法 , 使用 ==this.$emit(<自定义名称> [, 方法的参数])== (用于回调父类的方法
// 通过 sonFn()进行 调用父类的方法 components: { "son":{ template: "#Son", methods:{ // 自定义方法 调用父类传递的方法 sonFn() { this.$emit("parentsay"); } } } }
传递方法条件:
- 父组件向子组件传递方法 前提需要在父组件模板中的子组件标签添加 传递的关键字
- 子组件应用父组件中的方法 子组件必须创建自定义方法进行调用
实例:
<div id="app">
<father></father>
</div>
...
<template id="Father">
<div>
<p>父组件</p>
<button @click="say('父类')">按钮</button>
<!-- 传递方法 <自定义名称 parentsay> -->
<son @parentsay="say"></son>
</div>
</template>
<template id="Son">
<div>
<p>子组件</p>
<button @click="sonFn('子类')">按钮</button>
</div>
</template>
...
<script>
new Vue({
el: "#app",
data: {},
components: {
"father": {
template: "#Father",
components: {
"son":{
template: "#Son",
methods:{
// 自定义方法 调用父类传递的方法
sonFn(type) {
this.$emit("parentsay",type);
}
}
}
},
methods:{
say(type) {
alert(type+": 已经点击啦!")
}
}
}
}
})
</script>
方法传递额外参数
通过 $event
获取子类传递的参数 , 后面可在父类进行额外添加
// 子组件
<div @click="childClick">子组件</div>
childClick(){
this.$emit("emitClick","from child")
}
// 父组件
<div @emitClick="parentClick($event,'from parent')">父组件</div>
parentClick(child,parent){
console.log(child,parent)//from child from parent
}
# Vue3
# 数据通信
官方文档 : 点击跳转 (opens new window)
组件数据传递
API : defineProps()
示例
<!-- 父组件 -->
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'
</script>
<template>
<ChildComp msg="hello" />
</template>
<!-- 子组件 -->
<script setup>
const props = defineProps({
msg: String
})
</script>
<template>
<h2>{{ msg || '数据不能存在' }}</h2>
</template>
# 方法通信
官方文档 : 点击跳转 (opens new window)
API : defineEmits()
示例
<!-- 父组件 -->
<script setup>
import { ref } from 'vue'
import ChildComp from './ChildComp.vue'
const childMsg = ref('无数据')
</script>
<template>
<ChildComp @response="(msg) => childMsg = msg" />
<p>{{ childMsg }}</p>
</template>
<!-- 子组件 -->
<script setup>
const emit = defineEmits(['response'])
const onInput = e => {
emit('response', e.target.value)
}
</script>
<template>
<h2>Child component</h2>
<input :value="text" @input="onInput">
</template>
提示
自行通信可通过 $on()
、$once()
搭配 $emit()
实现