Vue笔记

本文最后更新于:2025年2月11日 晚上

为了应付一些课设的要求,就去B站找了个培训机构 的视频学习了一下Vue2,这是当时记的笔记

vue基础

MVVM

MVC

M:model V:view C:controller

MVVM

M:model V:view VM:view model

VM的实现原理

view model中定义了一个Observer(观察者)

  • ViewModel能够观察到数据的变化,并对视图对应的内容进行更新
  • ViewModel能够监听到视图数据的变化,并能够通知数据发生变化

——MVVM通过VM实现了双向数据绑定

一.vue快速开始

1.获得vue的cdn文件

https://www.bootcdn.cn/vue/2.6.12/

2.在页面中使用vue

  • html:<div id="app"></div></div>

  • 创建一个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
<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="utf-8">
<title>Title</title>
</head>

<body>
<div id="app">
欢迎你!{{name}}
</div>
</body>

<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
new Vue({
el: '#app', // element
// 数据
data: {
name: 'jens'
}
});
</script>

</html>

3.vue对象

new Vue({

​ el:’’ // 该对象绑定在哪个div上

​ data:{

​ } // 提供数据,里面存放键值对

})

二.差(插)值表达式

差值表达式是用在html被绑定的元素中的。目的是通过差值表达式来获取vue对象中的属性和方法。

插值表达式不能作为html标签中的属性的值,转到v-bind

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
<body>
<div id="app">
<!-- vue对象中的data -->
我是一位{{major}}程序员
<!-- 数组 -->
{{[0,1,2,3,4][3]}}<br />
{{ {name:'jens', age:20}.name }}
<!-- vue对象中的methods -->
{{ sayHi() }}
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
major: 'java'
},
methods: {
sayHi: function () {
alert('Hello')
}
}
})
</script>

三.vue关键字

1.v-model:双向数据绑定

将标签中的value值与vue实例中的data属性值进行绑定

1
2
3
4
5
6
7
8
9
10
11
12
13
<div id='app'>
请输入你的专业:<input type='text' v-model='major' /><br>
==============================<br>
我是一位{{major}}程序员
</div>


new Vue({
el: '#app',
data: {
major: 'java'
}
})

2.v-on:事件绑定

通过配合具体的事件名来触发绑定的vue实例中的函数

v-on:事件名=’函数名()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<div id='app'>
请输入你的专业:<input type='text' v-on:input="changeMajor" /><br>
</div>

new Vue({
el: '#app',
data: {
major: 'java'
},
methods: {
sayHi: function () {
alert('Hello')
},
changeMajor: function () {
console.log('changed')
}
}
})

event 内置参数对象

event.target.value

在响应函数中,可以指明使用event作为参数,该对象表示当前事件,可以通过event.target.value来获得当前事件对象的value的值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<input type='text' v-on:input="changeMajor" />

new Vue({
el: '#app',
data: {
major: 'java'
},
methods: {
changeMajor: function (event) {
// 效果为在input标签中输入后动态改变major的值
this.major = event.target.value
}
}
})

this的用法

this表示当前vue对象,可以通过this来调用当前对象的属性和方法

v-on的简写 @

v-on:input=”” ==> @input=””

3.v-bind:属性绑定

<… v-bind:属性名=”vue中的键名“ …>

1
2
3
4
5
6
7
8
<a v-bind:href="link">百度</a>

new Vue({
el: '#app',
data: {
link: 'https:/www.baidu.com'
}
})
v-bind 简写 :
1
<a v-bind:href="link">百度</a> ===>  <a :href='link'>

4.v-once

指明该标签中的差值表达式只获取一次数据。之后的数据变化不影响该表达式的值。

1
2
3
4
<p v-once>
{{link}}
</p>
<input type="text" v-model="link">

5.v-html 和 v-text

v-html会将vue中的属性的值作为html的元素来使用

v-text会将vue中的属性的值只作为纯文本来使用

1
<span v-html='mylink'></span><span v-text='mylink'></span>new Vue({        el: '#app',        data: {            link: 'https:/www.baidu.com',            mylink: '<a href="https:/www.baidu.com">baidu</a>'        }    })

image-20210405154551206

四.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
<div id="app">
{{ count > 10 ? '大于10' : '小于10' }}<br>
{{count}}<br>
<button type="button" @click="addbtn()">增加</button>
<button type="button" @click="relsbtn()">减少</button>
<input type="text" v-model="mystep" />
<br>
<p @mousemove="mymo">
{{x}}<br>
{{y}}
<!-- <span @mousemove="mystopmo">停止鼠标移动事件</span> -->
<span @mousemove.stop>停止鼠标移动事件</span>
</p>
</div>


new Vue({
el: '#app',
data: {
count: 0,
mystep: 1,
x: 0,
y: 0
},
methods: {
addbtn: function () {
this.count += this.mystep - 0
},
relsbtn: function () {
this.count -= this.mystep - 0
},
mymo: function (event) {
this.x = event.clientX
this.y = event.clientY
console.log(event)
},
mystopmo: function (event) {
event.stopPropagation()
}
}
})

事件修饰符

在事件处理程序中调用 event.preventDefault()event.stopPropagation() 是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。

为了解决这个问题,Vue.js 为 v-on 提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。

  • .stop
  • .prevent
  • .capture
  • .self
  • .once
  • .passive
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<!-- 阻止单击事件继续传播 -->
<a v-on:click.stop="doThis"></a>

<!-- 提交事件不再重载页面 -->
<form v-on:submit.prevent="onSubmit"></form>

<!-- 修饰符可以串联 -->
<a v-on:click.stop.prevent="doThat"></a>

<!-- 只有修饰符 -->
<form v-on:submit.prevent></form>

<!-- 添加事件监听器时使用事件捕获模式 -->
<!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 -->
<div v-on:click.capture="doThis">...</div>

<!-- 只当在 event.target 是当前元素自身时触发处理函数 -->
<!-- 即事件不是从内部元素触发的 -->
<div v-on:click.self="doThat">...</div>

按键修饰符

在监听键盘事件时,我们经常需要检查详细的按键。Vue 允许为 v-on 在监听键盘事件时添加按键修饰符:

1
<!-- 只有在 `key` 是 `Enter` 时调用 `vm.submit()` --><input v-on:keyup.enter="submit">

你可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。

1
<input v-on:keyup.page-down="onPageDown">

在上述示例中,处理函数只会在 $event.key 等于 PageDown 时被调用。

五.Vue改变内容

差值表达式

1
<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><body>    <div id="app">        {{count}}<br>        {{result}}<br>        <button type="button" @click="addbtn(2)">增加</button>    </div></body><script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script><script>    new Vue({        el: '#app',        data: {            count: 0,            result: "?"        },        methods: {            addbtn: function (step) {                this.count += step                this.result = this.count > 10 ? "大于10" : "小于10"            }        }    })</script></html>

computed 计算属性

什么是计算属性

计算属性是一个属性,其次,这个属性有计算的能力,这里计算的方式为函数;具体来说,他就是一个将函数结果缓存起来的属性。

计算属性与方法的区别

计算属性更像是一个data,是静态的结果;方法是一个函数,是动态的

1
<div id='app'>	{{getCurrentTime()}}<br>	{{getCurrentTime1}}</div>new Vue({	el: '#app',	methods: {		getCurrentTime: function () {			return new Date()		}	},	computed: {		getCurrentTime1: function () {			return new Date()		}	}	})

watch 监控属性

通过在watch里给属性绑定函数,当属性的值发生变化时,该函数就会被调用。调用时可以接收两个参数,第一个参数是属性改变后的值,第二个参数是属性改变前的值

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='app'>
{{title}}
<input type="text" v-model="title">
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
new Vue(
{
el: '#app',
data: {
title: "hello"
},
watch: {
title: function (newValue, oldValue) {
console.log("title changed")
console.log(newValue + '::' + oldValue)
}
}
})
</script>

六.Vue 改变样式

1.class的动态绑定

通过给html元素的class属性绑定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
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<title>Title</title>
<style>
.mydiv {
width: 400px;
height: 220px;
background-color: gray;
}
.red {
background-color: red;
}
.yellow {
background-color: yellow;
}
.green {
background-color: green;
}
</style>
</head>
<body>
<div id="app">
<div class="mydiv" v-bind:class="{red:temp}"></div>
<div class="mydiv"></div>
<div class="mydiv"></div>
<br />
<button type="button" @click="temp=!temp">点击</button>
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
new Vue({ el: "#app", data: { temp: false } });
</script>
</html>

2.加入computed

通过computed返回一个json对象,对象里放着多个键值对

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
<body>
<div id='app'>
<div class="mydiv" v-bind:class="{red:temp}"></div>
<hr>
<div :class="myClassStyle" class="mydiv"></div>
<hr>
<div class="mydiv"></div><br>
<button type="button" @click="temp=!temp">点击</button>
</div>

</body>

<script>
new Vue({
el: '#app',
data: {
temp: false
},
computed: {
myClassStyle: function () {
return {
red: this.temp,
myWidth: this.temp
}
}
}
})
</script>

3.通过v-model来改变样式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<div :class="mycolor" class="mydiv"></div><br>
<input type="text" v-model="mycolor">

<script>
new Vue({
el: '#app',
data: {
temp: false,
mycolor: 'green'
},
computed: {
myClassStyle: function () {
return {
red: this.temp,
myWidth: this.temp
}
}
}
})
</script>

4.使用v-model绑定多个样式

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
<style>
.red {
background-color: red;
}

.myWidth {
width: 450px;
}
</style>

<body>

<div :class="[mycolor,mywidth]" class="mydiv"></div>
</body>

<script>
new Vue({
el: '#app',
data: {
temp: false,
mycolor: 'green',
mywidth: 'myWidth',
},
})
</script>

5.在内嵌的css样式绑定Vue的键

style引用了Vue中的内容,因此是一个键值对,所以需要大括号;js中对象的键是不能出现”backgroud-color“这种形式的,应该改成backgroundColor

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<!-- 在内嵌的css样式绑定Vue的键 -->
<div :style="{backgroundColor: mycolor}" class="mydiv"></div>
<hr />
<div :style="myStyle" class="mydiv"></div>
<hr />
<div :style="[myStyle,{height:mw*2+'px'}]" class="mydiv"></div>
<script>
new Vue({
el: "#app",
data: { temp: false, mycolor: "green", mywidth: "myWidth", mw: 450 },
computed: {
myClassStyle: function () {
return { red: this.temp, myWidth: this.temp };
},
myStyle: function () {
return { backgroundColor: this.mycolor, width: this.mw * 2 + "px" };
},
},
});
</script>

七.Vue中的语句

1.分支语句

  • v-if
  • v-else-if
  • v-else
  • v-show : 实际上是让该元素的display属性为none,起到隐藏的效果。所以性能更好。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<body>
<div id="app">
<div v-if="temp">if</div>
<div v-else-if="temp1">else-if</div>
<!-- 此时temp2的bool值对是否显示else没有影响,只与temp和temp1的值有关 -->
<div v-else="temp2">else</div>
<button type="button" @click="temp=!temp">点我</button>
</div>
</body>

<script>
new Vue({
el: '#app',
data: {
temp: false,
temp1: false,
temp2: true,
}
})
</script>

2.循环语句

  • v-for

首先定义数据源,然后通过v-for遍历数据源,再通过差值表达式输出数据

只取值的for:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<body>
<div id="app">
<ul>
<li v-for="a in args">
{{a}}
</li>
</ul>
</div>
</body>

<script>
new Vue({
el: '#app',
data: {
args: [1, 2, 3, 4, 5, 6],
}
})
</script>
带索引的for:

v-for=”(value,key,index) in object”

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<body>
<div id="app">
<!-- 带索引的for -->
<ul>
<li v-for="(a,i) in args" :key="i">{{i}}--{{a}}</li>
</ul>
</div>
</body>

<script>
new Vue({
el: '#app',
data: {
args: [1, 2, 3, 4, 5, 6],
}
})
</script>
遍历对象:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<body>
<div id="app">
<!-- 遍历对象 -->
<ul>
<li v-for="(value,key,index) in student">{{index}}--{{key}}--{{value}}</li>
</ul>
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
args: [1, 2, 3, 4, 5, 6],
student: {
name: 'xiaoming',
age: 20
}
}
})
</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
<body>
<div id="app">
<!-- 遍历对象数组 -->
<ul>
<li v-for="student in students">
<span v-for="(value,key,index) in student">{{index}}--{{key}}--{{value}}----</span>
</li>
</ul>
</div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
new Vue({
el: '#app',
data: {
args: [1, 2, 3, 4, 5, 6],
students: [{
name: 'xiaoming',
age: 20
},
{
name: 'xiaowang',
age: 18
}]
}
})
</script>

Vue进阶

1.基础开发

一.Vue实例

1.Vue对象操作

1.可以通过一个Vue对象操作另一个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
<script>
var v2 = new Vue({
el: '#app2',
methods: {
changeOtherVueTitle: function () {
v1.title = "Hello Vue"
},
m1: function () {
v1.toUpCase()
}
},
});

var v1 = new Vue({
el: '#app1',
data: {
title: "hello"
},
methods: {
toUpCase: function () {
this.title = this.title.toUpperCase()
}
},
computed: {
toLowerCase: function () {
return this.title.toLowerCase()
}
},
watch: {
title: function (n, o) {
console.log(n + ':' + o)
}
}

});
</script>
2.Vue对象操作另一个Vue对象的内容,维度有两个,操作属性、操作方法
3.Vue的实例属性

直接通过“对象.属性”的方式调用的属性,是来自于data或computed中的属性,但是Vue对象中的el,data等等这些键也称为属性,这些属性就是Vue对象中的实例属性。

  • 设置实例属性
1
var data = { arg1: "arg1 value"}var v2 = new Vue({ el: "#app", data: data,})
  • 实例属性还能这么调用:v1.$data.title 相当于v1.title

2.实例属性 ref

在Vue中往往使用ref属性来代替id属性的使用。那么就可以快速的通过调用ref的值来获得页面中的某个元素。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<body>
<div id="app2">
<button type="button" ref="mybtn1" @click="showVueObject">点击</button>
<button type="button" ref="mybtn2" @click="showVueObject">点击</button>
</div>
</body>
<script>
var v2 = new Vue({
el: "#app2",
methods: {
showVueObject: function () {
this.$refs.mybtn1.innerHTML = "hello";
},
},
});
</script>

3.动态绑定Vue实例到页面中

​ 实现了页面元素和Vue对象的动态绑定,之前都是通过el的方式来绑定;也可以通过mount实例属性进行绑定

1
2
3
4
5
6
7
8
9
<body>
<div id="app"></div>
</body>
<script>
var v1 = new Vue({
template: "<h1>hello</h1>",
});
v1.$mount("#app");
</script>

二.Vue组件

1.Vue组件

组件化:可以将Vue对象作为一个组件,反复使用

​ 要想实现组件化,需要在页面中注册组件:关于注册的方式有两种,分别是全局注册和本地注册

1.注册组件(全局注册)
1
Vue.component("组件名",{vue对象})
2.使用组件

​ 在被Vue绑定了的html元素中才能使用组件。如果一个div没有被绑Vue绑定,那么这个div中不能使用之前注册组件

1
2
3
4
5
6
7
<body>
<div id="app"><model1></model1></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
Vue.component("model1", { template: "<div>{{title}}<button type='button' @click='btnfn'>点击</button></div>", data: function () { return { title: "hello" } }, methods: { btnfn: function () { alert("hello") } } }) new Vue({ el: "#app", })
</script>
3.作为组件的Vue对象的特点
特点1

Vue.component("组件名",{vue对象}),这个Vue对象和之前的Vue对象是有的data实例属性的写法是有区别的

单独的Vue对象 $\Downarrow$

1
new Vue({	data:{		name:"xm",		age:29}})

作为组件的Vue对象 $\Downarrow$

1
{	data: function(){		return{			name:"xm",			age:29		}	}}
特点2

这种组件中template的写法

template是将内容展现在页面上的一个键,他的值是一个字符串

注意:template里必须有且只能有一个根元素

1
template: "<div>{{title}}<button type='button' @click='btnfn'>点击</button></div>"

2.Vue的生命周期

3.Vue组件的本地(局部)注册

vue的组件全局注册后,在html页面的每一个被Vue绑定的div中都能使用

vue的组件本地注册后,只能在对应vue实例绑定的div中使用

1
2
3
4
5
6
7
8
9
<body>
<div id="app"><model11></model11></div>
<hr />
<div id="app1"><model2></model2></div>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.js"></script>
<script>
var model1 = { template: "<div>{{title}}<button type='button' @click='btnfn'>点击</button></div>", data: function () { return { title: "hello" } }, methods: { btnfn: function () { alert("hello") } } } new Vue({ el: "#app", components: { "model11": model1 } }) new Vue({ el: "#app1", components: { "model2": model1 } })
</script>

三.Vue开发模式

1.vue-cli脚手架

2.vue文件的组成

  • template
  • script
  • 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
<template>
<div id="app">
<img src="./assets/logo.png" />
<h1>{{ msg }}</h1>
<h2>Essential Links</h2>
<ul>
<li><a href="https://vuejs.org" target="_blank">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank">Forum</a></li>
<li>
<a href="https://chat.vuejs.org" target="_blank">Community Chat</a>
</li>
<li><a href="https://twitter.com/vuejs" target="_blank">Twitter</a></li>
</ul>
<h2>Ecosystem</h2>
<ul>
<li><a href="http://router.vuejs.org/" target="_blank">vue-router</a></li>
<li><a href="http://vuex.vuejs.org/" target="_blank">vuex</a></li>
<li>
<a href="http://vue-loader.vuejs.org/" target="_blank">vue-loader</a>
</li>
<li>
<a href="https://github.com/vuejs/awesome-vue" target="_blank"
>awesome-vue</a
>
</li>
</ul>
</div></template
>
<script>
export default {
name: "app",
data() {
return { msg: "Welcome to Your Vue.js App" };
},
};
</script>
<style lang="scss">
app {
font-family: "Avenir", Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1,
h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
1.在App.vue组件中使用另一个vue组件
1) 全局注册

在main.js中,通过import和Vue.component配合,来将一个.vue文件注册成为一个标签。该标签可以在整个项目中使用

1
2
3
4
import Header from './components/Header.vue'import Content from
'./components/Content.vue'import bottom from
'./components/bottom'Vue.component('MyHeader', Header)Vue.component("MyContent",
Content)Vue.component("MuBottom", bottom)
2) 本地注册

在组件的内部去注册另外一个组件,成为一个标签,这个标签只在该组件的内部使用,而不能在其他组件内使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
<template>
<div id="app">
<Myheader></Myheader> <MyContent></MyContent> <MyBottom></MyBottom></div
></template>
<script>
import Header from "./components/Header"
import Content from "./components/Content" import Bottom from "./components/bottom"
export default {
name: 'app',
components: {
"Myheader": Header,
"MyContent": Content,
"MyBottom": Bottom
}
}
</script>

2.各组件之间的参数传递

1.父传子

​ 通过子组件的props,来指明可以接收的参数,父组件通过在标签中写明参数的键值对来传递参数

props写法

  1. props:[参数列表]

    props:[‘MyProps1’,’MyProps2’,…]

  2. props:{参数对象}

    props: {

    ​ ‘MyProps1’:{ // 参数名

    ​ type:String, // 类型

    ​ required:true, // 是否是必须传递的参数

    ​ default:’…’ // 默认值

    ​ },

    ​ …

    }

子组件设参props

1
<script>    export default {        name: "Content",        props: ["MyTitle"]    }</script>

父组件使用子组件并传参

1
<MyContent :MyTitle="msg"></Mycontent>
2.子传父
  1. image-20210409213825418

  2. 以事件发射的方式来实现子传父的效果

在子组件中,使用this.$emit("键","值)

在父组件中,在子组件的标签中使用@键="msg=$event" 其中$event就能得到发射的值,msg是父组件中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
<template>
<div id="app">
<MyContent :MyTitle="msg" @newName="msg=$event"></Mycontent>
</div>
</template>

<script>
import Content from "./components/Content"
export default {
name: 'app',
data() {
return {
msg: "Hello vue"
}
},
components: {
"MyContent": Content
},
methods: {
FCfn: function (m) {
this.msg = m
}
}
}
</script>

<style>

</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
<template>
<div>
商品列表
{{MyTitle}}

<button type="button" @click="doClick">点击</button>
</div>
</template>

<script>
export default {
name: "Content",
props: {
'MyTitle': {
type: String,
required: true,
default: 'xx'
}
},
methods: {
doClick() {
this.$emit('newName', 'hello, js');
}
}
}
</script>

<style>

</style>

四.Vue中发送Ajax请求

1) 安装axios vue-axios
1
2
npm install --save axios vue-axios
npm install
2) 在main.js中引入
1
2
3
4
import axios from 'axios'
import VueAxios from 'vue-axios'

Vue.use(VueAxios, axios)
3) 发送ajax请求
  1. 发送get请求
1
2
3
4
5
6
7
this.axios({
method: 'get',
url: 'http://localhost:8090/regist?mail='+this.mail+'&password='+this.password
})
.then(function(response){
console.log(response.data)
})
  1. 发送post请求
1
2
3
4
5
6
7
8
9
10
11
this.axios({
method: 'post',
url: 'http://localhost:8090/regist',
data:{
mail: this.mail,
password: this.password
}
})
.then(function(response){
console.log(response.data)
})
4) 解决跨域问题

跨域是浏览器对javascript的一种安全限制,浏览器的页面去访问其他服务器上的资源时,就会出现跨域。同源策略,指的是协议、域名、端口完全相同才是安全的

在spring-mvc.xml中加入如下代码

1
2
3
4
5
6
7
<mvc:cors>
<mvc:mapping path="/**"
allowed-origins="http://domain1.com,http://domain2.com"
allowed-methods="GET, PUT, OPTIONS, DELETE, PUT, PUSH"
allowed-headers="Content-Type, Access-Control-Allow-Headers, Authorization, X-Requested-With"
allow-credentials="true" />
</mvc:cors>
在spring-web项目中的解决办法

在注解为@SpringBootConfiguration的config文件中重写addCorsMappings方法

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
// 数据库课设rpm项目的config如下
// src/main/java/edu/dhu/rpm/config/MyWebConfigurer.java


@SpringBootConfiguration
public class MyWebConfigurer implements WebMvcConfigurer {

@Bean
public LoginInterceptor getLoginInterceptor() {
return new LoginInterceptor();
}

@Override
public void addInterceptors(InterceptorRegistry registry){
registry.addInterceptor(getLoginInterceptor()).addPathPatterns("/**").excludePathPatterns("/index.html");
}

@Override
public void addCorsMappings(CorsRegistry registry) {
//所有请求都允许跨域
registry.addMapping("/**")
.allowedOrigins("*")
.allowedMethods("*")
.allowedHeaders("*");
}
}
5) 解决axios无法传递data中的参数问题

原因:默认情况下发送axios时请求头中的内容类型为:

1
Content-Type:application/json;charset=UTF-8

而实际服务端需要的是:

1
Content-Type:application/x-www-form-urlencoded

因此,使用axios的qs内置库中的方法进行内容类型的转换

1
2
3
4
5
6
7
8
9
import Qs from 'qs'

this.axios({
method:'post',
url:'http://locahost:8080/Login',
transformRequest:[function(data){
return Qs.stringify(data)
}],
})
6) 路由

在Vue中的路由,能够在一个Vue组件中实现其他组件的切换

也就是说,可以通过路由模块,将指定的组件显示在路由视图中。

1.安装路由模块
1
npm install vue-router -s
2.设计路由界面

创建components文件夹,文件夹内分别创建user、Home组件

  • user.vue
1
2
3
4
5
<template>
<div>
user
</div>
</template>
  • Home.vue
1
2
3
4
5
<template>
<div>
Home
</div>
</template>
3.创建静态路由表

在src下创建routes.js

1
2
3
4
5
6
7
import Home from '@/components/Home.vue'
import User from '@/components/user/user.vue'

export const routes = [
{path:'/', component:Home},
{path:'/user', component:User}
]
4.引入路由模块并使用

在main.js中引入路由模块并使用

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import Vue from 'vue'
import App from './App.vue'
import VueRouter from 'vue-router' //1.引入路由模块
import {routes} from './routes' //2.引入静态路由表

Vue.use(VueRouter); //3.使用路由模块

// 4.创建一个VueRouter模块的实例
const router = new VueRouter({
routes:routes
})

new Vue({
el: '#app',
router, //5.把router实例放入到vue实例中
render: h => h(App)
})
5.使用
  • App.vue
1
2
3
4
5
6
7
8
9
10
<template>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8">
<h1>Routing</h1>
<router-view></router-view>
</div>
</div>
</div>
</template>

改变url,发现<router-view></router-view>中的内容发生改变

向router实例中添加mode属性

  • “hash”: url带# 适用于调试模式
  • “history”: url不带#
6.链接路由的实现

创建Header.vue

1
2
3
4
5
6
<template>
<ul class="nav nav-pills">
<router-link to="/" tag="li" active-class="active" exact><a>Home</a></router-link>
<router-link to="/user" tag="li" active-class="active"><a>User</a></router-link>
</ul>
</template>

修改App.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<template>
<div class="container">
<div class="row">
<div class="col-xs-12 col-sm-8">
<h1>Routing</h1>
<Home></Home>
<router-view></router-view>
</div>
</div>
</div>
</template>
<script>
import Home from './components/Header.vue'
export default{
components:{'Home':Home}
}
</script>

e.g.

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 id="app">
<div class="container">
<div class="row">
<ul class="nav nav-tabs">
<li role="presentation">
<router-link to="/Home">首页</router-link>
</li>
<li role="presentation">
<router-link to="/Products">商品列表</router-link>
</li>
</ul>
</div>
<div class="row" id="rv">
<router-view></router-view>
</div>
</div>
</div>
</template>

<script>

export default {
name: 'app',
data() {
return {

}
},

}
</script>

<style>
#rv {
border: 1px soid red;
}
</style>
7.路由之间的参数传递

Header.vue传入参数

1
2
3
4
5
6
<template>
<ul class="nav nav-pills">
<router-link to="/" tag="li" active-class="active" exact><a>Home</a></router-link>
<router-link to="/user/10" tag="li" active-class="active"><a>User</a></router-link>
</ul>
</template>

路由表:router.js

1
2
3
4
export const routes = [
{path:'/', component:Home},
{path:'/user/:id', component:User}
]

修改user.vue

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
<div>
<div>user</div>
<p>userId:{{id}}</p>
</div>
</template>
<script>
export default{
data(){
return{
id:this.$route.params.id
}
}
}
</script>
  • 设参:

    通过路由表设置路由参数

    1
    2
    3
    4
    {
    path: "/Products/:id",
    component: Products
    }
  • 传参:

    通过router-link的to访问路径时携带参数

    1
    2
    3
    <li role="presentation">
    <router-link to="/Products/1">手机</router-link>
    </li>
  • 接参:

    在目标vue中,通过vue中的$route.params.my_param_name

    1
    2
    3
    4
    5
    6
    7
    8
    export default {
    name: "Products",
    data() {
    return {
    id: this.$route.params.id
    };
    },
    }
设置子路由并监听可以刷新同一父路由下的参数值的变化
6) 路由之间跳转的方式

通过HTML中的路由链接<router-link to="路由地址">进行跳转

1
2
3
<li role="presentation">
<router-link to="/Products/1">手机</router-link>
</li>
2.通过js实现路由跳转

this.$router.push("/Products/1")

1
2
3
4
5
6
7
8
9
10
11
12
<tempate>
...
<button type="button" @click="btnfn">点击</button>
...
</template>
...

methods: {
btnfn() {
this.$router.push("/Products/1")
}
}
7.scoped:Vue中组件样式表的作用范围

​ 如果vue组件中的style标签没有带上scoped属性,那么这个style的样式将会作用在整个页面中,而不是当前子组件中

8.资源打包

dist目录

五. webpack

1.创建工程
1
2
3
4
5
6
7
8
9
10
11
npm init webpack myvuedemo

? Project name myvuedemo
? Project description A Vue.js project
? Author Jens <1587198543@qq.com>
? Vue build standalone
? Install vue-router? No
? Use ESLint to lint your code? No
? Set up unit tests No
? Setup e2e tests with Nightwatch? No
? Should we run `npm install` for you after the project has been created? (recommended) no
2.安装依赖

需要vue-routerelement-uiaxiossass-loadernode-sass四个插件

1
2
3
4
5
npm install vue-router --save-dev
npm i element-ui -S
npm install --save axios vue-axios
npm install sass-loader node-sass --save-dev
npm install //安装依赖
3.配置路由
1)创建路由表

在src下创建router文件夹,里面创建index.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import VueRouter from 'vue-router'

import Login from '../views/Login.vue'

Vue.use(VueRouter);

export default new VueRouter({
routes: [
{
path: '/Login',
name: 'Login',
component: Login
}
]
})
2)在main.js中配置路由表
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import Vue from 'vue'
import App from './App'
import VueRouter from 'vue-router'

import router from './router'

Vue.use(VueRouter)

Vue.config.productionTip = false

new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
3)在App.vue中创建路由视图
1
2
3
4
5
<template>
<div id="app">
<router-view></router-view>
</div>
</template>
4)在项目中使用element-ui

官方指南

完整引入

在 main.js 中写入以下内容:

1
2
3
4
5
6
7
8
9
10
11
import Vue from 'vue';
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue';

Vue.use(ElementUI);

new Vue({
el: '#app',
render: h => h(App)
});

以上代码便完成了 Element 的引入。需要注意的是,样式文件需要单独引入。

五.嵌套路由(子路由)

在路由显示的组件内部,又嵌套着路由,称为子路由

1.配置路由表

修改路由js文件,在对应父路由下添加children

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
import Vue from 'vue'
import VueRouter from 'vue-router'

import Login from '../views/Login.vue'
import Home from '../views/Home.vue'
import ProductList from '.......'
Vue.use(VueRouter);

export default new VueRouter({
routes: [
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/Home',
name: 'Home',
component: Home,
children:[
{
path: '/productlist',
name: 'Productlist',
component: ProductList
}
]
}
]
})

2.使用嵌套路由

1
<router-link to="/productlist">商品列表</router-link>

六.路由的重定向

直接调用另一个已配置好的路由对象即可

1
2
3
4
5
6
7
8
9
10
11
routes: [
{
path: '/Login',
name: 'Login',
component: Login
},
{
path: '/Logout',
redirect: '/Login'
}
]

七.传参的两种方式

`

image-20210411133323363

路由钩子 router hook

  • beforeRouteEnter :在进入路由前执行
  • beforeRouteLeave:在离开路由前执行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
export default{
props: ['id'],
name: "UserProfile",
beforeRouteEnter: (to, from, next) => {
console.log("准备进入个人信息页")
next(
console.log("进入到目标页面之后调用的函数")
)
},
beforeRouteLeave: (to, from, next) => {
console.log("准备离开个人信息页")
next()
}
}

八.Mock数据

easy mock官方网站已下线

2.vue-element-admin

1.路由和侧边栏

整个项目的侧边栏是通过路由表动态生成的,可以调整路由表中的内容来改变侧边栏的内容

具体参考官方文档

官方文档

1) 改变侧边栏标题

修改src/router/index.js,

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
path: '/example',
component: Layout,
redirect: '/example/table',
name: 'Example',
meta: { title: 'Example', icon: 'el-icon-s-help' },
children: [
{
path: 'table',
name: 'Table',
component: () => import('@/views/table/index'),
meta: { title: 'Table', icon: 'table' } // 此处对应侧边栏的标题和图标
},
{
path: 'tree',
name: 'Tree',
component: () => import('@/views/tree/index'),
meta: { title: 'Tree', icon: 'tree' }
}
]
},

Vue笔记
https://jenscc.github.io/2021/07/03/Vue笔记/
作者
Jens
发布于
2021年7月3日
许可协议