【笔记】Vue脚手架工具

前言

Vue脚手架工具vue-cli学习笔记

安装脚手架工具

1
npm install -g @vue/cli

查看版本号

  • 查看版本号验证是否安装成功
1
vue --version

创建一个项目

<name>:项目名

1
2
vue create <name>
cd <name>

基本命令

运行项目

  • 编译和热更新
1
npm run serve

构建项目

  • 进行打包
1
npm run build

验证项目

  • 对eslint校验可靠性
1
npm run lint

项目结构

···

  • node_modules
  • public
  • src 项目源码
    • assets
    • components
    • views
    • App.vue
    • main.js
  • .gitignore
  • babel.config.js
  • package.json
  • package-lock.json
  • README.md
    ···

vue组件

vue组件结构

  • 所有的vue组建都是.vue结尾的文件
  • App.vue是所有组件的根组件

template:结构
script:逻辑
style:样式

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>

</template>

<script>
export default {
name: ""
}
</script>

<style scoped>

</style>

渲染数据

  • 最外层必须有默认暴露,vue的对象清单都必须在export default里面去罗列
  • 在vue组件中,为了防止javascript数据污染,data不可以是对象,而是一个函数返回一个对象
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div id="app">
{{num}}
</div>
</template>

<script>
export default {
data: function() {
return {
num: 100
}
}
}
</script>

<style scoped>

</style>

引入组件

  1. 引入组件
  2. 注册组件
  3. 调用组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<template>
<div>
<!-- 3、调用组建 -->
<Hello/>
</div>
</template>

<script>
// 1、引入组件
import Hello from "./components/Hello";

export default {
// 2、注册组件
components: {
Hello
}
}
</script>

<style scoped>

</style>

定义自定义函数

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
<template>
<div>
<h1>{{num}}</h1>
<button v-on:click="add">+</button>
</div>
</template>

<script>
export default {
name: "Hello",
data: function() {
return {
num: 0
}
},
methods: {
add() {
this.num++;
}
}
}
</script>

<style scoped>

</style>

native修饰器

  • 原生的事件监听在vue组件中不生效,需要在原生事件监听后添加后缀.native来使原生事件监听生效
Father.vue
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
<template>
<div>
<Son @click.native="click"></Son>
</div>
</template>

<script>
import Son from "./Son";

export default {
name: "Father",
components: {
Son
},
methods: {
click() {
console.log("事件监听");
}
}
}
</script>

<style scoped>

</style>
Son.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<button>+</button>
<Grandson></Grandson>
</div>
</template>

<script>
import Grandson from "./Grandson";

export default {
name: "Son",
components: {
Grandson
}
}
</script>

<style scoped>

</style>

父子组件传值

  • 父组件通过v-bind:自定义属性传值
  • 如果父组件传值需要用驼峰命名,需要使用-来代替,子组件接收时使用驼峰命名接收
  • 子组件通过props接收对应的参数,并在双大括号内直接通过自定义参数名调用
  • 子组件接收的可以是数组,也可以是对象

父组件传递给子组件值

父组件传值
App.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
<div>
<Hello v-bind:value-a="num"></Hello>
</div>
</template>

<script>
import Hello from "./components/Hello";

export default {
components: {
Hello
},
data: function() {
return {
num: 100
}
}
}
</script>

<style scoped>

</style>
子组件接收为数组
  • 如果接收为数组,不需要指定接收的数据的类型
Hello.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div>
<h1>父组件传递过来的值是{{valueA}}</h1>
</div>
</template>

<script>
export default {
name: "Hello",
props: ["valueA"]
}
</script>

<style scoped>

</style>
子组件接收为数对象
  • 如果接收为对象,可以限制接收类型
Hello.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>
<h1>父组件传递过来的值是{{valueA}}</h1>
</div>
</template>

<script>
export default {
name: "Hello",
props: {
valueA: Number
}
}
</script>

<style scoped>

</style>
配置参数为必传项

type:定义类型
require:true开启必传值校验,如果未接收到传值,控制台会报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h1>父组件传递过来的值是{{valueA}}</h1>
</div>
</template>

<script>
export default {
name: "Hello",
props: {
valueA: {
type: Number,
require: true
}
}
}
</script>

<style scoped>

</style>
配置参数默认值
  • 如果默认值是一个对象或数组,需要以函数和返回值的形式定义

defaule:接收不到传值的默认值。一般不和require混用

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
<template>
<div>
<h1>父组件传递过来的值(默认值)是{{valueA.num}}</h1>
</div>
</template>

<script>
export default {
name: "Hello",
props: {
valueA: {
type: Object,
default: function() {
return {
num: 100
}
}
}
}
}
</script>

<style scoped>

</style>
配置参数校验

validator:传值的手动校验,如果校验结果为false,则会在控制台报错

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
<div>
<h1>父组件传递过来的值是{{valueA}}</h1>
</div>
</template>

<script>
export default {
name: "Hello",
props: {
valueA: {
type: Number,
validator: function(value) {
return value>50
}
}
}
}
</script>

<style scoped>

</style>

子组件修改父组件值

  • 子组件不可以直接修改父组件的值
  • 子组件通过触发事件,调用this.$emit("自定义事件名"),向父组件传递事件被触发
  • 父组件通过接收到子组件被触发,从而触发自己的事件,来激活自己的函数
子组件向父组件传递事件触发
Hello.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div>
<button v-on:click="add">+</button>
</div>
</template>

<script>
export default {
name: "Hello",
methods: {
add() {
this.$emit("a");
}
}
}
</script>

<style scoped>

</style>
父组件接收到子组件事件被触发
  • 父组件接收到子组件被触发,从而触发自己的事件
App.vue
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>
<h1>{{num}}</h1>
<Hello v-on:a="add"></Hello>
</div>
</template>

<script>
import Hello from "./components/Hello";

export default {
components: {
Hello
},
data: function() {
return {
num: 0
}
},
methods: {
add() {
this.num++;
}
}
}
</script>

<style scoped>

</style>

watch监听数据变化

非对象数据

  • 通过watch对象中对应的以数据名命名的函数,得到新数据和旧数据,实现监听数据

newVal:新数据
oldVal:旧数据

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
<template>
<div>
<h1>{{num}}</h1>
<button v-on:click="add">+</button>
</div>
</template>

<script>

export default {
data: function() {
return {
num: 0
}
},
methods: {
add() {
this.num++;
}
},
watch: {
num: function(newVal, oldVal) {
console.log(newVal);
console.log(oldVal);
}
}
}
</script>

<style scoped>

</style>

对象数据(某个属性)

  • 复杂类型只支持监听某个属性值
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
<template>
<div>
<h1>{{obj.age}}</h1>
<button v-on:click="add">+</button>
</div>
</template>

<script>
// import Hello from "./components/Hello";

export default {
// components: {
// Hello
// },
data: function() {
return {
obj: {
age: 16
}
}
},
methods: {
add() {
this.obj.age++;
}
},
watch: {
"obj.age": function(newVal, oldVal) {
console.log(newVal);
console.log(oldVal);
}
}
}
</script>

<style scoped>

</style>

对象数据(整个对象)

  • 如果需要页面初始化就能触发一次监听,必须使用handler函数
  • 监听复杂数据只能在页面初始化监听一次

immediate:true表示开启初始化时监听
handler:监听函数

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
<template>
<div>
<h1>{{obj.age}}</h1>
<button v-on:click="add">+</button>
</div>
</template>

<script>

export default {
data: function() {
return {
obj: {
age: 16
}
}
},
methods: {
add() {
this.obj.age++;
}
},
watch: {
"obj": {
handler(val) {
console.log(val);
},
immediate: true
}
}
}
</script>

<style scoped>

</style>

计算属性

  • 计算属性(computed)和普通函数(methods)的区别:计算属性利用缓存,如果要重复渲染相同的函数,不会重复渲染

字符串反转

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
<template>
<div>
<h1>{{reverseStr}}</h1>
</div>
</template>

<script>

export default {
data: function() {
return {
str: "Hello"
}
},
computed: {
reverseStr() {
return this.str.split("").reverse().join("");
}
}
}
</script>

<style scoped>

</style>

实例属性

$attrs

  • $attrs可以从父组件接收到非props接收到的值
  • $attrs可以多级子孙传递
  • 如果父组件和子组件都传递给孙子组件相同的$attrs,那么子组件会覆盖父组件的$attrs
Father.vue
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
<template>
<div>
<Son :name="name" :age="age" :sex="sex"></Son>
</div>
</template>

<script>
import Son from "./Son";

export default {
name: "Father",
components: {
Son
},
data: function() {
return {
name: "张三",
age: 50,
sex: "男"
}
}
}
</script>

<style scoped>

</style>
Son.vue
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
<template>
<div>
<Grandson v-bind="$attrs" :age="age"></Grandson>
</div>
</template>

<script>
import Grandson from "./Grandson";

export default {
name: "Son",
components: {
Grandson
},
data: function() {
return {
age: 25
}
}
}
</script>

<style scoped>

</style>
Grandson.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>

</div>
</template>

<script>
export default {
name: "Grandson",
created() {
console.log(this.$attrs)
}
}
</script>

<style scoped>

</style>

$listeners

  • $linteners可以从父组件接收到非native修饰器接收到的事件监听
  • $linteners也可以多级子孙传递
Father.vue
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
<template>
<div>
<Son @cli="cli"></Son>
</div>
</template>

<script>
import Son from "./Son";

export default {
name: "Father",
components: {
Son
},
methods: {
cli() {
console.log("事件监听");
}
}
}
</script>

<style scoped>

</style>
Son.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<button>+</button>
<Grandson v-on="$listeners"></Grandson>
</div>
</template>

<script>
import Grandson from "./Grandson";

export default {
name: "Son",
components: {
Grandson
}
}
</script>

<style scoped>

</style>
Grandson.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<template>
<div>

</div>
</template>

<script>
export default {
name: "Grandson",
created() {
console.log(this.$listeners);
}
}
</script>

<style scoped>

</style>

$refs

  • $refs包含了当前组件的所有DOM和函数
  • 先在子组件上定义ref属性,再通过$refs调用子组件的函数
  • 如果ref对象不是一个自定义组件而是一个普通元素,返回的就是该元素本身
Father.vue
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
<template>
<div>
<Son ref="child"></Son>
<button @click="click">+</button>
</div>
</template>

<script>
import Son from "./Son";

export default {
name: "Father",
components: {
Son
},
methods: {
click() {
this.$refs.child.add();
}
}
}
</script>

<style scoped>

</style>
Son.vue
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
<template>
<div>
<h1>{{num}}</h1>
</div>
</template>

<script>

export default {
name: "Son",
data: function() {
return {
num: 100
}
},
methods: {
add() {
this.num++;
}
}
}
</script>

<style scoped>

</style>

$el

  • 通过ref获取子组件,再通过el获取子组件的根节点,从而实现css的修改
Father.vue
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
<template>
<div>
<Son ref="child"></Son>
<button @click="click">+</button>
</div>
</template>

<script>
import Son from "./Son";

export default {
name: "Father",
components: {
Son
},
methods: {
click() {
this.$refs.child.$el.style="color: red";
}
}
}
</script>

<style scoped>

</style>
Son.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
<div>
<h1>{{num}}</h1>
</div>
</template>

<script>

export default {
name: "Son",
data: function() {
return {
num: 100
}
}
}
</script>

<style scoped>

</style>

混入

  • 把共性的js抽离出来,在需要调用的组件中引入
  • 如果组件中的函数和js中的函数重名,组建中的函入会覆盖js中的函数
  • 如果组件中和js中都有created函数,会先执行js中的created,后执行组件中的created,不会覆盖
a.js
1
2
3
4
5
6
7
8
9
10
11
12
export const a = {
data() {
return {
num: 0
}
},
methods: {
add() {
this.num++;
}
}
}
Father.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<h1>{{num}}</h1>
<button @click="add">+</button>
</div>
</template>

<script>
import {a} from "../a.js"

export default {
name: "Father",
mixins: [a]
}
</script>

<style scoped>

</style>

完成

参考文献

哔哩哔哩——Python小清风