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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
1、下载 node.js 安装

2、检测node.js 是否安装成功
node -v npm -v

3、
# 设置npm全局安装包保存路径
npm config set prefix "D:\nodejs\node_global"
# 设置npm装包缓存路径
npm config set cache "D:\nodejs\node_cache"


# 查看npm全局安装包保存路径
npm config get prefix
# 查看npm装包缓存路径
npm config get cache


# 查看全局安装目录:
npm list -global

# 在node.js 安装路径下 创建 node_global 和 node_cache
# 以上操作表示,修改全局包下载目录为D:\node\node_global,缓存目录为D:\node\node_cache,并会自动创建node_global目录,而node_cache目录是缓存目录,会在你下载全局包时自动创建


4、设置环境变量
【系统变量】新建NODE_PATH D:\nodejs\node_global\node_modules
【系统变量】Path %NODE_PATH%
【系统变量】Path D:\nodejs

【用户变量】Path D:\nodejs\node_global
# 删除【用户变量】 Path C:\Users\用户名\AppData\Roaming\npm


5、加速
# 查看npm下载源
npm config get registry
# 安装cnpm
npm install -g cnpm --registry=https://registry.npm.taobao.org (使用国内阿里云镜像文件地址 https://registry.npmmirror.com/ )

# 查看npm下载源
cnpm config get registry
cnpm config list

6、安装vue
cnpm install vue -g

cnpm install vue -g

#查看安装的vue信息
cnpm info vue
或者
cnpm info vue

#查看安装的vue版本
cnpm list vue
如果 出现 enpty 命令后面加 -g
cnpm list vue -g


7.1、安装全局vue-cli脚手架2.0
cnpm install vue-cli -g


7.2、安装全局vue-cli脚手架3.0
cnpm install @vue/cli -g

# 卸载2.x版本
cnpm uninstall vue-cli -g
# 卸载3.x版本
cnpm uninstall @vue/cli -g


8、后续升级手脚架
cnpm update -g @vue/cli


9.安装webpack
cnpm install webpack -g (全局安装)
cnpm install webpack --save-dev (局部安装)
# webpack 4x以上,webpack将命令相关的内容都放到了webpack-cli,所以还需要安装webpack-cli:
cnpm install --global webpack-cli
# 查看版本号
webpack -v


10.1、vue-cli2创建vue项目
vue init webpack 项目名

10.2 、vue-cli3创建vue项目
vue create 项目名











# 全局安装
cnpm install -g yarn

# 全局安装目录
yarn config set global-folder D:\Yarn\yarn_global

# 缓存目录
yarn config set cache-folder D:\Yarn\yarn_cache

# 查看当前源
yarn config get registry

# 修改为淘宝镜像源
yarn config set registry https://registry.npm.taobao.org

npm命令

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
# 查看当前版本
npm -v

# 更新到最新版本
npm install -g npm

# 更新到指定版本
npm -g install npm@6.8.0

# 清理 npm 缓存数据
npm cache clean --force

# 查看全局安装目录:
npm list -global
# 查看vue版本
npm list vue




# 查看当前的版本信息
npm updated -d
# 查看模块的所有版本
npm view npm versions




安装 卸载

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# npm 安装时 --save --dev 和 --save 区别
--save:将保存配置信息到pacjage.json的dependencies节点中。
--save-dev:将保存配置信息到pacjage.json的devDependencies节点中。
dependencies:运行时的依赖,发布后,即生产环境下还需要用的模块
devDependencies:开发时的依赖。里面的模块是开发时用的,发布时用不到它。



1. 安装jquery
cnpm install jquery --save
卸载jquery
cnpm uninstall jquery --save


2. 安装swiper
cnpm install swiper --save-dev
卸载swiper
cnpm uninstall swiper --save-dev

# 有的时候npm 无法使用 要用cnpm
cnpm uninstall swiper

安装swiper

1
2
# 安装swiper
cnpm install swiper@5.4.5

安装colorthief

1
2
# 安装colorthief
yarn add colorthief

安装wangEditor

1
2
3
4
5
6
7
8
9
10
yarn add @wangeditor/editor
# 或者
npm install @wangeditor/editor --save


yarn add @wangeditor/editor-for-vue (使用这个必须引入上面那个)
# 或者
npm install @wangeditor/editor-for-vue --save

import "@wangeditor/editor/dist/css/style.css"

vue升级

1
vue-template-compiler 和 vue 要保持版本一致

方法

1
2
3
4
5
6
7
8
//大写
.toUpperCase()





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
<body>
<div id="root">
<h1>Hello {{name}} 地址: {{address}}</h1>
<h2>{{user.age}}</h2>
<h2>{{user.height}}</h2>
</div>
</body>

<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。
// 创建 Vue实列
new Vue({
el:'#root',// el 用于指定Vue实列为那个容器服务
data:{ //data 中用于存储的数据, 数据提供el指定的容器去使用
name: 'zkc',
address:'北京',
user:{
age:18,
height:178
}
}
})
// 容器 和 实列只能 1对1 的关系
</script>

指令语法(v-bind )

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<div id="root">
<h1>插值语法</h1>
<h3>你好{{name}}</h3>
<hr/>
<a v-bind:href="url" :title="name">百度</a>// v-bind: 或者 : 都可以
</div>
</body>

<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。

// 创建 Vue实列
new Vue({
el:'#root',// el 用于指定Vue实列为那个容器服务
data:{ //data 中用于存储的数据, 数据提供el指定的容器去使用
name: 'zkc',
url:'https://www.baidu.com'
}
})
</script>

v-bind、v-model(数据绑定)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
<body>
<div id="root">
单项数据绑定:<input type="text" v-bind:value="name"><br/>

双项数据绑定:<input type="text" v-model:value="name">
<!--
v-model 只能用在表单类元素上
-->
</div>
</body>

<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。

new Vue ({
el:'#root',
data:{
name:'zkc'
}
})
</script>
</html>

v-text

1
<h1 v-text="time"></h1>  # 向起所在节点渲染文本内容

v-html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>

<div id="root">
<h1 v-html="time"></h1> <!-- 支持标签渲染 -->
</div>

</body>
<script type="text/javascript">
Vue.config.productionTip = false
//全局过滤器
Vue.filter('mySlice',function (value){
return value.slice(0,4)
})

new Vue({
el: '#root',
data: {
time: '<h1>zkc</h1>'
}
})
</script>

v-show

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<h2 v-show="false">zkc</h2>   // 直接隐藏  
或者
<body>
<div id="root">
<h2 v-show="a">zkc{{name}}</h2>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el:'#root',
data:{
a:false,
name:'你好!'
}
})
</script>



v-if 、v-else-if、v-else

1
2
3
4
5
6
7
<h2 v-if="false">zkc</h2>   // 直接删除DOM


<div v-if="n === 1">1</div>
<div v-else-if="n === 2">2</div>
<div v-else-if="n === 3">3</div>
<div v-else>哈哈</div>

v-for

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
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
persons: [
{id: '001', name: '张三', age: '18'},
{id: '002', name: '李四', age: '19'},
{id: '003', name: '王五', age: '20'}
],
car:{
name:'1',
price:'2',
color:'3'
}
}
})
</script>


遍历数组
<li v-for="item in persons" :key="item.id">{{item.name}} - {{item.age}}</li>
<li v-for="(item,index) in persons" :key="item.id">{{item.name}} - {{item.age}}</li> // index 坐标
或者
<li v-for="(a,b,c) in persons">{{a}} - {{b}} - {{c}}</li>
遍历对象
<ul>
<li v-for="(value,k) in car" :key="k">{{k}} - {{value}}</li>
</ul>

v-on

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<div id="root">
<h1>{{name}}</h1>
<button v-on:click="showInfo1">点我(不传参)</button>
<button @click="showInfo2($event,66)">点我(传参)</button>
</div>
</body>
<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。
const v = new Vue ({
el:'#root',
data:{ // 第一种写法
name:'zkc'
},
methods:{
showInfo1(event){
alert("你好1")
},
showInfo2(event,number){
console.log(event,number)
alert("你好2")
}
}
})
</script>

v-cloak

1
2
3
v-cloak没有属性

v-cloak 在Vue实例创建完毕接管容器后,会删除掉v-cloak属性,在这之前可以用css隐藏掉页面中展示的{{xxx}} 的问题

v-once

1
2
v-once没有属性
v-once所在节点初次动态选然后,就变成静态内容,不会在随元数据改变而改变了

v-pre

1
2
3
v-pre没有属性

跳过编译过程,直接显示在界面中(代码是什么,就显示在页面中)

自定义指令-函数式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body>
<div id="root">
<h1 v-big="time"></h1>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//全局过滤器
Vue.filter('mySlice',function (value){
return value.slice(0,4)
})
new Vue({
el: '#root',
data: {
time: 10
},
directives:{
big:function (element,binding){
element.innerText = binding.value *10
}
}
})
</script>

自定义指令-对象式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<body>
<div id="root">
<h1 v-big="time"></h1>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false
//全局过滤器
Vue.filter('mySlice',function (value){
return value.slice(0,4)
})
new Vue({
el: '#root',
data: {
time: 10
},
directives:{
big(element,binding){
element.innerText = binding.value *10
}
}
})
</script>

el两种写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<div id="root">
<h1>{{name}}</h1>
</div>
</body>

<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。

const v = new Vue ({
//el:'#root', // 第一种写法
data:{
name:'zkc'
}
})
v.$mount('#root') // 第二种写法
</script>

data两种写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<div id="root">
<h1>{{name}}</h1>
</div>
</body>

<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。
const v = new Vue ({
el:'#root',
// data:{ // 第一种写法
// name:'zkc'
// }
data:function (){ // 第二种写法 不能写成 data:()=> ,一旦携程箭头函数 , this就不再是Vue实列,而是windows
return{
name:'zkc1'
}
}
})
</script>

MVVM模型

image-20211103135632758

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// data 中的所有数据 都出现在了 vm 身上
// vm 的所有属性 及 Vue原型属性 都可以在Vue模板中使用

<body>
<div id="root">
<h1>名称{{name}}</h1>
<h1>地址{{address}}</h1>
</div>
</body>

<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。

const v = new Vue ({
el:'#root',
data:{
name:'zkc'
,address:'北京'
}
})
</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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
<body>
<!--
事件修饰符
pervent 阻止默认事件
stop 阻止事件冒泡
once 事件只触发一次
capture 使用事件的捕获模式
self 只有event.target是当前操作的元素时才能触发事件
passive 事件的默认行为立即执行,无需等待事件回调执行完毕
-->
<div id="root">
<h1>{{name}}</h1>
<a href="https://www.baidu.com" @click.prevent="showInfo1">点击</a> <!--阻止默认事件-->

<hr/>
<div @click="showInfo1">
<button @click.stop="showInfo1">点击</button> <!--阻止事件冒泡-->
</div>

<hr/>
<button @click.once="showInfo1">点击</button> <!--事件只触发一次-->

<hr/>
<div @click.capture="showMsg(1)"> <!--使用事件的捕获模式-->
div1
<div @click="showMsg(2)">
div2
</div>
</div>

<hr/>
<div @click.self="showInfo1"> <!--只有event.target是当前操作的元素时才能触发事件-->
<button @click="showInfo1">点击</button>
</div>
</div>
</body>

<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。
const v = new Vue ({
el:'#root',
data:{ // 第一种写法
name:'zkc'
},
methods:{
showInfo1(event){
console.log(event.target)
alert("你好1")
},
showMsg(msg){
console.log(msg)
}
}
})
</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
36
37
38
<body>
<!--

@kkeydown - 键按下的过程

@kkeypress - 键被按下

@keyup - 键被松开
@keyup.enter 回车按键松开
@keyup.left 左键按键松开
@keyup.right 右键按键松开
@keyup.up 上键按键松开
@keyup.down 下键按键松开
@keyup.delete 删除键松开
@keyup.esc 退出键松开
@keyup.space 空格键松开
@keyup.tab 换行键松开
-->
<div id="root">
<input type="text" placeholder="按下回车" @keyup.enter="showInfo"/>
</div>
</body>
<script>
Vue.config.productionTip = false //设置为 false 以阻止 vue 在启动时生成生产提示。
const v = new Vue ({
el:'#root',
data:{ // 第一种写法
name:'zkc'
},
methods:{
showInfo(event){
//console.log(event.key,event.keyCode)
//if(event.keyCode !== 13) return
console.log(event.target.value)
}
}
})
</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
36
37
38
39
40
41
42
43
44
<body>

<div id="root">
姓:<input type="text" v-model:value="firstName"/><br/>
名:<input type="text" v-model="lastName"/><br/>
姓名:<span>{{fullName}}</span>
</div>

</body>

<script type="text/javascript">
Vue.config.productionTip = false

new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三'
},
computed:{
fullName: {
// 被调用时执行,返回值为 fullName的值
get(){
console.log('get调用了')
return this.firstName + '-' + this.lastName
},
// fullName 被修改时调用
set(value){
console.log('set',value)
const arr = value.split('-')
this.firstName =arr[0]
this.lastName =arr[1]
}
}
}
// 可简写为
// computed:{
// fullName(){
// console.log('get调用了')
// return this.firstName + '-' + this.lastName
// }
// }
})
</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
36
37
38
39
40
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>
</body>

<script type="text/javascript">
Vue.config.productionTip = false
const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
// watch:{ // 方法一
// isHot:{
// immediate:true, //初始化的时候让handler调用一下
// handler(newValue,oldValue){ // hander什么时候调用?什么时候改变
// console.log('isHot被修改了',newValue,oldValue)
// }
// }
// }
})
vm.$watch('isHot',{ //方法二
immediate:true, //初始化的时候让handler调用一下
handler(newValue,oldValue){ // hander什么时候调用?什么时候改变
console.log('isHot被修改了',newValue,oldValue)
}
})
</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
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
<body>

<div id="root">

<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
<hr/>

<h3>{{numbers.a}}</h3>
<button @click="numbers.a++">点击+1</button>

<h3>{{numbers.b}}</h3>
<button @click="numbers.b++">点击+1</button>
</div>

</body>

<script type="text/javascript">
Vue.config.productionTip = false

const vm = new Vue({
el:'#root',
data:{
isHot:true,
numbers:{
a:1,
b:2
}
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{ // 默认不检测 numbers 内部值的改变 配置deep:true 可以检测多层
isHot:{
immediate:true, //初始化的时候让handler调用一下
handler(newValue,oldValue){ // hander什么时候调用?什么时候改变
console.log('isHot被修改了',newValue,oldValue)
}
},
// 'numbers.a':{
// handler() {
// console.log('a改变了')
// }
// }

numbers:{ // 监视多级结构中所有属性的变化
deep:true,
handler(newValue, oldValue) {
console.log('numbers改变了')
}
}

}
})
</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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
<body>
<div id="root">
<h2>今天天气很{{info}}</h2>
<button @click="changeWeather">切换天气</button>
</div>

</body>

<script type="text/javascript">
Vue.config.productionTip = false

const vm = new Vue({
el:'#root',
data:{
isHot:true
},
computed:{
info(){
return this.isHot ? '炎热' : '凉爽'
}
},
methods:{
changeWeather(){
this.isHot = !this.isHot
}
},
watch:{ // 默认不检测 numbers 内部值的改变 配置deep:true 可以检测多层

// isHot:{
// // immediate:true, //初始化的时候让handler调用一下
// // deep:true, //深度监视
// handler(newValue,oldValue){ // hander什么时候调用?什么时候改变
// console.log('isHot被修改了',newValue,oldValue)
// }
// }

// 简写
// isHot(newValue,oldValue){
// console.log('isHot被修改了',newValue,oldValue)
// }

}
})


// vm.$watch('isHot',{
// immediate:true, //初始化的时候让handler调用一下
// handler(newValue,oldValue){ // hander什么时候调用?什么时候改变
// console.log('isHot被修改了',newValue,oldValue)
// }
// })

// 简写
vm.$watch('isHot',function (newValue,oldValue){
console.log('isHot被修改了',newValue,oldValue)
})

</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
<body>

<div id="root">
姓:<input type="text" v-model:value="firstName"/><br/>
名:<input type="text" v-model="lastName"/><br/>
姓名:<span>{{fullName}}</span>
</div>

</body>

<script type="text/javascript">
Vue.config.productionTip = false

new Vue({
el:'#root',
data:{
firstName:'张',
lastName:'三',
fullName:'张-三'
},
watch:{
firstName(val){
setTimeout(() =>{
this.fullName = val + '-' + this.lastName
},1000)
},
lastName(val){
this.fullName = this.firstName + '-' + val
},

}
})
</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
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
<body>

<div id="root">
<input type="text" placeholder="请输入" v-model="keyWord"/>
<ul>
<li v-for="(item,index) in filPerons" :key="index">{{item.name}} - {{item.age}} - {{item.sex}}</li>
</ul>
</div>

</body>


<!--watch 实现
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyWord:'',
persons: [
{id: '001', name: '张三', age: '18',sex:'女'},
{id: '002', name: '李四', age: '19',sex:'男'},
{id: '003', name: '王五', age: '20',sex:'女'},
{id: '004', name: '王五', age: '21',sex:'女'},
{id: '005', name: '王五', age: '22',sex:'女'},
{id: '006', name: '王五', age: '23',sex:'女'}
],
filPerons:[]
},
watch:{
keyWord:{
immediate:true,
handler(val){
this.filPerons = this.persons.filter((p)=>{
return p.name.indexOf(val) !== -1
})
}
}
}
})
</script>-->

<!--computed 实现-->
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyWord:'',
sortType:0, //0 原顺序 1 降序 2 升序
persons: [
{id: '001', name: '张三', age: '30',sex:'女'},
{id: '002', name: '李四', age: '19',sex:'男'},
{id: '003', name: '王五', age: '20',sex:'女'},
{id: '004', name: '王五', age: '5',sex:'女'},
{id: '005', name: '王五', age: '29',sex:'女'},
{id: '006', name: '王五', age: '23',sex:'女'}
]
},
computed:{
filPerons(){
return this.filPerons = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
}
}
})
</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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<body>

<div id="root">
<input type="text" placeholder="请输入" v-model="keyWord"/>
<button @click="sortType = 2">年龄升序</button>
<button @click="sortType = 1">年龄降序</button>
<button @click="sortType = 0">原顺序</button>
<ul>
<li v-for="(item,index) in filPerons" :key="index">{{item.name}} - {{item.age}} - {{item.sex}}</li>
</ul>
</div>

</body>


<!--computed 实现-->
<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
keyWord:'',
sortType:0, //0 原顺序 1 降序 2 升序
persons: [
{id: '001', name: '张三', age: '30',sex:'女'},
{id: '002', name: '李四', age: '19',sex:'男'},
{id: '003', name: '王五', age: '20',sex:'女'},
{id: '004', name: '王五', age: '5',sex:'女'},
{id: '005', name: '王五', age: '29',sex:'女'},
{id: '006', name: '王五', age: '23',sex:'女'}
]
},
computed:{
filPerons(){

const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})


if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr

}
}
})
</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
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
<body>

<!--
v-model.trim 自动过滤掉输入框的首尾空格。
v-model.number 输入框输入的内容,即使是数字,默认也是 string 类型,.number时让其转换为 number 类型
v-model.lazy 失去焦点后接受数据
-->

<div id="root">
<form @submit.prevent="demo">
账号: <input type="text" v-model.trim="userInfo.account"/><br/>
密码: <input type="password" v-model="userInfo.password"/><br/>
年龄: <input type="number" v-model.number="userInfo.age"/><br/>

性别:
男: <input type="radio"name="sex" v-model="userInfo.sex" value="male"/>
女: <input type="radio"name="sex" v-model="userInfo.sex" value="female"/><br/>

爱好
学习: <input type="checkbox" v-model="userInfo.hobby" value="学习"/>
吃饭: <input type="checkbox" v-model="userInfo.hobby" value="吃饭"/>
游戏: <input type="checkbox" v-model="userInfo.hobby" value="游戏"/><br/>

所属校区
<select v-model="userInfo.city">
<option value="">请选择</option>
<option value="北京">北京</option>
<option value="上海">上海</option>
<option value="武汉">武汉</option>
<option value="深圳">深圳</option>
</select>

<br/><br/>
其他信息
<textarea v-model.lazy="userInfo.other"></textarea><br/><br/>

<input type="checkbox" v-model="userInfo.agree"><a href="https://www.baidu.com">《用户协议》</a><button>提交</button>
</form>

</div>

</body>


<script type="text/javascript">
Vue.config.productionTip = false
new Vue({
el: '#root',
data: {
userInfo:{
account:'',
password:'',
age:'',
sex:'female',
hobby:[],
city:'北京',
other:'',
agree:''
}
},
methods:{
demo(){
console.log(JSON.stringify(this.userInfo))
}
}
})
</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
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
<body>

<div id="root">
<h2>显示格式化后的时间</h2>

<!-- 计算属性实现-->
<h3>现在是:{{fmtTime}}</h3>

<!-- methods -->
<h3>现在是:{{getFmtTime()}}</h3>

<!-- 过滤器实现 -->
<h3>现在是:{{time | timeFormater()}}</h3>

<!-- 过滤器实现(传参) -->
<h3>现在是:{{time | timeFormater('YYYY__MM__DD') | mySlice}}</h3>
</div>

<div id="root2">
{{name | mySlice}}
</div>

</body>
<script type="text/javascript">
Vue.config.productionTip = false
//全局过滤器
Vue.filter('mySlice',function (value){
return value.slice(0,4)
})

new Vue({
el: '#root',
data: {
time: 1621561377603
},
computed:{
fmtTime(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');
}

},
methods:{
getFmtTime(){
return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss');
}
},

// 局部过滤器
filters:{
timeFormater(value,str= 'YYYY-MM-DD HH:mm:ss'){
return dayjs(value).format(str);
}
}
})


new Vue({
el: '#root2',
data: {
name: 'zkc12312312'
}
})
</script>

生命周期

beforeCreate

1

created(初始化)

1
2
3
created() { // 初始化(进入页面 就直接执行的代码)
this.UserAll();
},

beforeMount

mounted(仅在整个视图都被渲染之后才会运行的代码)

1
2
3
4
5
mounted: function () {
this.$nextTick(function () {
// 仅在整个视图都被渲染之后才会运行的代码
})
}

beforeUpdate

updated

activated

1
2
3
activated() { //激活时触发

},

deactivated

1
2
3
deactivated() { // 失活时触发

}

beforeDestroy

1
2
3
beforeDestroy() {
实例销毁之前调用
},

destroyed

errorCaptured

组件

非单文件组件(局部组件、全局组件)

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
77
78
<body>
<div id="root">
<h1>{{msg}}</h1>
<hell></hell>
<xuexiao></xuexiao><!--(第三步)(局部) -->
<hr/>
<xinxi></xinxi><!--(第三步)(局部) -->
<xinxi></xinxi><!--(第三步)(局部) -->
</div>

<div id="root2">
<hell></hell>
</div>
</body>


<script type="text/javascript">
Vue.config.productionTip = false

//创建组件(第一步)(局部)
const ceshi1= Vue.extend({
template:'<div>' +
'<div>{{account}}</div>' +
'<div>{{password}}</div>' +
'<button @click="showName">点我</button>' +
'</div>',
data(){
return{
account:'1',
password:'2'
}
},
methods:{
showName(){
alert(this.account)
}
}
})

//创建组件(第一步)(局部)
const ceshi2= Vue.extend({
template:'<div><div>{{age}}</div><div>{{sex}}</div></div>',
data(){
return{
age:'3',
sex:'4'
}
}
})

//创建组件(第一步)(全局)
const hell = Vue.extend({
template:'<div><h2>你好{{name}}</h2></div>',
data(){
return{
name:'zkc'
}
}
})
Vue.component('hell',hell)/*注册组件 (全局)*/


new Vue({
el: '#root',
data:{
msg:'你好!'
},
/* 注册组件 (局部组件)(第二步) */
components:{
xuexiao:ceshi1,
xinxi:ceshi2
}

})
new Vue({
el: '#root2',
})
</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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
<body>
<div id="root">
<h1>{{msg}}</h1>
<School></School>
<!-- <School/> 必须在vue-cli下面使用 -->
</div>
</body>
<script type="text/javascript">

Vue.config.productionTip = false

//创建组件(第一步)

const ss = { // 简写

}

const s = Vue.extend({ // 正常写法
name:'zkc', /* 可以指定组件在开发者工具中的名字 */
template:'<div>' +
'<h2>名称{{name}}</h2>' +
'<h2>地址{{address}}</h2>' +
'</div>',
data(){
return{
name:'zkc',
address:'北京'
}
}
})

new Vue({
el: '#root',
data:{
msg:'你好!'
},
/* 注册组件 (局部组件)(第二步) */
components:{
/*
组件命名推荐(单个单词):
school
School
多单词推荐:
'my-school'
MySchool(脚手架中使用)
*/
School:s,
}

})
</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
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
<body>
<div id="root">

</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false

const student = Vue.extend({ // 正常写法
name:'student',
template:'<div>' +
'<h2>姓名{{name}}</h2>' +
'<h2>年龄{{age}}</h2>' +
'</div>',
data(){
return{
name:'zkc',
age:'18'
}
}
})


const school = Vue.extend({ // 正常写法
name:'school',
template:'<div>' +
'<h2>名称{{name}}</h2>' +
'<h2>地址{{address}}</h2>' +
'<student></student>'+
'</div>',
data(){
return{
name:'zkc',
address:'北京'
}
},
components:{
student,
}
})


const hello = Vue.extend({
template:'<div><h2>你好{{name}}</h2></div>',
data(){
return{
name:'zkc'
}
}
})



// 定义app组件
const app = Vue.extend({
template:'<div><hello></hello><school></school></div>',
components:{
school,
hello
}
})

new Vue({
template:'<app></app>',
el: '#root',
// 注册组件 局部
components:{
app
}
})

</script>

VueComponent

1
2
3
4
VueComponent 简称 vc  与vm 的区别:
vc el(x) data(){}
vm el data:{} 或者 data(){}

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
<body>
<div id="root">
<school></school>
<hello></hello>
</div>
</body>
<script type="text/javascript">
Vue.config.productionTip = false

const school = Vue.extend({ // 每次调用 返回的都是一个全新的 VueComponent
name:'school',
template:'<div>' +
'<h2>名称{{name}}</h2>' +
'<h2>地址{{address}}</h2>' +
'<button @click="showNmae">点击</button>' +
'</div>',
data(){
return{
name:'zkc',
address:'北京'
}
},
methods:{
showNmae(){
alert(this.name) // 这里的 this 是 VueComponent
}
}
})

const hello = Vue.extend({ // 正常写法
name:'hello',
template:'<div>' +
'<h2>名称{{name}}2</h2>' +
'<h2>地址{{address}}2</h2>' +
'</div>',
data(){
return{
name:'zkc',
address:'北京'
}
}
})


new Vue({
el: '#root',
components:{
school,
hello
}
})


</script>

vue_cli

vue_cli目录介绍

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
.
|-- build // 项目构建(webpack)相关代码
| |-- build.js // 生产环境构建代码
| |-- check-version.js // 检查node、npm等版本
| |-- dev-client.js // 热重载相关
| |-- dev-server.js // 构建本地服务器
| |-- utils.js // 构建工具相关
| |-- webpack.base.conf.js // webpack基础配置
| |-- webpack.dev.conf.js // webpack开发环境配置
| |-- webpack.prod.conf.js // webpack生产环境配置
|-- config // 项目开发环境配置
| |-- dev.env.js // 开发环境变量
| |-- index.js // 项目一些配置变量
| |-- prod.env.js // 生产环境变量
| |-- test.env.js // 测试环境变量
|-- src // 源码目录
| |-- components // vue公共组件
| |-- store // vuex的状态管理
| |-- App.vue // 页面入口文件
| |-- main.js // 程序入口文件,加载各种公共组件
|-- static // 静态文件,比如一些图片,json数据等
| |-- data |-- .babelrc // ES6语法编译配置
|-- .editorconfig // 定义代码格式
|-- .gitignore // git上传需要忽略的文件格式
|-- README.md // 项目说明
|-- favicon.ico
|-- index.html // 入口页面
|-- package.json // 项目基本信息,npm的包依赖安装信息
.

暴露

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
// 分别暴露
// export const school = Vue.extend({
// data(){
// return{
// schoolName:'天下',
// address:'北京'
// }
// },
// methods:{
// showName(){
// alert(this.schoolName())
// }
// }
// })

// 统一暴露
// const school = Vue.extend({
// data(){
// return{
// schoolName:'天下',
// address:'北京'
// }
// },
// methods:{
// showName(){
// alert(this.schoolName())
// }
// }
// })
// export {school}


// 默认暴露(常用)
// const school = Vue.extend({
// data(){
// return{
// schoolName:'天下',
// address:'北京'
// }
// },
// methods:{
// showName(){
// alert(this.schoolName())
// }
// }
// })
// export default school

// 默认暴露(常用)优化
export default {
name:'School',
data(){
return{
schoolName:'天下',
address:'北京'
}
},
methods:{
showName(){
alert(this.schoolName())
}
}
}

output.js

1
2
3

vue inspect > output.js # 默认配置整理到output.js中
npx vue-cli-service inspect > output.js # 默认配置整理到output.js中

vue.config.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
27
28
29
30
31
32
33
34
pages: {
index: {
// page 的入口
entry: 'src/main.js',
// 模板来源
template: 'public/index.html',
}

}
// 关闭语法检查 (与pages同级)
lintOnSave:false

// 开启代理服务器(方式一) (与pages同级)
devServer:{
proxy:'http://localhost:8080'
}

//开启代理服务器(方式二)
devServer: {
proxy: {
'/atguigu': { // http:www.yuming.com:8080/atguigu
target: 'http://localhost:5000',
pathRewrite:{'^/atguigu':''}, // 用正则去掉前缀
// ws: true, //用于支持websocket
// changeOrigin: true //用于控制请求头中的host值
},
'/demo': {
target: 'http://localhost:5001',
pathRewrite:{'^/demo':''},
// ws: true, //用于支持websocket
// changeOrigin: true //用于控制请求头中的host值
}
}
}

ref

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 v-text="msg" ref="title"></h1>
<button @click="showName" ref="btn">点我输出上方dom元素</button>
<School ref="sch"/>
</div>
</template>



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


export default {
name: 'App',
components:{
School,
},
data(){
return{
msg:"欢迎"
}
},
methods:{
showName(){
console.log(this.$refs.title) //dom元素
console.log(this.$refs.btn) //dom元素
console.log(this.$refs.sch) //School组件的实列对象
}
}


}
</script>

props

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
77
78
# vue.app
<template>
<div>
<Student name="历史" sex="女" :age="18"/>
</div>
</template>



<script>
import Student from "./components/Student"
export default {
name: 'App',
components:{
Student,
}
}
</script>





#Student.vue
<template>
<div class="school">
<h1>{{msg}}</h1>
<h2>{{name}}</h2>
<h2>{{sex}}</h2>
<h2>{{myAge+1}}</h2>
<button @click="updateAge">Age修改</button>
</div>
</template>


<script>
// 默认暴露(常用)优化
export default {
name:'Student',
data(){
console.log(this)
return{
msg:"我是没事别学JAVA",
myAge:this.age
}
},
methods:{
updateAge(){
this.myAge++
}
},

//props:['name','age','sex'] // 简单声明接收

// 接收的同时,对数据进行类型限制
// props:{
// name:String,
// age:Number,
// sex:String
// }

// 接收的同时,对数据进行类型限制+默认值指定+必要性限制
props:{
name:{
type:String, // name的类型是字符串
required:true // name是必须要的
},
age:{
type:Number,
default:99 // 默认值
},
sex:{
type:String,
required:true
},
}
}
</script>

mixin

局部和全局要引入的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
export const hunhe = {
methods:{
showNmae(){
alert(this.name)
}

},
mounted(){
console.log('你好')
}

}


export const hunhe2 = {
data(){
return{
x:100,
y:200
}
}
}

全局混合

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 引入vue
import Vue from 'vue'
// 引入app组件 所有组件的父组件
import App from './App.vue'

import {hunhe,hunhe2} from './mixin' // 全局(混合)


// 关闭vue的生产提示
Vue.config.productionTip = false
Vue.mixin(hunhe) // 全局(混合)
Vue.mixin(hunhe2) // 全局(混合)



// 创建vue实列对象
new Vue({
render: h => h(App), // 将app组件放入容器中
}).$mount('#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
<template>
<div class="school">
<h2 @click="showNmae">{{name}}</h2>
<h2>{{sex}}</h2>
</div>
</template>


<script>
// 默认暴露(常用)优化
import {hunhe,hunhe2} from "@/mixin"; //局部(混合)

export default {
name:'Student',
data(){
console.log(this)
return{
name:"我是没事别学JAVA",
sex:"男"
}
},
mixins:[hunhe,hunhe2] //局部(混合)
}
</script>

插件

1
2
用于增强Vue
包含install方法的一个对象, 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
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
export default {
install(Vue){


Vue.filter('mySlice',function (value){
return value.slice(0,4)
})


Vue.directive('find',{

bind(element,binding){
element.value=binding.value
},

inserted(element){
element.focus()
},

update(element,binding){
element.value = binding.value
}


})


Vue.mixin({
data(){
return{
x:100,
y:200
}
}
})




Vue.prototype.hello = () =>{
alert("你好")
}

}
}

main.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 引入vue
import Vue from 'vue'
// 引入app组件 所有组件的父组件
import App from './App.vue'

// 引入插件
import plugins from './plugins'

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


// 使用插件
Vue.use(plugins)


// 创建vue实列对象
new Vue({
render: h => h(App), // 将app组件放入容器中
}).$mount('#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
77
<template>
<div>
<Student/>
<hr/>
<School/>
</div>
</template>



<script>
import Student from "./components/Student"
import School from "./components/School"
export default {
name: 'App',
components:{
Student,
School
}
}

</script>
-------------------------------------------------------------------------------------
<template>
<div class="Student">
<h2>{{name}}</h2>
<h2>{{sex}}</h2>
<input type="text" v-find:value="name"/>
</div>
</template>




<script>
export default {
name:'Student',
data(){
console.log(this)
return{
name:"我是没事别学JAVA",
sex:"男"
}
}
}
</script>
-------------------------------------------------------------------------------------
<template>
<div class="school">
<h2>{{name | mySlice}}</h2>
<h2>{{address}}</h2>
<button @click="test">点击</button>
</div>
</template>




<script>
// 默认暴露(常用)优化
export default {
name:'School',
data(){
console.log(this)
return{
name:"zkc1321313321",
address:"北京"
}
},
methods:{
test(){
this.hello()
}
}

}
</script>

样式

1
2
3
4
5
6
7
8
<style scoped>
.Student{
background-color: orange;
}
</style>


如果在app.vue中使用<style scoped> 则在其他vue文件中的相同的 class 和 id 样式就会失效

组件自定义事件

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
-----------------------------------------------------------------------main.js
import Vue from 'vue'
import App from './App.vue'

Vue.config.productionTip = false

new Vue({
render: h => h(App),
/* mounted() {
setTimeout(()=>{
this.$destroy()
},3000)
}, */
}).$mount('#app')
-----------------------------------------------------------------------App.vue
<template>
<div id="app">
<h2 class="title">{{msg}}</h2>
<h1>{{studentName}}</h1>

<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on) -->
<HelloWorld @atguigu="getStudentName" @demo="m1"/>

<!-- 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种写法,使用ref) -->
<HelloWorld ref="student" @click.native="show"/>
</div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'

export default {
name: 'App',
components: {
HelloWorld
},
data(){
return{
msg:'zkc',
studentName:''
}
},
methods:{
getStudentName(name,...params){
console.log('App收到了学生名:',name,params)
this.studentName = name
},
m1(){
console.log('demo事件被触发了!')
},
show(){
alert(123)
}
},
mounted() {
//this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件
this.$refs.student.$once('atguigu',this.getStudentName) //绑定自定义事件(一次性)
},
}
</script>

<style>
.title{
color: red;
}
</style>
-----------------------------------------------------------------------HelloWorld.vue
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<h2>当前求和为:{{number}}</h2>
<button @click="sendStudentlName">把学生名给App</button>
<button @click="unbind">解绑atguigu事件</button>

<button @click="death">销毁当前Student组件的实例(vc)</button>
<button @click="add">点我number++</button>

</div>
</template>

<script>
export default {
name: 'HelloWorld',
data() {
return {
name:'张三',
sex:'男',
number:0
}
},
methods: {
sendStudentlName(){
//触发Student组件实例身上的atguigu事件
this.$emit('atguigu',this.name,666,888,900)
this.$emit('demo')
//this.$emit('click') // 在app.vue 中如果不用@click.native="show" 这里就要这样写 ,引入vue 会任务你是自定事件,加上@click.native就行了,这里就不用写了
},
unbind(){
this.$off('atguigu') //解绑一个自定义事件
// this.$off(['atguigu','demo']) //解绑多个自定义事件
// this.$off() //解绑所有的自定义事件
},
death(){
this.$destroy() //销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效。
},
add(){
console.log('add回调被调用了')
this.number++
}

},
}
</script>

<style scoped>
div{
background-color: orange;
}
</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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
-----------------------------------------------------------------------main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
el:'#app',
render: h => h(App),
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线
},
})
-----------------------------------------------------------------------App.vue
<template>
<div class="app">
<h1>{{msg}}</h1>
<School/>
<Student/>
</div>
</template>

<script>
import Student from './components/Student'
import School from './components/School'

export default {
name:'App',
components:{School,Student},
data() {
return {
msg:'你好啊!',
}
}
}
</script>

<style scoped>
.app{
background-color: gray;
padding: 5px;
}
</style>
-----------------------------------------------------------------------School.vue
<template>
<div class="school">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</template>

<script>
export default {
name:'School',
data() {
return {
name:'尚硅谷',
address:'北京',
}
},
mounted() {
// console.log('School',this)
this.$bus.$on('hello',(data)=>{
console.log('我是School组件,收到了数据',data)
})
},
beforeDestroy() {
this.$bus.$off('hello')
},
}
</script>

<style scoped>
.school{
background-color: skyblue;
padding: 5px;
}
</style>
-----------------------------------------------------------------------Student.vue
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">把学生名给School组件</button>
</div>
</template>

<script>
export default {
name:'Student',
data() {
return {
name:'张三',
sex:'男',
}
},
mounted() {
// console.log('Student',this.x)
},
methods: {
sendStudentName(){
this.$bus.$emit('hello',this.name)
}
},
}
</script>

<style scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
npm install --save pubsub-js


-----------------------------------------------------------------------main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//关闭Vue的生产提示
Vue.config.productionTip = false

//创建vm
new Vue({
el:'#app',
render: h => h(App),
})
-----------------------------------------------------------------------App.vue
<template>
<div class="app">
<h1>{{msg}}</h1>
<School/>
<Student/>
</div>
</template>

<script>
import Student from './components/Student'
import School from './components/School'

export default {
name:'App',
components:{School,Student},
data() {
return {
msg:'你好啊!',
}
}
}
</script>

<style scoped>
.app{
background-color: gray;
padding: 5px;
}
</style>
-----------------------------------------------------------------------Student.vue
<template>
<div class="student">
<h2>学生姓名:{{name}}</h2>
<h2>学生性别:{{sex}}</h2>
<button @click="sendStudentName">把学生名给School组件</button>
</div>
</template>

<script>
import pubsub from 'pubsub-js'
export default {
name:'Student',
data() {
return {
name:'张三',
sex:'男',
}
},
mounted() {
// console.log('Student',this.x)
},
methods: {
sendStudentName(){
pubsub.publish('hello',666)
}
},
}
</script>

<style scoped>
.student{
background-color: pink;
padding: 5px;
margin-top: 30px;
}
</style>
-----------------------------------------------------------------------School.vue
<template>
<div class="school">
<h2>学校名称:{{name}}</h2>
<h2>学校地址:{{address}}</h2>
</div>
</template>

<script>
import pubsub from 'pubsub-js'
export default {
name:'School',
data() {
return {
name:'尚硅谷',
address:'北京',
}
},
methods:{
// demo(msgName,data){
// console.log('hello消息收到了',msgName,data) // 第二种
// }
},
mounted() {
this.pubId = pubsub.subscribe('hello',(msgName,data)=>{ // 第一种
console.log(this)
console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
})

// this.pubId = pubsub // 第二种
// .subscribe('hello',this.demo) // 第二种

},
beforeDestroy() {
pubsub.unsubscribe(this.pubId)
},
}
</script>

<style scoped>
.school{
background-color: skyblue;
padding: 5px;
}
</style>
-----------------------------------------------------------------------

vue-resource

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
import vueResource from 'vue-resource'
// 使用插件
Vue.use(vueResource)

-----------------------------------------------------------------------

<template>
<section class="jumbotron">
<h3 class="jumbotron-heading">Search Github Users</h3>
<div>
<input type="text" placeholder="enter the name you search" v-model="keyWord"/>&nbsp;
<button @click="searchUsers">Search</button>
</div>
</section>
</template>

<script>
export default {
name:'Search',
data() {
return {
keyWord:''
}
},
methods: {
searchUsers(){
//请求前更新List的数据
this.$bus.$emit('updateListData',{isLoading:true,errMsg:'',users:[],isFirst:false})
this.$http.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response => {
console.log('请求成功了')
//请求成功后更新List的数据
this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
},
error => {
//请求后更新List的数据
this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
}
)
}
},
}
</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
-----------------------------------------------------------------------
<template>
<div class="container">
<Category title="美食" >
<img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
</Category>

<Category title="游戏" >
<ul>
<li v-for="(g,index) in games" :key="index">{{g}}</li>
</ul>
</Category>

<Category title="电影">
<video controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
</Category>
</div>
</template>
-----------------------------------------------------------------------
<template>
<div class="category">
<h3>{{title}}分类</h3>
<!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
<slot>我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
</div>
</template>

具名插槽

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
-----------------------------------------------------------------------
<template>
<div class="category">
<h3>{{title}}分类</h3>
<!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
<slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现1</slot>
<slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现2</slot>
</div>
</template>

<script>
export default {
name:'Category',
props:['title']
}
</script>
-----------------------------------------------------------------------
<template>
<div class="container">
<Category title="美食" >
<img slot="center" src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
<a slot="footer" href="http://www.atguigu.com">更多美食</a>
</Category>

<Category title="游戏" >
<ul slot="center">
<li v-for="(g,index) in games" :key="index">{{g}}</li>
</ul>
<div class="foot" slot="footer">
<a href="http://www.atguigu.com">单机游戏</a>
<a href="http://www.atguigu.com">网络游戏</a>
</div>
</Category>

<Category title="电影">
<video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
<template v-slot:footer> <!-- <template v-slot:footer> 只有 template 才能这样写 -->
<div class="foot">
<a href="http://www.atguigu.com">经典</a>
<a href="http://www.atguigu.com">热门</a>
<a href="http://www.atguigu.com">推荐</a>
</div>
<h4>欢迎前来观影</h4>
</template>
</Category>
</div>
</template>

<script>
import Category from './components/Category'
export default {
name:'App',
components:{Category},
data() {
return {
foods:['火锅','烧烤','小龙虾','牛排'],
games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
films:['《教父》','《拆弹专家》','《你好,李焕英》','《尚硅谷》']
}
},
}
</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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
-----------------------------------------------------------------------
<template>
<div class="container">

<Category title="游戏">
<template scope="ceshi"> <!-- 这个名字是自己起的 -->
<ul>
<li v-for="(g,index) in ceshi.games" :key="index">{{g}}</li>
</ul>
</template>
</Category>

<Category title="游戏">
<template scope="{games}">
<ol>
<li style="color:red" v-for="(g,index) in games" :key="index">{{g}}</li>
</ol>
</template>
</Category>

<Category title="游戏">
<template slot-scope="{games}">
<h4 v-for="(g,index) in games" :key="index">{{g}}</h4>
</template>
</Category>

</div>
</template>

<script>
import Category from './components/Category'
export default {
name:'App',
components:{Category},
}
</script>
-----------------------------------------------------------------------
<template>
<div class="category">
<h3>{{title}}分类</h3>
<slot :games="games" msg="hello">我是默认的一些内容</slot>
</div>
</template>

<script>
export default {
name:'Category',
props:['title'],
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽'],
}
},
}
</script>

vuex

安装

1
2
3
4
5
6
npm i vuex

// 引入Vuex
import Vuex from 'vuex'
// 使用插件
Vue.use(Vuex)
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
-----------------------------------------------------------store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
}
//准备mutations——用于操作数据(state)
const mutations = {
}
//准备state——用于存储数据
const state = {
}

//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})

-----------------------------------------------------------main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入插件
import vueResource from 'vue-resource'
//引入store
import store from './store'

//关闭Vue的生产提示
Vue.config.productionTip = false
//使用插件
Vue.use(vueResource)

//创建vm
new Vue({
el:'#app',
render: h => h(App),
store,
beforeCreate() {
Vue.prototype.$bus = this
}
})

基本使用

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
-----------------------------------------------------------store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
/* jia(context,value){
console.log('actions中的jia被调用了')
context.commit('JIA',value)
},
jian(context,value){
console.log('actions中的jian被调用了')
context.commit('JIAN',value)
}, */
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
//准备mutations——用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//准备state——用于存储数据
const state = {
sum:0 //当前的和
}

//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
})
-----------------------------------------------------------components/Count.vue
<template>
<div>
<h1>当前求和为:{{$store.state.sum}}</h1>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前求和为奇数再加</button>
<button @click="incrementWait">等一等再加</button>
</div>
</template>

<script>
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
}
},
methods: {
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
mounted() {
console.log('Count',this)
},
}
</script>

getters

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
-----------------------------------------------------------store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
/* jia(context,value){
console.log('actions中的jia被调用了')
context.commit('JIA',value)
},
jian(context,value){
console.log('actions中的jian被调用了')
context.commit('JIAN',value)
}, */
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
//准备mutations——用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//准备state——用于存储数据
const state = {
sum:0 //当前的和
}
//准备getters——用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum*10
}
}

//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
-----------------------------------------------------------components/Count.vue
<template>
<div>
<h1>当前求和为:{{$store.state.sum}}</h1>
<h3>当前求和放大10倍为:{{$store.getters.bigSum}}</h3>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前求和为奇数再加</button>
<button @click="incrementWait">等一等再加</button>
</div>
</template>

<script>
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
}
},
methods: {
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
mounted() {
console.log('Count',this.$store)
},
}
</script>

<style lang="css">
button{
margin-left: 5px;
}
</style>

mapState、mapGetters

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
-----------------------------------------------------------store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
//准备mutations——用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//准备state——用于存储数据
const state = {
sum:0, //当前的和
school:'尚硅谷',
subject:'前端'
}
//准备getters——用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum*10
}
}

//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
-----------------------------------------------------------components/Count.vue
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍为:{{bigSum}}</h3>
<h3>我在{{school}},学习{{subject}}</h3>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment">+</button>
<button @click="decrement">-</button>
<button @click="incrementOdd">当前求和为奇数再加</button>
<button @click="incrementWait">等一等再加</button>
</div>
</template>

<script>
import {mapState,mapGetters} from 'vuex'
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
}
},
computed:{
//靠程序员自己亲自去写计算属性
/* sum(){
return this.$store.state.sum
},
school(){
return this.$store.state.school
},
subject(){
return this.$store.state.subject
}, */

//借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({sum:'sum',school:'school',subject:'subject'}),

//借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState(['sum','school','subject']),

/* ******************************************************************** */

/* bigSum(){
return this.$store.getters.bigSum
}, */

//借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
// ...mapGetters({bigSum:'bigSum'})

//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters(['bigSum'])

},
methods: {
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
mounted() {
const x = mapState({sum:'sum',school:'school',subject:'subject'})
console.log(x)
},
}
</script>

<style lang="css">
button{
margin-left: 5px;
}
</style>

mapMutations、mapActions

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
-----------------------------------------------------------store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const actions = {
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
}
//准备mutations——用于操作数据(state)
const mutations = {
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
}
}
//准备state——用于存储数据
const state = {
sum:0, //当前的和
school:'尚硅谷',
subject:'前端'
}
//准备getters——用于将state中的数据进行加工
const getters = {
bigSum(state){
return state.sum*10
}
}

//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state,
getters
})
-----------------------------------------------------------components/Count.vue
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍为:{{bigSum}}</h3>
<h3>我在{{school}},学习{{subject}}</h3>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>
</div>
</template>

<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
}
},
computed:{
//借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),

//借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState(['sum','school','subject']),

/* ******************************************************************** */

//借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
// ...mapGetters({bigSum:'bigSum'})

//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters(['bigSum'])

},
methods: {
//程序员亲自写方法
/* increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
}, */

//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
...mapMutations({increment:'JIA',decrement:'JIAN'}),

//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
// ...mapMutations(['JIA','JIAN']),

/* ************************************************* */

//程序员亲自写方法
/* incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
}, */

//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})

//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
// ...mapActions(['jiaOdd','jiaWait'])
},
mounted() {
const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
console.log(x)
},
}
</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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
--------------------------------------------------components/Count.vue
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍为:{{bigSum}}</h3>
<h3>我在{{school}},学习{{subject}}</h3>
<h3 style="color:red">Person组件的总人数是:{{personList.length}}</h3>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>
</div>
</template>

<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
}
},
computed:{
//借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState('countAbout',['sum','school','subject']),
...mapState('personAbout',['personList']),
//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters('countAbout',['bigSum'])
},
methods: {
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
},
mounted() {
console.log(this.$store)
},
}
</script>

<style lang="css">
button{
margin-left: 5px;
}
</style>
--------------------------------------------------components/Person.vue
<template>
<div>
<h1>人员列表</h1>
<h3 style="color:red">Count组件求和为:{{sum}}</h3>
<h3>列表中第一个人的名字是:{{firstPersonName}}</h3>
<input type="text" placeholder="请输入名字" v-model="name">
<button @click="add">添加</button>
<button @click="addWang">添加一个姓王的人</button>
<button @click="addPersonServer">添加一个人,名字随机</button>
<ul>
<li v-for="p in personList" :key="p.id">{{p.name}}</li>
</ul>
</div>
</template>

<script>
import {nanoid} from 'nanoid'
export default {
name:'Person',
data() {
return {
name:''
}
},
computed:{
personList(){
return this.$store.state.personAbout.personList
},
sum(){
return this.$store.state.countAbout.sum
},
firstPersonName(){
return this.$store.getters['personAbout/firstPersonName']
}
},
methods: {
add(){
const personObj = {id:nanoid(),name:this.name}
this.$store.commit('personAbout/ADD_PERSON',personObj)
this.name = ''
},
addWang(){
const personObj = {id:nanoid(),name:this.name}
this.$store.dispatch('personAbout/addPersonWang',personObj)
this.name = ''
},
addPersonServer(){
this.$store.dispatch('personAbout/addPersonServer')
}
},
}
</script>
--------------------------------------------------store/count.js
//求和相关的配置
export default {
namespaced:true,
actions:{
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
},
mutations:{
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
},
},
state:{
sum:0, //当前的和
school:'尚硅谷',
subject:'前端',
},
getters:{
bigSum(state){
return state.sum*10
}
},
}
--------------------------------------------------store/person.js
//人员管理相关的配置
import axios from 'axios'
import { nanoid } from 'nanoid'
export default {
namespaced:true,
actions:{
addPersonWang(context,value){
if(value.name.indexOf('王') === 0){
context.commit('ADD_PERSON',value)
}else{
alert('添加的人必须姓王!')
}
},
addPersonServer(context){
axios.get('https://api.uixsj.cn/hitokoto/get?type=social').then(
response => {
context.commit('ADD_PERSON',{id:nanoid(),name:response.data})
},
error => {
alert(error.message)
}
)
}
},
mutations:{
ADD_PERSON(state,value){
console.log('mutations中的ADD_PERSON被调用了')
state.personList.unshift(value)
}
},
state:{
personList:[
{id:'001',name:'张三'}
]
},
getters:{
firstPersonName(state){
return state.personList[0].name
}
},
}
--------------------------------------------------store/index.js
//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
import countOptions from './count'
import personOptions from './person'
//应用Vuex插件
Vue.use(Vuex)

//创建并暴露store
export default new Vuex.Store({
modules:{
countAbout:countOptions,
personAbout:personOptions
}
})
--------------------------------------------------App.vue
<template>
<div>
<Count/>
<hr>
<Person/>
</div>
</template>

<script>
import Count from './components/Count'
import Person from './components/Person'

export default {
name:'App',
components:{Count,Person},
mounted() {
// console.log('App',this)
},
}
</script>
--------------------------------------------------main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入插件
import vueResource from 'vue-resource'
//引入store
import store from './store'

//关闭Vue的生产提示
Vue.config.productionTip = false
//使用插件
Vue.use(vueResource)

//创建vm
new Vue({
el:'#app',
render: h => h(App),
store,
beforeCreate() {
Vue.prototype.$bus = this
}
})

路由

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
 # 安装
npm install --save vue-router


//引入VueRouter
import VueRouter from 'vue-router'
//应用插件
Vue.use(VueRouter)

#创建
router/index.js
//引入路由器
import router from './router'



//创建vm
new Vue({
el:'#app',
render: h => h(App),
router:router # 主要是这个地方添加
})
# 以上都是在main.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
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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
-----------------------------------------------------------------------------------------main.js
//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'


//引入VueRouter
import VueRouter from 'vue-router'
//引入路由器
import router from './router'

//关闭Vue的生产提示
Vue.config.productionTip = false
//应用插件
Vue.use(VueRouter)

//创建vm
new Vue({
el:'#app',
render: h => h(App),
router:router
})
-----------------------------------------------------------------------------------------App.vue
<template>
<div>
<div class="row">
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header"><h2>Vue Router Demo</h2></div>
</div>
</div>
<div class="row">
<div class="col-xs-2 col-xs-offset-2">
<div class="list-group">
<!-- Vue中借助router-link标签实现路由的切换 -->
<router-link class="list-group-item" active-class="active" to="/about">About</router-link>
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
</div>
</div>
<div class="col-xs-6">
<div class="panel">
<div class="panel-body">
<!-- 指定组件的呈现位置 -->
<router-view></router-view>
</div>
</div>
</div>
</div>
</div>
</template>

<script>
export default {
name:'App',
}
</script>
-----------------------------------------------------------------------------------------router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../components/About'
import Home from '../components/Home'

//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home
}
]
})
-----------------------------------------------------------------------------------------Home.vue
<template>
<h2>我是Home的内容</h2>
</template>

<script>
export default {
name:'Home'
}
</script>
-----------------------------------------------------------------------------------------About.vue
<template>
<h2>我是About的内容</h2>
</template>

<script>
export default {
name:'About'
}
</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
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
-----------------------------------------------------------------------------------------router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'

//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
}
]
}
]
})
-----------------------------------------------------------------------------------------Home.vue
<template>
<div>
<h2>Home组件内容</h2>
<div>
<ul class="nav nav-tabs">
<li>
<router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
</li>
<li>
<router-link class="list-group-item" active-class="active" to="/home/message">Message</router-link>
</li>
</ul>
<router-view></router-view>
</div>
</div>
</template>

<script>
export default {
name:'Home',
/* beforeDestroy() {
console.log('Home组件即将被销毁了')
}, */
/* mounted() {
console.log('Home组件挂载完毕了',this)
window.homeRoute = this.$route
window.homeRouter = this.$router
}, */
}
</script>

query参数

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
-----------------------------------------------------------------------------------------Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- 跳转路由并携带query参数,to的字符串写法 第一种方式 -->
<!-- <router-link :to="`/home/message/datail?id=${m.id}&title=${m.title}`">{{m.title}}</router-link>-->

<!-- 跳转路由并携带query参数,to的对象写法 第二种方式-->
<router-link :to="{
path:'/home/message/datail',
query:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>

</li>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>

<script>
export default {
name:'Message',
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'},
{id:'004',title:'消息004'},
{id:'005',title:'消息005'}
]
}
}
}
</script>
-----------------------------------------------------------------------------------------Detail.vue
<template>
<ul>
<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>
</ul>
</template>

<script>
export default {
name: "Detail",
mounted() {
console.log(this.$route)
}

}
</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
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
-----------------------------------------------------------------------------------------router/index.js
作用:简化路由的跳转
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
children:[
{
name:'xiangqing', //给路由命名
path:'datail',
component:Detail
}
]
}
]
}
]
})
-----------------------------------------------------------------------------------------
<router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
<router-link class="list-group-item" active-class="active" :to="{name:'guanyu'}">About</router-link>



<!-- 跳转路由并携带query参数,to的对象写法 -->
<router-link :to="{
//path:'/home/message/datail',
name:'xiangqing', // 可以使用name简化跳转
query:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>

params参数

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
-----------------------------------------------------------------------------------------router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'datail/:id/:title', //使用占位符声明接收params参数
component:Detail
}
]
}
]
}
]
})
-----------------------------------------------------------------------------------------
<!-- 跳转路由并携带params参数,to的字符串写法 第一种方式 -->
<!-- <router-link :to="`/home/message/datail/${m.id}/${m.title}`">{{m.title}}</router-link>-->

<!-- 跳转路由并携带params参数,to的对象写法 第二种方式-->
<router-link :to="{
//path:'/home/message/datail',
name:'xiangqing', // 用params参数,这里必须用路由的命名,不允许用path
params:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>

路由的props配置

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
-----------------------------------------------------------------------------------------router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
export default new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
path:'news',
component:News,
},
{
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'datail/:id/:title',
component:Detail,
// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}

//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true

//props的第三种写法,值为函数
props($route){
return {
id:$route.params.id, //params参数 写params query参数 写query
title:$route.params.title,
a:1,
b:'hello'
}
}
}
]
}
]
}
]
})
-----------------------------------------------------------------------------------------Message.vue
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<!-- 跳转路由并携带params参数,to的字符串写法 -->
<!-- <router-link :to="`/home/message/datail/${m.id}/${m.title}`">{{m.title}}</router-link>-->

<!-- 跳转路由并携带params参数,to的对象写法 -->
<router-link :to="{
//path:'/home/message/datail',
name:'xiangqing', // 用params参数,这里必须用路由的命名,不允许用path
params:{
id:m.id,
title:m.title
}
}">
{{m.title}}
</router-link>

</li>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>

<script>
export default {
name:'Message',
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'},
{id:'004',title:'消息004'},
{id:'005',title:'消息005'}
]
}
}
}
</script>
-----------------------------------------------------------------------------------------Detail.vue
<template>
<ul>
<li>消息编号:{{id}}</li>
<li>消息标题:{{title}}</li>


<li>{{a}}</li>
<li>{{b}}</li>
</ul>
</template>

<script>
export default {
name: "Detail",
props:['id','title','a','b'],
mounted() {
console.log(this.$route)
}
}
</script>

router-link的replace属性

1
2
3
4
5
作用:添加该属性后点击此链接浏览器就不会有前进后退了


<router-link replace class="list-group-item" active-class="active" :to="{name:'guanyu'}">About</router-link>
<router-link replace class="list-group-item" active-class="active" to="/home">Home</router-link>

编程式路由导航

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
77
78
79
80
81
82
83
作用:不借助 router-link 实现路由跳转,让路由跳转更加零花
-----------------------------------------------------------------------------------------
<template>
<div>
<ul>
<li v-for="m in messageList" :key="m.id">
<button @click="pushShow(m)">push查看</button>
<button @click="replaceShow(m)">replace查看</button>
</li>
</ul>
<hr/>
<router-view></router-view>
</div>
</template>

<script>
export default {
name:'Message',
data(){
return{
messageList:[
{id:'001',title:'消息001'},
{id:'002',title:'消息002'},
{id:'003',title:'消息003'},
{id:'004',title:'消息004'},
{id:'005',title:'消息005'}
]
}
},
methods:{
pushShow(m){
this.$router.push({
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
})
},
replaceShow(m){
this.$router.replace({
name:'xiangqing',
params:{
id:m.id,
title:m.title
}
})
}
}


}
</script>


------------------------------后退---------前进-------go(可前进可后退)---------------------------------------------
<template>
<div class="col-xs-offset-2 col-xs-8">
<div class="page-header">
<h2>Vue Router Demo</h2>
<button @click="back">后退</button>
<button @click="forward">前进</button>
<button @click="go">go</button>
</div>
</div>
</template>

<script>
export default {
name:'Banner',
methods:{
back(){
this.$router.back()
},
forward(){
this.$router.forward()
},
go(){
this.$router.go(-2)
}
}
}
</script>

缓存路由组件

1
2
3
4
5
6
7
8
作用: 让不展示的组件保持挂载,不被注销
<keep-alive include="News"> // 不写 include 标识全部挂载,写了就是指定组件挂载,写的是组件名字
<router-view></router-view>
</keep-alive>

<keep-alive :include="['News','Meeeage']"> // 缓存多个
<router-view></router-view>
</keep-alive>

全局前置路由守卫

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
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About
},
{
path:'/home',
component:Home,
children:[
{
name:'xinwen',
path:'news',
component:News,
},
{
name:'xiaoxi',
path:'message',
component:Message,
children:[
{
name:'xiangqing',
path:'datail/:id/:title',
component:Detail,
// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}

//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true

//props的第三种写法,值为函数
props($route){
return {
id:$route.params.id, //params参数 写params query参数 写query
title:$route.params.title,
a:1,
b:'hello'
}
}
}
]
}
]
}
]
})

// 全局路由前置路由守卫-------初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,form,next) =>{
console.log(to, form)
//if(to.path === '/home/news' || to.path === '/home/message'){
if(to.name === 'xinwen' || to.name === 'xiaoxi'){
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert("学校名不对,无权查看")
}
}else {
next()
}

})

export default router

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
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{isAuth:false}
},
{
path:'/home',
component:Home,
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{isAuth:true}
},
{
name:'xiaoxi',
path:'message',
component:Message,
meta:{isAuth:true},
children:[
{
name:'xiangqing',
path:'datail/:id/:title',
component:Detail,
// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}

//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true

//props的第三种写法,值为函数
props($route){
return {
id:$route.params.id, //params参数 写params query参数 写query
title:$route.params.title,
a:1,
b:'hello'
}
}
}
]
}
]
}
]
})

// 全局路由前置路由守卫-------初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next) =>{
console.log(to, from)
if(to.meta.isAuth){ // 判断是否需要权限
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert("学校名不对,无权查看")
}
}else {
next()
}

})
export default router

全局后置路由守卫

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
77
78
79
80
81
82
83
84
85
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{isAuth:false,title:'关于'}
},
{
path:'/home',
component:Home,
meta:{isAuth:false,title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{isAuth:true,title:'新闻'}
},
{
name:'xiaoxi',
path:'message',
component:Message,
meta:{isAuth:true,title:'消息'},
children:[
{
name:'xiangqing',
path:'datail/:id/:title',
component:Detail,
meta:{isAuth:true,title:'详情'},
// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}

//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true

//props的第三种写法,值为函数
props($route){
return {
id:$route.params.id, //params参数 写params query参数 写query
title:$route.params.title,
a:1,
b:'hello'
}
}
}
]
}
]
}
]
})

// 全局路由前置路由守卫-------初始化的时候被调用、每次路由切换之前被调用
router.beforeEach((to,from,next) =>{
console.log('前置路由守卫',to, from)
if(to.meta.isAuth){ // 判断是否需要权限
if(localStorage.getItem('school')==='atguigu'){
next()
}else{
alert("学校名不对,无权查看")
}
}else {
next()
}

})
// 全局路由后置路由守卫-------初始化的时候被调用、每次路由切换之后被调用
router.afterEach((to,from) =>{
console.log('后置路由守卫',to, from)
document.title = to.meta.title || 'zkc'
})


export default router

独享路由守卫

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{isAuth:false,title:'关于'}
},
{
path:'/home',
component:Home,
meta:{isAuth:false,title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{isAuth:true,title:'新闻'},
beforeEnter:(to,from,next) =>{
console.log('独享路由守卫', to, from)
if (to.meta.isAuth) { // 判断是否需要权限
if (localStorage.getItem('school') === 'atguigu') {
next()
} else {
alert("学校名不对,无权查看")
}
} else {
next()
}
}
},
{
name:'xiaoxi',
path:'message',
component:Message,
meta:{isAuth:true,title:'消息'},
children:[
{
name:'xiangqing',
path:'datail/:id/:title',
component:Detail,
meta:{isAuth:true,title:'详情'},
// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}

//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true

//props的第三种写法,值为函数
props($route){
return {
id:$route.params.id, //params参数 写params query参数 写query
title:$route.params.title,
a:1,
b:'hello'
}
}
}
]
}
]
}
]
})

// // 全局路由前置路由守卫-------初始化的时候被调用、每次路由切换之前被调用
// router.beforeEach((to,from,next) =>{
// console.log('前置路由守卫',to, form)
// if(to.meta.isAuth){ // 判断是否需要权限
// if(localStorage.getItem('school')==='atguigu'){
// next()
// }else{
// alert("学校名不对,无权查看")
// }
// }else {
// next()
// }
//
// })
// // 全局路由后置路由守卫-------初始化的时候被调用、每次路由切换之后被调用
// router.afterEach((to,from) =>{
// console.log('后置路由守卫',to, form)
// document.title = to.meta.title || 'zkc'
// })
export default router

组件内路由守卫

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
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
-----------------------------------------------------------------------------------------About.vue
<template>
<h2>我是About的内容</h2>
</template>

<script>
export default {
name: 'About',
mounted() {
console.log(this.$route)
},
// 通过路由规则,进入组件时被调用
beforeRouteEnter(to,from,next){
console.log('beforeRouteEnter')
if (to.meta.isAuth) { // 判断是否需要权限
if (localStorage.getItem('school') === 'atguigu') {
next()
} else {
alert("学校名不对,无权查看")
}
} else {
next()
}
},
// 通过路由规则,离开组件时被调用
beforeRouteLeave(to,from,next){
console.log('beforeRouteEnter')
next()
}

}
</script>
-----------------------------------------------------------------------------------------router/index.js
// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from "../pages/Detail";

//创建并暴露一个路由器
const router = new VueRouter({
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{isAuth:true,title:'关于'}
},
{
path:'/home',
component:Home,
meta:{isAuth:false,title:'主页'},
children:[
{
name:'xinwen',
path:'news',
component:News,
meta:{isAuth:true,title:'新闻'},
beforeEnter:(to,from,next) =>{
console.log('独享路由守卫', to, from)
if (to.meta.isAuth) { // 判断是否需要权限
if (localStorage.getItem('school') === 'atguigu') {
next()
} else {
alert("学校名不对,无权查看")
}
} else {
next()
}
}
},
{
name:'xiaoxi',
path:'message',
component:Message,
meta:{isAuth:true,title:'消息'},
children:[
{
name:'xiangqing',
path:'datail/:id/:title',
component:Detail,
meta:{isAuth:true,title:'详情'},
// props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
// props:{a:1,b:'hello'}

//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
// props:true

//props的第三种写法,值为函数
props($route){
return {
id:$route.params.id, //params参数 写params query参数 写query
title:$route.params.title,
a:1,
b:'hello'
}
}
}
]
}
]
}
]
})

// // 全局路由前置路由守卫-------初始化的时候被调用、每次路由切换之前被调用
// router.beforeEach((to,from,next) =>{
// console.log('前置路由守卫',to, form)
// if(to.meta.isAuth){ // 判断是否需要权限
// if(localStorage.getItem('school')==='atguigu'){
// next()
// }else{
// alert("学校名不对,无权查看")
// }
// }else {
// next()
// }
//
// })
// // 全局路由后置路由守卫-------初始化的时候被调用、每次路由切换之后被调用
// router.afterEach((to,from) =>{
// console.log('后置路由守卫',to, form)
// document.title = to.meta.title || 'zkc'
// })


export default router

_history模式和hash模式

1
2
3
4
5
6
7
8
9
10
11
12
13
-----------------------------------------------------------------------------------------router/index.js
//创建并暴露一个路由器
const router = new VueRouter({
mode: 'history', // 去掉url中的#
routes:[
{
name:'guanyu',
path:'/about',
component:About,
meta:{isAuth:true,title:'关于'}
}
})
export default router

element-ui安装

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
项目目录下运行
npm i element-ui -S


# 完整引入
// 引入ElementUI组件库
import ElementUI from 'element-ui'
// 引入ElementUI全部样式
import 'element-ui/lib/theme-chalk/index.css'
// 应用ElementUI
Vue.use(ElementUI)



# 按需引入
在babel.config.js中追加
{
"presets": [["es2015", { "modules": false }]],
"plugins": [
[
"component",
{
"libraryName": "element-ui",
"styleLibraryName": "theme-chalk"
}
]
]
}

import { Button, Select } from 'element-ui';
Vue.component(Button.name, Button);
Vue.component(Select.name, Select);
/* 或写为
* Vue.use(Button)
* Vue.use(Select)
*/

axios

安装

1
npm install axios
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>
<button @click="searchUsers">Search</button>
</div>
</template>

<script>
import axios from 'axios'
export default {
name:'Search',
methods: {
searchUsers(){
axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
response => {
console.log('请求成功了')
//请求成功后更新List的数据
this.$bus.$emit('updateListData',{isLoading:false,errMsg:'',users:response.data.items})
},
error => {
//请求后更新List的数据
this.$bus.$emit('updateListData',{isLoading:false,errMsg:error.message,users:[]})
}
)
}
},
}
</script>

vue打包

1
npm run build

swiper使用

1
2
# 引入指定版本的swiper
cnpm install swiper@5.4.5