创建组件
1. 组件系统是 Vue 的另一个重要概念,因为它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用。仔细想想,几乎任意类型的应用界面都可以抽象为一个组件树:
2. 定义组件选项
const options = {
template: '模板-视图的结构(布局)',
data() {
return {}
},
methods: {},
computed: {},
components: {},
}
注意:
- template 中定义的结构,必须使用单个根元素包裹
- data 必须是函数结构,在函数体内部返回一个普通对象
- 为什么 data 要是函数?
(1).组件是可被复用的,当创建同一个组件的不同实例时,如果 data 是普通对象,则不同的实例引用到的是同一个 data 对象,当任意一个实例中对 data 数据进行更新时,其它实例都会受影响,通常这与实际业务不符。
(2).定义成函数,则创建各组件实例时,会调用 data 函数生成组件实例自身私有用到的对象数据,各组件实例间数据是独立的,互不受影响。
3. 注册组件:
- 注册全局组件 Vue.component(name, options)
<script src="/Vue框架的初步了解/libs/vue.js"></script>//引入Vue框架文件
<script>
/* TodoHeader */
Vue.component('todo-header', {//这是全局组件TodoHeader
template: `
<h3>组件渲染的内容。。。</h3>
`,
})
- 注册局部组件 components: {name: componentOptions}
/* TodoList */
Vue.component('todo-list', {//这是全局组件TodoList
template: `
<ul v-if="true">
<todo-item v-for="n in 4"></todo-item>
</ul>
<div v-else>
代办事项列表为空,请添加代办事项!
</div>
`,
components: { //局部组件注册 toto-item
'todo-item': {
template: `
<li>
<input type="checkbox" />
<span>代办事项内容</span>
<button>删除</button>
</li>
`,
},
},
})
**4.**渲染主键
<div id="app">
<todo-header></todo-header>// 刚才注册的组件名,采用短横线命名规范
<todo-input></todo-input>
<todo-list></todo-list>
<todo-footer></todo-footer>
</div>
/* 注册的组件 */
/* APP */
new Vue({
el:'#app',
})
注意:
在使用自定义组件名作为标签名称使用时,要完整书写独立的结束标签,标签名称应该使用短横线命名的规范。
父子件通信
- 父组件传数据给子组件:利用属性(props)的方式传递数据。
(1).子组件定义时,在选项中使用 props 定义组件可接收的属性。
components: {
son: {
template: `
<div>
<span>这是子组件内容:{{ name }} - {{ sex }} - {{ phone }}</span><br>
//标签里接收 (props) 属性传递来的数据
<button @click="handleClick">像父组件传递数据</button>
</div>
`,
// props: ['name' , 'sex' ,'phone'],//声明组件可接收的属性名称
props: {// 声明组件及可接收的属性名极其校验规则
name: String,
sex: {
type: String,
default: '男',
},
phone: {
type: String,
required: true,
}
},
(2).父组件中使用到子组件(标签)时,在标签内部书写需要传递给子组件的数据(是 name=value 键值对格式的属性)。
Vue.component('father',{
template: `
<div>
<span>这个是父组件内容</span>
// 在条用的子组件标签内部书写传递给子组件的数据
<son name="小明" sex="男" :phone="phone"></son>
</div>
`,
- 子传父:利用事件方式传递数据。
(1).父组件中使用到子组件标签时,利用v-on
注册一个自定义的事件监听,通常引用在父组件中定义的methods
方法去处理接收到的数据。
Vue.component('father',{
template: `
<div>
<span>这个是父组件内容</span>
<!-- <son name="小明" sex="男" :phone="phone"></son> -->
<son name="小明"
:phone="phone"
@receive="handleReceive"
></son>
</div>
`,
data() {
return {
phone: '123456789',
}
},
methods: {
handleReceive(data) {
console.log('这是父组件中用于接收数据的方法:',data);
}
},
(2).在子组件中需要传递数据时,调用 this.$emit(eventName(上面自定义事件名), data(向父组件传递的数据))
触发在父组件中绑定的自定义事件并传递数据即可($emit() 的第二个参数是需要传递给父组件的数据)
components: {
son: {
template: `
<div>
<span>这是子组件内容:{{ name }} - {{ sex }} - {{ phone }}</span><br>
<button @click="handleClick">像父组件传递数据</button>
</div>
`,
// props: ['name' , 'sex' ,'phone'],//声明组件可接收的属性名称
props: {// 声明组件及可接收的属性名极其校验规则
name: String,
sex: {
type: String,
default: '男',
},
phone: {
type: String,
required: true,
}
},
methods: {
handleClick() {
console.log('传送数据');
// 调用(触发)在父组件中绑定的事件,像父组件传递数据。
this.$emit('receive',{code: 200,data: {uuserInfo: {name: '张三',age: 18}}})
},
}
跨组件层级组件通信
- 转换为父子关系
- event-bus(事件总线):
(1).借助 Vue 实例中的$on()
与$emit()
方法来实现:首先创建一个全局的 Vue 实例对象(bus
)
//创建一个 Vue 实例对象,用于在组件间进行通信(不传递选项对象参数)
// const eventBus = new Vue()
//向 Vue.prototype 原型中添加一个自定得 $bus 属性
//在所有得 Vue 实例及组件实例中,都可以使用 this.$bus
//来访问到这个属性得值
Vue.prototype.$bus = new Vue()
(2).在需要接收数据的组件中,利用 bus
来注册事件监听(绑定自定义事件)
methods: {
// 处理添加代办事项
handIeAddTodoTiem(title) {
this.todos.push({
id: Math.random(),
title,
completed: false,
})
},
// 删除代办事项
removeIodoItem(id) {
this.todos = this.todos.filter(todo => todo.id !== id)
}
},
created() { // 这是一个生命周期得钩子函数
// 当前组件(App)会接收数据,调用 eventBus.$on() 绑定事件
// eventBus.$on('remove', this.removeIodoItem)
this.$bus.$on('remove', this.removeIodoItem)
// remove (为自定义事件) removeIodoItem (事件处理函数)
}
(3).在需要传递数据的组件中,利用 bus
来触发事件并传递数据。
// 在需要传递数据的组件中,利用 `bus` 来触发事件并传递数据。
methods: {
handleRemove() {
// eventBus.$emit('remove', this.item.id)
this.$bus.$emit('remove', this.item.id)
}
}
- vuex