处理UI界面的重用(Vue组件)
组件系统是 Vue 的另一个重要概念,它是一种抽象,允许我们使用小型、独立和通常可复用的组件构建大型应用,因此几乎任意类型的应用界面都可以看成一个组件树。
组件注册
- 根组件: 通过
new Vue()
来实例化的,通常只有一个 - 可复用性组件: 通过
Vue.component()
来创建
组件分为全局组件,局部组件
全局注册
通过 component 来实现注册
只要是新实例化对象就能调用 k-div
可复用性组件
- js准备
Vue.component("k-div",{
template:`
<div>
<div>hello</div>
<div>world</div>
</div>
`
})
let app = new Vue({
el:"#app"
});
- HTML调用
<div id="app">
<k-div> </k-div>
</div>
- 页面显示结构
局部注册
注意: 通过属性名 components 来实现
全局注册时没有 s
这种注册的方式,只允许在 app变量代表的区域内使用 k-div
- js准备
let app = new Vue({
el:"#app",
// 局部注册可复用性组件的方式 有 s
components:{
"k-div":{
template:`
<div>
<div>hello</div>
<div>world</div>
</div>
`,
}
}
});
- HTML调用
<div id="app">
<k-div> </k-div>
</div>
- 页面结构
组件嵌套
全局组件嵌套
- 代码实现
Vue.component("k-div",{
template:`
<div>
<div>hello</div>
<p-p-t></p-p-t>
<div>world</div>
</div>
`,
components:{
'p-p-t':{
// 只允许存在一个总标签
template:`
<div>
<p>我是你需要仰望的约德尔人</p>
<span>测试结果嵌套</span>
</div>
`
}
}
})
let app = new Vue({
el:"#app"
});
- 页面结构
局部组件嵌套 - 代码实现
let app = new Vue({
el:"#app",
// 局部注册可复用性组件的方式 有 s
components:{
"k-div":{
template:`
<div>
<div>hello</div>
<p-p-t></p-p-t>
<div>world</div>
<p-p-t></p-p-t>
</div>
`,
components:{
'p-p-t':{
template:`
<h3>你好,世界</h3>
`
}
}
}
}
});
- 页面结构
组件数据
组件内部的数据是各自独立的,为维持数据的独立性
组件内部的数据写成函数的形式
data:function(){ return { 对象形式 } }
- 代码结构
<div id="app">
<k-div> </k-div>
</div>
<script>
Vue.component("k-div",{
template:`
<div>
<div>hello</div>
<div>world</div>
<p>{{name}}</p>
</div>
`,
data:function(){
return {
// 使用的是这里的 name
name:"kids"
}
}
})
let app = new Vue({
el:"#app",
data:{
// 这里的 name 并不没有被使用
name:"father"
}
});
</script>
- 页面效果
组件传参
父传子
- 父组件传递数据
使用 v-bind 绑定属性的方式,绑给子组件调用时的标签
<k-div :height="175" :msg="txt" > </k-div>
- 子组件接收数据
在子组件的内部使用props属性,以数组的形式接收
props:["height","msg"]
- 代码实现
<div id="app">
<p v-text="name"></p>
<!-- 父组件 传递 使用 v-bind 绑定属性的方式 -->
<k-div :height="175" :msg="txt" > </k-div>
</div>
<script>
// 可复用性组件的全局注册
Vue.component("k-div",{
// 子组件 接收 使用 props
// props: 使用存储数据,
// 组件内部数据的使用方式和 data 一致
props:["height","msg"],
template:`
<div>
<div>hello</div>
<div>world</div>
<hr/>
<span>接收的信息{{height}}-{{msg}}</span>
</div>
`,
data:function(){
return {
name:`子组件的name:kids`
}
}
})
let app = new Vue({
el:"#app",
data:{
name:`父组件的name:father`,
txt:"父组件的文本信息"
}
});
</script>
子传父
- 子组件传递数据
在特定条件下,触发自定义事件来通知父组件 - 父组件接收数据
父组件在接收到通知后,自行决定是否修改数据
- 代码实现
<div id="app">
<k-div @victory-on="fn"></k-div>
<p> 接收的数据:{{text}} </p>
</div>
<script>
Vue.component("k-div",{
template:`
<div>
<div>hello</div>
<div>world</div>
<button @click="goOn">点击</button>
{{name}}
</div>
`,
data:function(){
return {
name:`子组件的name:kids`
}
},
methods:{
goOn(){
// 不允许出现 大写 监听名称 这里的名称
// 与 挂载点处的点击事件名称必须一致
this.$emit("victory-on",this.name)
}
}
})
let app = new Vue({
el:"#app",
data:{
name:`父组件的name:father`,
text:"测试文本信息"
},
methods:{
fn:function(item){
console.log(item)
this.text = item;
}
}
});
</script>
- 页面效果
两种方式的区别
- 父 => 子
父组件调用子组件,通过子组件的属性传输数据
子元素内部通过 props 配置项(数组形式),来接收对应的数据 - 子 => 父
vue中的数据默认的单向流动,只能父到子直接传递,但是子到父不能直接改
因为父级的数据,不一定只是某个子组件使用 或许还有其他的组件使用
子组件随意修改父组件数据很容易混乱 - 子组件想修改数据
子组件执行 $emit() 来触发自定义事件
(自定义名称 不允许出现大写)
父组件监听 子组件触发的自定义事件
监听触发 执行父级的回调函数