目录
组件分类
局部组件 建子-挂子-用子
<div id="app">
<!-- 3.使用子组件 -->
<App></App>
</div>
<script>
//1.创建子组件
const App = {
//必须是一个函数
data() {
return {
msg: '我是App组件'
}
},
components: {
Vcontent
},
template: `
<div>
<Vheader></Vheader>
<div>
<Vaside />
<Vcontent />
</div>
</div>
`
}
new Vue({
el: '#app',
data: {
},
components: {
// 2.挂载子组件
App
}
})
</script>
全局组件
通过Vue.component(组件名,{})
Vue.component('Child',{
template:`
<div>
<h3>我是一个子组件</h3>
</div>
`
})
组件通信
父传子
子组件使用props:[]接收
Vue.component('Child',{
template:`
<div>
<h3>我是一个子组件</h3>
<h4>{{childData}}</h4>
</div>
`,
props:['childData']
})
const App = {
data() {
return {
msg: '我是父组件传进来的值'
}
},
template: `
<div>
<Child :childData = 'msg'></Child>
</div>
`,
computed: {
}
}
子传父
子组件通过$emit()自定义事件传递给父组件
Vue.component('Child', {
template: `
<div>
<h3>我是一个子组件</h3>
<input type="text" @input = 'handleInput'/>
</div>
`,
methods:{
handleInput(e){
//e.target.value 获取input值
const val = e.target.value;
//使用$emit触发子组件的事件
this.$emit('inputHandler',val);
}
},
})
const App = {
data() {
return {
msg: '我是父组件传进来的值',
newVal:''
}
},
methods:{
input(value){
this.newVal = value;
}
},
template: `
<div>
<div class='father'>
数据:{{newVal}}
</div>
<!--子组件监听事件-->
<Child @inputHandler = 'input'></Child>
</div>
`,
}
平行组件
使用中央事件总线bus
bus.$emit() bus.$on()
使用this.$parents.$emit() this.$parents.$on()传递
const bus = new Vue();
// 中央事件总线 bus
// Vue.prototype.$bus = bus
Vue.component('B', {
data() {
return {
count: 0
}
},
template: `
<div>{{count}}</div>
`,
created(){
// $on 绑定事件
bus.$on('add',(n)=>{
this.count+=n;
})
}
})
Vue.component('A', {
data() {
return {
}
},
template: `
<div>
<button @click='handleClick'>加入购物车</button>
</div>
`,
methods:{
handleClick(){
// this.$parent.$emit('add', 1)
// 触发绑定的函数 // $emit 触发事件
bus.$emit('add',1);
}
}
})
多层嵌套组件
父组件 provide来提供变量,然后再子组件中通过inject来注入变量.无论组件嵌套多深
//子组件
const DemoChild = {
data() {
return {
}
},
inject: ['childData'],
template: `
<div>
孩子组件
{{childData.name}}
</div>
`,
}
//中间子组件
const SecondChild = {
components: {
DemoChild,
},
}
//父组件
const App ={
data(){
childData: {
name: "provide提供"
}
},
provide() {
return {
childData: this.childData
}
},
components:{
SecondChild
}
}
$refs
this.$refs.name获取指定的元素或组件
在组合API中不行
<!-- ref 写在标签上时:this.$refs.名字 获取的是标签对应的dom元素
ref 写在组件上时:这时候获取到的是 子组件(比如counter)的引用-->
<div id="root">
<!-- 子组件触发了事件 这里父组件(模板区里面)监听该事件 调用handleChange方法
因此handleChange方法定义在父组件的methods里面-->
<counter ref="one" @change="handleChange"></counter>
<counter ref="two" @change="handleChange"></counter>
<div>{{total}}</div>
</div>
<script>
Vue.component('counter', {
template: '<div @click="handleClick"> {{number}} </div>',
data: function() {
return {
number: 0
}
},
methods: {
handleClick: function() {
this.number ++
//子组件向父组件传值 子组件被点击的时候 number+1 同时告诉外面 也即是触发一个事件
this.$emit('change')
}
},
})
var vm = new Vue({
el: '#root',
data: {
total: 0
},
methods: {
handleChange: function() {
//在此方法中计算两个数量的和 通过this.$refs.引用名字 获取两个子组件的引用
this.total = this.$refs.one.number +
this.$refs.two.number
}
}
})
</script>
v-model
$attrs 和 $listeners
多级组件嵌套需要传递数据时,通常使用的方法是通过vuex。如果仅仅是传递数据,而不做中间处理,使用 vuex 处理,这就有点大材小用了。所以就有了 $attrs / $listeners ,通常配合 inheritAttrs 一起使用。
$attrs
:包含了父作用域中不被认为 (且不预期为) props 的特性绑定 (class 和 style 除外),并且可以通过 v-bind=”$attrs” 传入内部组件。当一个组件没有声明任何 props 时,它包含所有父作用域的绑定 (class 和 style 除外)。
$listeners
:包含了父作用域中的 (不含 .native 修饰符) v-on 事件监听器。它可以通过 v-on=”$listeners” 传入内部组件。它是一个对象,里面包含了作用在这个组件上的所有事件监听器,相当于子组件继承了父组件的事件。inheritAttrs:true 继承除props之外的所有属性;inheritAttrs:false 只继承class属性。
father组件
<template>
<child :name="name" :age="age" :infoObj="infoObj" @updateInfo="updateInfo" @delInfo="delInfo" />
</template>
<script>
import Child from '../components/child.vue'
export default {
name: 'father',
components: { Child },
data () {
return {
name: 'Lily',
age: 22,
infoObj: {
from: '上海',
job: 'policeman',
hobby: ['reading', 'writing', 'skating']
}
}
},
methods: {
updateInfo() {
console.log('update info');
},
delInfo() {
console.log('delete info');
}
}
}
</script>
child组件
<template>
<grand-son :height="height" :weight="weight" @addInfo="addInfo" v-bind="$attrs" v-on="$listeners" />
// 通过 $listeners 将父作用域中的事件,传入 grandSon 组件,使其可以获取到 father 中的事件
</template>
<script>
import GrandSon from '../components/grandSon.vue'
export default {
name: 'child',
components: { GrandSon },
props: ['name'],
data() {
return {
height: '180cm',
weight: '70kg'
};
},
created() {
console.log(this.$attrs);
// 结果:age, infoObj, 因为父组件共传来name, age, infoObj三个值,由于name被 props接收了,所以只有age, infoObj属性
console.log(this.$listeners); // updateInfo: f, delInfo: f
},
methods: {
addInfo () {
console.log('add info')
}
}
}
</script>
grandson组件
<template>
<div>
{{ $attrs }} --- {{ $listeners }}
<div>
</template>
<script>
export default {
... ...
props: ['weight'],
created() {
console.log(this.$attrs); // age, infoObj, height
console.log(this.$listeners) // updateInfo: f, delInfo: f, addInfo: f
this.$emit('updateInfo') // 可以触发 father 组件中的updateInfo函数
}
}
</script>