vue组件
1.什么是组件化开发
组件化开发指的是:根据封装的思想,把页面上可重用的UI结构封装为组件,从而方便项目的开发和维护。
2.vue中的组件化开发
vue是一个支持组件化开发的前端框架。
vue中规定:组件的后缀名是.vue。之前解除到的App.vue文件本质上就是一个Vue的组件。
3.vue组件的三个组成部分
每个.vue组件都由3部分构成,分别是:
- template -->>组件的模板结构
- script -->>组件的javascript行为
- style -->>组件的样式
<template>
<!--组件的模板结构中只能有唯一一个根节点-->
<div class="test-box">
<h3>这是用户自定义的xxx</h3>
</div>
</template>
<script>
//默认导出,这是固定写法
export default {
//data数据源
//注意 .vue组件中的data不能像之前一样,不能指向对象
//注意: 组件中的data必须是一个函数
data(){
//这个return出去的{}中可以定义数据
return {
username:'zs'
}
},
//定义组件方法
methods:{
changeName(){
//在组件中,this表示当前组件的实例对象
this.username = 'wakakakaka'
}
},
watch:{
},
computed:{
},
filter:{
}
}
</script>
// 默认只支持css语法,如果要启用less语法,需要在style标签中加入lang = "less"
<style lang="less">
.test-box {
background-color:pink;
h3 {
color:red;
}
}
</style>
在Vue组件中,data选项需要返回一个函数,而不是直接返回一个对象,主要是为了确保每个组件实例都能够独立地拥有自己的数据副本。
当data选项返回一个对象时,这个对象会在组件的所有实例之间共享,即每个实例都会引用相同的data对象。这样,在一个实例中修改data的值会影响到其他实例,从而导致不可预测的结果。
为了避免这种共享数据的问题,Vue要求将data选项返回一个函数。这样,每个组件实例在创建时,都会调用该函数并返回一个全新的数据对象。这样,每个实例都会拥有独立的数据副本,修改数据只会影响到当前实例,不会影响其他实例。
4. 组件中的父子关系
组件在封装好后,彼此之间是相互独立的,不存在父子关系。
在使用组件的时候,根据彼此的嵌套关系,才形成了父子关系、兄弟关系
4.1 使用组件的三个步骤
1)在父组件中使用import语法导入需要的组件
2)使用components 节点注册组件
3)让组件以标签的形式使用
扩展 在vscode中配置@路径提示的插件
插件名: Path Autocomplete
在settings.json中的头部括号内加上以下代码:
//导入文件时是否携带文件的扩展名
"path-autocomplete.extensionOnImport": true,
//配置@的路径提示
"path-autocomplete.pathMappings": {
"@":"${folder}/src"
},
4.2 通过comonents注册的组件是私有子组件
例如:
在组件A的components节点下,注册了组件F。则组件F只能用在组件A中,不能被用在组件C中。
4.3 注册全局子组件
在vue项目的main.js入口文件中,通过VUe.component() 方法可以注册全局组件。示例代码如下:
//导入需要全局注册的组件
import Count from '@/components/HelloWorld.vue'
//参数1:字符串格式,表示组件的 '注册名称'
//参数2: 需要被全局注册的那个组件
Vue.component('mycount',Count)
5.组件的props
props 是组件的自定义属性,在封装通用组件的时候,合理地使用props可以极大的提高组件的复用性!
它的语法格式如下:
export default {
//组件的自定义属性
//props中的数据,可以直接在模板结构中使用
//Props中的数据只能读取不能更改,不要修改props的值,终端会报错
//props 里面的属性,也能通过 this访问到
//要想修改props的值,可以把props值转存到data中,因为data中的数据都是可读可写的
props:['自定义属性A','自定义属性B','其他自定义属性'...],
//组件的私有数据
data(){
return {
}
}
}
//在count 组件中
<template>
<div>
<!-- //props中的数据,可以直接在模板结构中使用-->
<h3>count:{{count}}</h3>
<button @click="count">+</button>
</div>
</template>
<script>
export default {
props:['init'],
data(){
return{
count:this.init,
}
}
}
</script>
<style>
</style>
----------------------
//在使用了count的组件的其他组件中
<template>
//不加:(v-bind)是字符串,加了:是数字
<mycount :init='10'></mycount>
</template>
<script>
export default {
}
</script>
<style>
</style>
5.1 props default 、type 和 required
如果用户没有传值,则需要给props一个默认值,需要把props写成对象形式
<script>
export default {
props:{
//自定义属性A
init:{
//用default属性定义属性的默认值
default:0,
//指定自定义属性的值类型
type:Number,
//表示必须传一个值,不传就会报错,哪怕有默认也会报错,和默认值无关
required:true,
},
//自定义属性B...
}
data(){
return{
count:this.init,
}
}
}
</script>
6.组件之间的样式冲突问题
默认情况下,卸载.vue组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题。
导致组件样式冲突的根本原因是:
1)单页面应用程序中,所有组件的DOM结构,都是基于唯一的index.html页面进行呈现的
2)每个组件中的样式,都会影响整个index.html页面中的DOM元素
6.1解决样式冲突问题
原理:通过自定义属性结合属性选择器来设置
<template>
<div>
<h3 data-v-003>左组件</h3>
<mycount :init='10'></mycount>
</div>
</template>
<script>
export default {
}
</script>
<style>
h3[data-v-003]{
color:red;
}
</style>
由于给每个标签自定义属性很麻烦,vue简化了这一操作,只需要在style标签中加上 scoped属性即可解决样式冲突问题
<style scoped>
h3[data-v-003]{
color:red;
}
</style>
6.2 /deep/样式穿透
在父组件中修改子组件样式的时候,使用/deep/
当时用第三方组件库的时候,如果有修改默认样式需求则需要用到/deep/
<style>
//加上deep 标签变成 [data-v-xxxx] h5
//不加deep 标签为 h5[data-v-xxx]
/deep/h5{
color:pink;
}
</style>
6.3 组件工作原理
浏览器无法解析vue文件,每个.vue文件并不是直接执行
pakage.json 下的 vue-template-compiler": “^2.6.14” 这个包帮助浏览器编译解析vue文件。
创建vue模板,只要不使用,就不会创建实例。