组件的创建和使用
一个组件就是一个对象(html+css+js),组件分为全局组件和局部组件。(组件须在创建Vue实例之前创建)
全局组件:创建之后就可以直接使用。
局部组件:创建之后需要挂载才能使用,且只能在挂载的组件或Vue实例中使用。
全局组件
全局组件通过Vue.component('组件名',{})创建,{}是一个对象,它和Vue实例一样有着data、methods、computed、template等属性。其中template中可以设计我们想要的组件,需要注意的是它是用反引号``,且最外层用<div></div>将里面的内容包裹起来。同时这里的data和Vue实例中的有区别,它是一个函数,这个函数返回一个对象(方便后期维护,每一个组件只需要维护它自己的一个实例),在这个对象内可以写需要的属性。
<body>
<div id="app">
<Vcontent></Vcontent>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('Vcontent', {
data() {
return {
msg: 'hello 全局组件'
}
},
template: `
<div>
我是全局组件
<h2>{{ msg }}</h2>
<button @click='handleClick'>点我</button>
</div>
`,
methods: {
handleClick(){
alert('hello 全局组件');
}
},
})
new Vue({
el: '#app',
})
</script>
</body>
局部组件
使用局部组件需要牢记三个步骤:创建、挂载、使用。
局部组件通过const 组件名 = {}声明创建,Vue实例有一个components属性,将创建的局部组件挂载在其中即可在这个Vue实列绑定的元素中使用,同时也可以继续在局部组件的components属性中挂载其他的局部组件。
注意:创建全局组件使用的是component,而用于挂载局部组件的是components,这边稍不注意可能写错。
<body>
<div id="app">
<App></App>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const App = {
data() {
return {
msg: 'hello 局部组件'
}
},
template: `
<div>
我是局部组件
<h2>{{ msg }}</h2>
<button @click='hanldeClick'>点我</button>
</div>
`,
methods: {
hanldeClick() {
alert('hello 局部组件')
}
},
components: {
//可挂载其他组件
}
}
new Vue({
el: '#app',
components: {
App
}
})
</script>
</body>
组件的通信
父传子(props)
- 在子组件的props中声明属性,接收从父组件中传入的数据
- 该属性可在子组件的template中任意使用
- 在父组件中的子组件标签上为子组件props中声明的属性绑定父组件需要传入的数据
<body>
<div id="app">
<App></App>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('Child',{
template:`
<div>{{ appMsg }}</div>
`,
props:['appMsg']
},)
const App = {
data() {
return {
msg: 'hello 子组件'
}
},
//通过绑定将msg传入子组件
template: `
<div>
<Child :appMsg='msg'></Child>
</div>
`,
}
new Vue({
el: '#app',
components: {
App
}
})
</script>
</body>
子传父
- 在父组件中的子组件标签上绑定自定义事件
- 在子组件中触发原生的事件,在事件函数中通过
this.$emit()触发自定义事件
<body>
<div id="app">
<App></App>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('Child', {
template: `
<div>
<input type='text' @input='handleInput'/>
</div>
`,
methods: {
handleInput(e) {
const v = e.target.value;
//this.$emit()触发事件
this.$emit('inputHandle', v)
}
},
})
const App = {
data() {
return {
newVal: ''
}
},
template: `
<div>
<div>子组件传入的数据:{{ newVal }}</div>
<Child @inputHandle='input'></Child>
</div>
`,
methods: {
input(v) {
this.newVal = v;
}
},
}
new Vue({
el: '#app',
components: {
App
}
})
</script>
</body>
平行组件通信(兄弟组件通信)
通过new Vue()创建一个中央事件总线,在A组件的生命周期函数created()中通过中央事件总线和$on绑定事件函数。在B组件中的事件函数中通过中央事件总线和$emit触发绑定的事件函数。
<body>
<div id="app">
<App></App>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const bus = new Vue();
Vue.component('A', {
data() {
return {
count: 0
}
},
template: `
<div>
{{ count }}
</div>
`,
created() {
bus.$on('add', (n) => {
this.count += n;
})
},
})
Vue.component('B', {
template: `
<div>
<button @click='handleClick'>加入购物车</button>
</div>
`,
methods: {
handleClick() {
bus.$emit('add', 1);
}
},
})
const App = {
data() {
return {
}
},
template: `
<div>
<A></A>
<B></B>
</div>
`,
}
new Vue({
el: '#app',
components: {
App
}
})
</script>
</body>
组件通信的其他方式(provide和inject)
在App组件的provide中声明要传递的数据,provide是一个函数,返回一个对象,在App组件的孙子组件B中通过inject来接收想要的数据。同时还有this.$parent和this.$children等可获取父组件、子组件。
<body>
<div id="app">
<App></App>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
Vue.component('A', {
template: `
<div>
<B></B>
</div>
`,
created() {
//获取父组件
console.log(this.$parent.title);
//获取子组件(此时B还没有创建所以取0索引时拿不到)
console.log(this.$children);
},
})
Vue.component('B', {
template: `
<div>
{{ msg }}
</div>
`,
inject: ['msg'],
created() {
//方法中使用加this
console.log(this.msg);
}
})
const App = {
data() {
return {
title: 'App'
}
},
provide() {
return {
msg: '我是你爷爷'
}
},
template: `
<div>
<A></A>
</div>
`,
}
new Vue({
el: '#app',
components: {
App
}
})
</script>
</body>