目录
@ 路径自动提示
在 vscode 中导入下面的插件:
在设置 settings.json 插入如下配置:
// 导入文件时是否携带文件的拓展名
"path-autocomplete.extensionOnImport": true,
// 配置 @ 的路径提示
"path-autocomplete.pathMappings": {
"@": "${folder}/src"
},
使用组件的步骤
步骤1:使用 import 语法导入需要的组件
<script>
import Left from "@/components/Left.vue"
import Right from "@/components/Right.vue"
export default {}
</script>
步骤2:使用 components 节点注册组件
<script>
import Left from "@/components/Left.vue"
import Right from "@/components/Right.vue"
export default {
components: {
Left,
Right
}
}
</script
步骤3:以标签形式使用刚才注册的组件
<div class="box">
<!-- 渲染 Left 组件和 Right 组件 -->
<Left></Left>
<Right></Right>
</div>
以上修改内容都是在 App.vue 中修改
全局注册组件
注册私有组件
在组件 A 的 components 节点下注册的组件,不能在其他与组件 A 平级的组件中使用
注册全局组件
在 vue 项目中的 main.js 入口文件中,通过 Vue.component() 方法,可以注册全局组件
// 导入需要全局注册的组件
import Count from "@/components/Count.vue"
// 参数1:字符串格式,表示组件的 "注册名称"
// 参数2:需要被全局注册的组件
Vue.component('MyCount', Count);
然后在需要此组件的组件中以标签形式使用接口
组件自身中不能使用自己
自动闭合标签插件
自定义属性 props
props
为 count 组件声明 props 自定义属性
props 是组件的自定义属性,在封装通用组件的时候,合理地使用 props 可以极大地提高组件的复用性
自定义属性 props 传递的是字符串,不是数值
props 中的数据,可以直接在模板结构中被使用
props 是只读的
Count.vue
<script>
export default {
// props 是自定义属性,允许使用者通过自定义属性,为当前组件指定初始值
// props: ['自定义属性1', '自定义属性2', '自定义属性3', ...]
props: ['init'],
}
</script>
<div>
<p>count 的值是: {{ init }}</p>
<button @click="init++">+1</button>
</div>
Left.vue
<div class="left-container">
<MyCount init = "9"></MyCount>
</div>
Right.vue
<div class="right-container">
<MyCount init="6"></MyCount>
</div>
集合 v-bind 使用自定义属性
组件的封装者:Count.vue
组件的使用者:Left.vue、Right.vue
在 v-bind 中写入的内容都是 JavaScript
<div class="left-container">
<!-- v-bind:init="9" 传递的值就是数值 -->
<!-- v-bind:inti="'9'" 传递的值是字符串 -->
<MyCount :init = "9"></MyCount>
</div>
props 是只读的
不建议直接修改 props 自定义的属性,因为将来该属性可能会被覆盖
vue 规定:组件中封装的自定义属性是只读的,程序员不能直接修改 props。否则会报错
要想修改 props 的值,可以把 props 的值转存到 data 中,data 中的数据是可读可写的
<template>
<div>
<h5>Count 组件</h5>
<p>count 的值是: {{ count }}</p>
<!-- 不建议直接修改 props 自定义的属性 init,因为将来 init 可能会被覆盖 -->
<button @click="count++">+1</button>
</div>
</template>
<script>
export default {
data() {
return {
count: this.init,
}
},
methods: {},
// props 是自定义属性,允许使用者通过自定义属性,为当前组件指定初始值
props: ['init'],
}
</script>
上述代码中,init 只负责初始化,其他的功能实现都通过 count
当页面中的数值发生改变时,count 值将发生改变,但 init 值并不会被改变
default 默认值
数组格式的 props 不能设置默认值
对象格式的 props 才可以设置默认值
<script>
export default {
// props: ['init',] 数组格式的 props 不能设置默认值
// props 是自定义属性,允许使用者通过自定义属性,为当前组件指定初始值
props: {
init: {
// 用 default 属性定义属性的默认值
default: 8,
}
},
}
</script>
type 值类型
在声明自定义属性时,可以通过 type 来定义属性的值类型
<script>
export default {
props: {
init: {
default: 8,
// 用 type 属性定义属性的值类型
// 如果传递过来的值不符合此类型,则会在终端报错
type: Number,
}
},
}
</script>
required 必填项
<script>
export default {
props: {
init: {
default: 8,
type: Number,
// 规定只要使用此组件的组件都必须传 init 属性,否则将会报错
required: true,
}
},
}
</script>
样式冲突-了解 scoped 的使用和底层实现原理
组件之间的样式冲突问题
默认情况下,写在 .vue 组件中的样式会全局生效,因此很容易造成多个组件之间的样式冲突问题
导致组件之间样式冲突的根本原因是:
- 单页面应用程序中,所有组件的 DOM 结构,都是基于唯一的 index.html 页面进行呈现的
- 每个组件中的样式,都会影响整个 index.html 页面中的 DOM 元素
解决样式冲突
原理:保证每一个组件中都有一个 data-v-00x,以区分每一个组件,从而解决样式冲突的问题
<template>
<div class="left-container" data-v-001>
<h3 data-v-001>Left 组件</h3>
<MyCount :init = "9" data-v-001></MyCount>
</div>
</template>
<style lang="less">
h3[data-v-001] {
color: darkcyan;
}
</style>
实际开发中,只需要在 style 标签后面写上 scoped 属性,vue 就会自动为该组件的 template 中的每一个标签添加 data-v-00x,从而解决样式冲突的问题
<style lang="less" scoped>
h3 {
color: darkcyan;
}
</style>
/deep/ 样式穿透
使用 deep 修改子组件中的样式
当使用第三方组件库的时候,如果有修改第三方组件默认样式的需求,需要用到 /deep/
scoped 也是有缺陷的
父组件 Left.vue 无法直接对子组件 Count.vue 中的标签进行样式修改
<style lang="less" scoped>
h3 {
color: darkcyan;
}
h5 {
color: beige;
}
</style>
以上对子组件中 h5 标签的样式修改并不会起作用。
因为 scoped 属性只会为当前组件 Left.vue 中 template 中的标签添加 data-v-xxx。并不会为子组件标签添加 data-v-xxx
此时就需要用到 /deep/,/deep/ 将为子组件中的标签添加 data-v-xxx
<style lang="less" scoped>
/* 原先的解决办法是 h5 [data-v-xxx] */
/* 加上 /deep/ 之后,[data-v-xxx] h5 */
/deep/ h5 {
color: beige;
}
</style>
vue 组件的实例对象
.vue 文件是一个模板,此模板真正被渲染到页面上,需要 vue-template-compiler 进行编译
Count.vue 可以被看作是一个构造函数
使用标签引入 Count.vue 的过程,可以看作是一个 new Vue 实例对象的过程