组件化开发
根据封装的思想,把页面上可重用的UI结构封装为组件
vue中的组件化开发
vue是支持组件化开发的前端框架
组件的后缀名是.vue
组件的三个组成部分
组件的模板结构
<template></template>
组件的js行为
<script>
export default{}
</script>
组件的样式
<style></style>
<template>
<div class="box">
<h3>{{username}}</h3>
<button @click="changeName">改名</button>
</div>
</template>
<script>
export default {
//data:{
// username:'admin'
//}
//上面的写法会报错
//组件中的data不能指向对象,组件中的data必须是一个函数
//并且要写在return中
data(){
return {
username:'admin'
}
},
methods:{
changeName(){
this.username = 'user'
//在vue组件中,this就是组件实例
console.log(this);
}
},
filters:{},
watch:{},
computed:{},
components:{}
}
</script>
<style lang = "less">
.box{
background-color: pink;
h3{
background-color: #FF0000;
}
}
</style>
注意:
组件的template标签中,只能包含一个根元素
启用less语法:在style开始标签上面加上lang="less"
在组件中使用其他组件
导入:在组件中导入其他组件
注册:在组件中注册其他组件
使用:在组件中以标签形式使用其他组件
<template>
<div class="app-container">
<h1>App 根组件</h1>
<hr>
<div class="box">
<!-- 渲染Left和Right组件 -->
<Left></Left>
<Right></Right>
</div>
</div>
</template>
<script>
import Left from './components/Left.vue'
import Right from './components/Right.vue'
export default {
components:{
Left,
Right
}
}
</script>
<style lang="less">
.app-container{
padding: 1px 20px 20px;
background-color: #efefef;
}
.box{
}
</style>
私有组件和全局组件
私有组件:通过components注册的是私有组件。如在组件A的components节点下,导入注册了组件F,则组件F只能用在组件A中,不能用在组件C中(C中未导入注册)。
全局组件:在main.js入口文件中,通过vue.component()方法,可以注册全局组件。一次注册,到处使用。
import Vue from 'vue'
import App from './App.vue'
//导入
import Test from './Test.vue'
//全局注册
Vue.component('MyTest',Test )
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
组件的props自定义属性
props 是组件的自定义属性,在封装通用组件的时候,合理地使用 props 可以极大的提高组件的复用性。
props允许使用者通过自定义属性,为当前组件指定初始值
props自定义的属性,可以像data中定义的属性一样使用
props是只读的,不可修改
封装时:
export default{
//数组格式
// props:['init','xxx','xxx'],
//对象格式
props:{
init:{
//默认值
default:0,
//数据类型
type:Number,
//是否必填
required:true
},
//如果定义的时候为驼峰法,如carNum,则在使用时可以用:car-num="变量"
carNum:{
//默认值
default:0,
//数据类型,可以是多个类型中的一个
type:[Number,String]
},
cars:{
type:Object,
//对象或数组默认值必须从工厂函数中获取
//或者不写default
default:function(){
return { id:1,brand:'BMW'}
}
}
},
data(){
return{
//props是只读的,不能修改其值,所以要把props的值赋给data中,才能进行修改
count:this.init
}
}
}
使用时:
<template>
<div class="left-container">
//使用
<MyCount :init="9" :car-num="9"></MyCount>
</div>
</template>
使用scoped处理组件之间的样式冲突问题
默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。
导致组件之间样式冲突的根本原因是:
单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素
解决:
给当前组件的style标签加上scoped属性
<style lang="less" scoped="scoped">
h3{
color: red;
}
</style>
原理是给当前组件的每一个标签加上相同的属性(组件内相同,组件之间唯一),构成css中的属性选择器
使用/deep/修改子组件的样式
<style lang="less" scoped="scoped">
.title{
color: blue;//不加/deep/,生成的选择器格式为.title[data-v-052242de]
}
/deep/.title{
color: blue;//加/deep/,生成的选择器格式为[data-v-052242de] .title
}
</style>
组件实例对象的理解
.vue组件文件,相当于一个类文件
在以标签形式使用组件时,相当于new了一个类的对象(实例)