Vue笔记-系列
Vue笔记[一]-初识
Vue笔记[二]-组件化
Vue笔记[三]-ToDoList
Vue笔记[四]-动画、Vuex
Vue笔记[五]-路由
Vue笔记[六]-Vue3
Vite、Pinia、Router
QX-AI
GPT-4
QX-AI初始化中...
暂无预设简介,请点击下方生成AI简介按钮。
介绍自己
生成预设简介
推荐相关文章
生成AI简介

生命周期

Vue会在一些特殊时刻去调用一些特殊的函数

这些要经过的特殊时刻就是生命周期,要调用的特殊函数就是生命周期函数(生命周期钩子,生命周期回调函数)

为什么叫钩子:vm在某个步骤上已经写了执行该名称的函数,但函数内容未定义,得程序员来定义。即生命周期函数的名字不可更改,但函数的具体内容需要程序员根据业务需求编写

Vue实例的生命周期:
1、初始化显示

  1. beforeCreate() => 初始化:生命周期、事件,但数据代理还未开始
  2. create() => 初始化:数据监测、数据代理
  3. beforeMount() => 模板解析完毕,虚拟DOM建立,但还未挂载
  4. mounted() => 挂载完毕,虚拟DOM转为真实DOM

2、更新状态: this.xxx = value

  1. beforeUpdate() => 数据已更新,但页面还未更新,新旧虚拟dom还未对比
  2. updated() => 数据和页面都是新的

3、销毁 vue 实例: vm.$destroy() 触发下面两个钩子

  1. beforeDestroy() => 此时vm上所有东西都是可用的,但不再解析模板更新页面
  2. destroyed() => vm彻底被销毁

还有三个钩子不在图中,和路由相关

常用钩子:

  1. mounted: 发送ajax请求、启动定时器、绑定自定义事件、订阅消息等【初始化操作】
  2. beforeDestroy: 清除定时器、解绑自定义事件、取消订阅消息等【收尾工作】

关于销毁Vue实例:

  1. 在大多数场景中不应该调用 vm.$destroy() 。最好使用 v-if 和 v-for 指令以数据驱动的方式控制子组件的生命周期。
  2. 销毁后借助Vue开发者工具看不到任何信息
  3. 销毁后自定义事件会失效,但原生D0M事件依然有效
  4. 在beforeDestroy中做好善后工作

组件

组件:应用中局部功能代码资源集合

在 Vue 中,组件是可复用Vue实例

组件体现了封装的思想,组件也可以嵌套封装

组件化:编写一套组件,在所需的页面引入组件,当应用中的功能都是多组件的方式来编写的, 这个应用就是一个组件化的应用

为什么要组件化:传统的三件套可以只能做到拆分css、js模块化,而html结构不复用,且文件依赖关系(N-1-N)复杂,组件化后,页面的每个部分都对应一个组件,组件中的小功能部分也能对应更多组件,组件逐层嵌套,最终由一个Vue实例管理,依赖关系清晰,通过引入组件构建页面,代码复用率高,后续维护也能针对性找到组件进行操作

非单文件组件

非单文件组件:一个文件中包含n个组件,实际开发几乎不用这种写法

使用组件流程:

  1. 定义组件: Vue.extend()
    - 配置项中不能写el属性,因为最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器
    - 组件中的data必须用函数式,避免组件被复用时,数据存在引用关系。
    - 使用 template 配置组件模板结构,必须有一个根元素包裹
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    const school = Vue.extend({
    // 模板,template中的模板必须有一个根元素包裹
    template: `
    <div>
    <h3>{{name}}</h3>
    <h3>{{city}}</h3>
    </div>
    `,
    // 组件中的data必须用函数式
    // 因为对象是引用类型数据,函数式返回一个新对象才能保证多次引用组件的data互不影响
    data() {
    return {
    name: '五道口',
    city: '京海'
    }
    }
    })

  2. 注册组件:
    - Vue.component() 全局注册
    - 局部注册,在vm配置项的 components 属性中
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    // 全局注册组件,多个vue实例都能使用该组件
    Vue.component('school', school)
    // 组件由vm管理
    new Vue({
    el: '#root',
    data: {
    msg: '信息'
    },
    // 局部注册组件
    components: {
    // 组件名
    student
    }
    })

  3. 使用组件:在容器中写组件标签

案例:

非单文件组件案例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
<div id="root">
<h2>{{msg}}</h2>
<!-- 引用组件,组件标签 -->
<school></school>
<hr />
<!-- 多次引用组件,且数据独立互不影响 -->
<student></student>
<student></student>
</div>
<script>
// 使用Vue.extend定义一个组件,传入一个配置项
const school = Vue.extend({
// 模板,template中的模板必须有一个根元素包裹
template: `
<div>
<h3>{{name}}</h3>
<h3>{{city}}</h3>
</div>
`,
// 组件中的data必须用函数式
// 因为对象是引用类型数据,函数式返回一个新对象才能保证多次引用组件的data互不影响
data() {
return {
name: '五道口',
city: '京海'
}
}
})
const student = Vue.extend({
template: `
<div>
<h3>{{name}}</h3>
<h3>{{age}}</h3>
<button @click="age++">年龄加一</button>
</div>
`,
data() {
return {
name: 'chuckle',
age: '19'
}
}
})
// 全局注册组件,多个vue实例都能使用该组件
Vue.component('school', school)
// 组件由vm管理
new Vue({
el: '#root',
data: {
msg: '信息'
},
// 局部注册组件
components: {
// 组件名
student
}
})
</script>

注意事项

关于组件名:

  1. 组件名只有一个单词时,引用组建时写小写 <student>大写 <Student> Vue只会去找小写的组件名,即组件名只有一个单词时需使用小写
  2. 组件名由多个单词组成时,有两种写法:横杠写法双驼峰写法(只能在脚手架环境中使用)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    <!-- 横杠写法 -->
    <my-school></my-school>
    <script>
    Vue.component('my-school', MySchool)
    </script>
    <!-- 双驼峰写法(只能在脚手架环境中使用) -->
    <MySchool></MySchool>
    <script>
    Vue.component('MySchool', MySchool)o[]
    </script>

  3. 不能使用html已有标签名作为组件名
  4. 在定义组件时添加 name 配置,无论注册使用时是什么名,在开发者工具中显示的都是该 name(首字母同样会自动显示大写)
    1
    2
    3
    4
    5
    6
    7
    8
    9
    const school = Vue.extend({
    // 设置 name
    name: 'MySchool',
    template: ``,
    data() {
    return {}
    }
    })

脚手架环境下,可以使用组件时可以写双标签 <school></school>自闭合标签 <school/>,不用使用脚手架时,<school/> 会导致后续组件不能渲染。

定义组件可以简写:
注册组件时底层有判断,若是一个对象,Vue会帮我们调用Vue.extend,并将对象作为配置项传入

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 简写,实际上也调用了Vue.extend
const school = {
template: ``,
data() {
return {}
}
}
// 写上 Vue.extend 不简写
const school = Vue.extend({
template: ``,
data() {
return {}
}
})

组件嵌套

组件嵌套:一个组件也会用到其它多个组件,组件关系逐层嵌套,形成父子组件关系

使用方式:在父组件中 components 配置项注册其子组件,组件在哪注册就要在哪使用

开发中的技巧:定义一个名为 app 的组件,用于管理页面中最上层的所有组件,而 vm 本身只管理 app 组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
<div id="root"></div>
<script>
// 子组件的定义要放到父组件前
const student = {
template: `
<div>
<h3>学生姓名:{{name}}</h3>
<h3>学生年龄:{{age}}</h3>
</div>
`,
data() {
return {
name: 'chuckle',
age: '19'
}
}
}
// 定义父组件
const school = {
// 在父组件中使用子组件
template: `
<div>
<h2>学校名:{{name}}</h2>
<hr />
<student></student>
</div>
`,
data() {
return {
name: '五道口'
}
},
// 注册子组件
components: {
student,
}
}
// 定义一个欢迎语组件,和school组件同级
const hello = {
template: `
<div>
<h3>{{welcome}}</h3>
<hr/>
</div>
`,
data() {
return{
welcome: '欢迎!'
}
}
}
// 定义app组件,管理所有组件
const app = {
template: `
<div>
<hello></hello>
<school></school>
</div>
`,
// 管理下一层的父级组件
components: {
school,
hello
}
}
new Vue({
el: '#root',
// 应用app组件,替换掉root容器
template:`<app></app>`,
components: {
// vm只管理app组件
app
}
})
</script>

VueComponent构造函数

每个组件的本质都是一个 VueComponent() 构造函数,它由 Vue.extend() 生成并返回

每次调用 Vue.extend() ,返回的都是一个全新的 VueComponent() 构造函数

打印app组件:

1
2
3
4
5
const app = Vue.extend({
template: ``,
components: {}
})
console.log(app)
输出
1
2
3
ƒ VueComponent(options) {
this._init(options);
}

既然是构造函数,使用它就需要 new 创建实例
只需要在合适的位置写 <school></school> ,Vue 在解析模板时会自动去创建对应的VueComponent构造函数的实例

即Vue会在解析模板自动执行new VueComponent(options)

1、this的指向:
(1) Vue.extend(options) 组件配置中,this 指向 VueComponent 实例对象
(2) new Vue(options) 配置中,this 指向 vm 实例对象

2、Vue对组件的关系设计:

  1. 每种组件定义时都需要调用 Vue.extend() ,它返回一个新的 VueComponent() 构造函数,即不同种类的组件,其对应的 VueComponent 构造函数不同,以此来区分组件的种类
  2. Vue在解析模板时,会对每个组件标签都调用一次对应的构造函数,返回的实例都是互不影响的,以此来区分同种组件不同实例(同种组件在出现在页面不同位置,展示不同内容)

vm与vc

VueComponent() 的实例对象,简称vc(也可称之为:组件实例对象)
Vue() 的实例对象,简称vm

对vm和vc的理解:
1、vm 和 vc 长得差不多(属性和方法都一样的),因为 Vue(options)VueComponent(options) 两个构造函数,在源码中都是调用了其原型上_init(options)

2、vm 或 vc 的 $children 属性以数组形式保存着 vm 或 vc 所管理的组件子组件实例对象

3、组件是可复用的 Vue 实例(vm),所以它们与 new Vue() 接收相同的配置选项 options,例如 data、computed、watch、methods 以及生命周期钩子等。仅有的例外是像 el 这样根实例特有的选项。

4、vc 由 vm 管理,vc 没有 el 配置,只有 vm 能通过 el 配置来指定为谁服务

重要内置关系

VueComponent.prototype.__proto__ = Vue.prototype

复习原型与原型链JavaScript基础笔记(3)—原型与原型链

$mount、$watch 等属性和方法都在 Vue.prototype 上,也就是 Vue 的原型上

作用:这个重要的内置关系将组件的原型Vue的原型通过 __proto__ 相连,使 VueComponent 继承 Vue原型,让组件实例顺着原型链也能使用$mount、$watch 等属性和方法,

目的:组件实例对象(vc)可以访问到Vue原型上的属性、方法

单文件组件

单文件组件:一个文件中仅包含一个组件,文件后缀为 .vue

浏览器并不认识.vue文件,需要通过 webpack脚手架,将其加工为JS文件

文件名推荐规则:单个单词大写,多个单词双驼峰

.vue文件中代码分为三个标签

  1. <template> => 组件的结构
  2. <script> => 组件交互相关代码,包含组件所用的数据、方法
  3. <style> => 组件的样式

主要的文件:需放入脚手架中才能运行
1、xxx.vue 各种组件
2、App.vue 汇总所有组件
3、main.js 入口文件,创建Vue实例,注册App组件并应用
4、index.html 页面

一个简单的组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<template>
<!-- 组件的结构 -->
<div class="student">
<h2>{{ name }}}</h2>
<h3>{{ age }}}</h3>
</div>
</template>

<script>
// 组件交互相关代码
// 省略Vue.extend,直接暴露组件的配置对象
export default {
name: 'Student', //最好与文件名保持一致
data() {
return {
name: 'chuckle',
age: '19'
}
}
}
</script>

<style>
/* 组件的样式 */
.student {
background: #ccc;
border-radius: 8px;
}
</style>

必须有 App.vue 汇总所有组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<School></School>
</div>
</template>

<script>
// 引入Student组件
import School from "./Student.vue"

export default {
name: "App",
components: {
School
}
}
</script>

<style></style>

main.js 入口文件,创建Vue实例,注册App组件并应用

1
2
3
4
5
6
7
8
9
10
import App from "./App.vue" // 引入App组件

new Vue({
el: '#root',
template: '<App></App>',
components: {
App
}
})

index.html 页面

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<!-- 准备一个容器 -->
<div id="root"></div>
<!-- 引入vue文件 -->
<script src="../../js/vue.js"></script>
<!-- 引入入口文件 -->
<script src="./main.js"></script>
</body>
</html>

脚手架Vue-cli

Vue 脚手架是 Vue 官方提供的标准化开发工具(开发平台)

Vue 有多种脚手架,Vue-cli 是其中一种

起步

安装:该全局模块会暴露一个全局命令vue

1
npm install -g @vue/cli

创建一个项目

1
vue create <项目名>

选择项目的vue版本,babel用于ES6转ES5,eslint语法检查

1
2
3
4
5
Vue CLI v5.0.8
? Please pick a preset:
Default ([Vue 3] babel, eslint)
> Default ([Vue 2] babel, eslint)
Manually select features

等待安装完毕,运行项目

1
npm run serve

项目文件结构

默认 HelloWord 项目结构:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
├─ public
│ ├─ favicon.ico
│ └─ index.html

├─ src
│ ├─ assets
│ │ └─ logo.png
│ ├─ components
│ │ └─ HelloWorld.vue
│ ├─ App.vue
│ └─ main.js

├─ .gitignore
├─ vue.config.js
├─ babel.config.js
├─ jsconfig.json
├─ package-lock.json
├─ package.json

文件解释:

1、根目录中的一些配置文件:

  1. babel.config.js babel控制文件,脚手架已写好,无需再动
  2. package.json 定义了当前项目所需要的各种模块,以及项目的配置信息(比如名称、版本、许可证等)
  3. package-lock.json 锁定所有模块的版本号,包括主模块和所有依赖子模块
  4. .gitignore git忽略文件配置
  5. jsconfig.json 指定根文件和JavaScript语言服务提供的功能选项,明确项目的文件范围
  6. vue.config.js 一个可选的脚手架配置文件,进行vue项目本地运行和构建相关配置,若根目录中存在这个文件,它会被 @vue/cli-service 自动加载

2、src文件夹:有些熟悉的文件,main.js入口文件、app.vue组件等
- assets文件夹:存放静态资源
- components:存放组件,除了App组件

main.js有一些变化
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
// 整个项目的入口文件
// 引入Vue
import Vue from 'vue'
// 引入App组件,是所有组件的父组件
import App from './App.vue'

// 关闭Vue的生产环境提示
Vue.config.productionTip = false

// 创建Vue实例对象
new Vue({
// 将App组件放入容器中
render: h => h(App),
}).$mount('#app') // 绑定容器

3、public文件夹:页面的根目录,存放了index.html和ico图标

应该知道:main.js之所以是入口文件,而且它能找到public中的index.html去绑定容器,是脚手架配置、规定的

render函数

在 main.js 中,render: h => h(App) 作用是将App组件放入容器中

若使用之前的模板写法,控制台会报错

模板写法
1
2
3
4
5
6
7
8
9
import App from "./App.vue" // 引入App组件
new Vue({
el: '#root',
template: '<App></App>',
components: {
App
}
})

报错内容: [vue warn]: You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build.
意思是:正在使用Vue的仅运行时版本(runtime模式),其中模板编译器不可用。将模板预编译为render函数,或者使用包含编译器的内部版本。

问题原因:
Vue包含两个部分,核心部分模板解析器,核心部分是生命周期与各种属性与函数,模板解析器用于解析模板,当通过cdn引入来使用Vue时,应该将两者都引入,但如果使用脚手架、webpack将.vue文件都翻译为.js文件,且模板都已经解析为html,模板解析器在生产环境就没有用了

因为Vue中不是所有部分都在生产环境中用到,且模板解析器占Vue体积的三分之一,所以Vue除了完整版,还有许多精简版,带模板解析器的称为 compiler(模板)模式,反之称为 runtime(运行时)模式

(1) vue.js 是完整版Vue,包含:核心功能+模板解析器
(2) vue.runtime.xxx.js 是运行版Vue,只包含核心功能,没有模板解析器

通过 import Vue from 'vue' 引入的就是不带模板解析器的精简版,vue模块的package.json的main/model字段默认为runtime模式,指向了”dist/vue.runtime.common.js”。

解决办法一:引入完整版Vue,不推荐

1
import Vue from 'vue/dist/vue.js'

解决办法二:使用渲染函数 render() 代替模板写法

render 配置项是一个函数,传入 createElement 参数也是一个函数

createElement() 可以创建具体的元素,可以传入一个组件或是 ('标签名','标签内容')的形式 ,返回创建好的元素

Vue会调用 render() 并接收其返回值,将 createElement() 的返回值(创建好的元素)返回即可

1
2
3
4
5
6
// 完整写法
render(createElement) {
return createElement('h1', '你好啊')
}
// 箭头函数简写
render: h => h(App)

注意:在开发环境中有 vue-cli 自带有 vue-template-compiler 插件,能解析 .vue 文件中的 <template></template> 模板,但写在配置对象 template 属性中的模板没有插件能解析,所以要使用 render()

以后一般也只有在创建vm时配置项里会用到render

自定义脚手架配置

脚手架默认使用main.js作为入口文件等默认配置都在一个文件中,该文件被隐藏了起来

使用命令导出、查看脚手架配置文件的拷贝

1
vue inspect > output.js

vue-cli配置参考项中查看可配置项

vue.config.js 文件中进行自定义配置

1
2
3
4
5
// vue.config.js
const { defineConfig } = require('@vue/cli-service')
module.exports = defineConfig({
// 配置选项
})

ref标签属性

替代 id 属性给元素或子组件注册引用信息(打标识)

元素标签组件标签添加 ref 属性,就能在组件实例对象的 $refs 上获取dom元素子组件实例对象

1
2
3
4
5
6
7
<!-- 打标识 -->
<h1 v-text="msg" ref="xxx"></h1>
<School ref="xxx"></School>
<!-- 获取dom元素或子组件vc -->
<script>
this.$refs.xxx
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
<template>
<div>
<h1 v-text="msg" ref="title"></h1>
<button @click="showTitle">显示/隐藏标题</button>
<School></School>
</div>
</template>

<script>
import School from "./components/school.vue";

export default {
name: "App",
components: {
School,
},
data() {
return {
msg: "学校信息",
};
},
methods: {
showTitle() {
this.$refs.title.classList.toggle('hide');
},
},
};
</script>

<style>
.hide {
opacity: 0;
}
</style>

props配置项

子组件的 props 配置项接收父组件通过组件标签传入的数据

作用:实现父组件与子组件的通信

通过标签属性给子组件传数据

注意:

  1. 普通属性传的是字符串,要传入其它数据类型的属性,需要 v-bind 绑定属性,传入表达式的值
  2. 传入引用数据类型时,传的是引用,浅拷贝
1
<Student name="chuckle" sex="男" :age="18"></Student>

子组件接收数据,三种写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
// 简单接收,不对数据类型进行限制
props: ['name', 'age', 'sex']
// 接收同时限制数据类型
props: {
name: String,
age: Number,
sex: String
}
// 更多配置,必须的、默认值等
props: {
name: {
type: String,
required: true // 必须的
},
age: {
type: Number,
required: true // 必须的
},
sex: {
type: String,
default: "男"
}
}

props 接收到的数据会代理到 vc 身上,但不允许修改只能读取(直接修改也有效果,但控制台会发出警告),所以也不能使用 v-model 绑定

若需修改,应先将数据拷贝到data中,用一个新属性接收

1
2
3
4
5
data() {
return {
myAge: this.age + 1
};
},

mixins混入

多个相似组件中通常会有重复的配置项,可以将这些配置项提取成一个混入对象,给这些组件引入复用(混入)

将相同的配置项提取至 mixin.js

mixin.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
export const mixin1 = {
data(){
return {
x: 100,
y: 200
}
}
}
export const mixin2 = {
data() {
return {
name: '',
}
},
methods: {
showName(){
console.log(this.name);
}
},
}

组件通过 mixins 配置项引入 mixin.js 中的配置

Vue会将这些外部的配置混入组件的同名配置中(混合合并),配置中重复的属性保留组件中的

mixins: [] 局部混入

局部组件混入
1
2
3
4
5
6
// 引入混入对象文件
import {mixin1, mixin2} from '../mixin.js';
export default {
// 局部混入
mixins: [mixin1,mixin2],
};

Vue.mixin() 全局混入

在main.js中全局混入,给所有组件
1
2
3
import {mixin1, mixin2} from '../mixin.js';
Vue.mixin(mixin1)
Vue.mixin(mixin2)

插件

Vue中插件本质是一个对象,对象中必须有一个 install() 方法

plugins.js 或其它名字的独立js文件中定义插件

1
2
3
4
5
export default {
install(){
console.log('这是一个插件');
}
}

main.js 中导入并使用 Vue.use() 应用插件

1
2
3
4
// 导入插件
import plugins from "./plugins";
// 使用插件
Vue.use(plugins);

插件对象的 install() 方法默认第一个参数接收 Vue构造函数 作为参数,在插件中可以进行各种全局配置以及在原型上添加属性和方法

plugins.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
import {mixin1, mixin2} from './mixin.js';
export default {
// 第一个参数接收Vue构造函数作为参数
install(Vue){
// 配置全局过滤器
Vue.filter('interceptStr',(value, num=4)=>{
return value.slice(0,num)
})

// 注册全局自定义指令
Vue.directive('inHtml', function(el, binding){
el.innerHTML = binding.value
})

// 应用全局混入
Vue.mixin(mixin1)
Vue.mixin(mixin2)

// 在Vue原型上添加属性和方法
Vue.prototype.hello = function(){
console.log('Hello')
}

}
}

自定义参数:
Vue.use() 使用插件时也可以传入其它参数,会被 install() 方法接收,第一个参数仍然是 Vue构造函数

1
2
3
4
5
// 传入三个自定义参数,三个数字
Vue.use(plugins,1,2,3);
install(Vue,a,b,c){
console.log(a,b,c);// 1 2 3
}

scoped样式

多个组件有多个 style 标签,所有组件样式都会汇总到一个 CSS 文件中

当组件中有相同类名时,样式就会冲突,可以给组件的 style 标签加上 scoped 属性解决冲突

作用:让样式仅在当前组件中生效,防止样式冲突

原理:当style标签加上 scoped 属性后,Vue会给该组件所有标签元素都加上一个随机的 data-v 属性,css选择器也会自动选择 data-v

1
2
3
4
5
6
<div data-v-22321ebb="" class="demo">
<h2 data-v-22321ebb="">学生姓名:chuckle</h2>
<h2 data-v-22321ebb="">学生性别:男</h2>
<h2 data-v-22321ebb="">学生年龄:19</h2>
<hr data-v-22321ebb="">
</div>
1
2
3
.demo[data-v-22321ebb] {
background: rgb(78, 180, 220);
}

注意:一般在 App.vue 的 style 标签中写全局共用样式,所以 App 不适合加 scoped

更多: style 标签的 lang 属性可以指定 CSS 预处理语言,常用 less,使用 less 前需要安装 less-loader 用于解析 less

1
2
<style lang="less" scoped>
</style>