My_Study_Vuejs’s 学习笔记¶
邂逅vue¶
安装Vue¶
安装方式比较多
cdn引入¶
cdn方式推荐代码部署在服务器上面的比较好, 让用户可以使用cdn技术快速访问到文件。
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.vue"></script>
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
cli和npm结合¶
后续通过webpack和CLI的使用,我们使用该方式。
体验vue¶
hello vue¶
通过简单的hello 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>
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h2> {{ message }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
"message": "123"
}
})
</script>
</body>
</html>
|
可以在浏览器进行数据修改,然后自动页面修改。

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 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
<ul>
<li v-for="zoom in zooms ">
{{ zoom }}
</li>
</ul>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
zooms: ["dog","cat","panda"]
}
})
</script>
</body>
</html>
|
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>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
<h2>{{ cnt }}</h2>
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
cnt:1,
},
methods:{
add: function (){
this.cnt+=1
},
sub: function(){
this.cnt-=1
}
}
})
</script>
</body>
</html>
|
mvvm架构¶
mvvm 是model view view model 的合称。
data和vue对象的分离¶
vue中的mvvm¶

- View层:
视图层 在我们前端开发中,通常就是DOM层。 主要的作用是给用户展示各种信息。
- Model层:
数据层 数据可能是我们固定的死数据,更多的是来自我们服务器,从网络上请求下来的数据。 在我们计数器的案例中,就是后面抽取出来的obj,当然,里面的数据可能没有这么简单。
- VueModel层:
视图模型层 视图模型层是View和Model沟通的桥梁。 一方面它实现了Data Binding,也就是数据绑定,将Model的改变实时的反应到View中 另一方面它实现了DOM Listener,也就是DOM监听,当DOM发生一些事件(点击、滚动、touch等)时,可以监听到,并在需要的情况下改变对应的Data
vue的options¶
vue的options有很多
主要的有以下几个
el: 决定vue实例管理哪个dom。
data: vue实例对应的数据对象。
methods: 定义方法,方便其他地方调用。
mvvm生命周期¶

基础语法¶
插值操作¶
通过插值操作可以完成vue对象的数据,填充到html中去。
<h2> {{ message }} </h2>
v-once¶
可以完成vue仅仅一次的数据绑定,后续的数据修改不在同步页面。
v-html¶
可以将数据中的html内容,以html展示到页面上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-html directive: <span v-html="rawHtml"></span></p>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
rawHtml: '<span style="color:red"> this should be red</span>'
}
})
</script>
</body>
</html>
|
v-text¶
可以将数据中的html内容,以text展示到页面上。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<p>Using mustaches: {{ rawHtml }}</p>
<p>Using v-text directive: <span v-text="rawHtml"></span></p>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
rawHtml: '<span style="color:red"> this should be red</span>'
}
})
</script>
</body>
</html>
|
v-pre¶
用于跳过这个元素和他子元素的编译过程,用于展示原本内容。
v-cloak¶
某些情况下 ,浏览器可能会直接展示未编译的mustache标签。 通过此可以不展示这些信息。
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 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
[v-cloak] {
display: none ;
}
</style>
</head>
<body>
<div id="app" v-cloak>
<h2 >{{ cnt }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
setTimeout(function(){
let app = new Vue({
el: "#app",
data: {
cnt: 1,
}
})},3000)
</script>
</body>
</html>
|
绑定属性¶
v-bind可以绑定属性。
绑定基本使用¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<img :src="srcUrl" alt="">
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
srcUrl: "https://i1.hdslb.com/bfs/face/c850c18ae6b507d0ef34837f53a51090b6a7451f.jpg@96w_96h_1c.webp"
}
})
</script>
</body>
</html>
|
动态绑定class¶
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 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.active{
color: red;
}
.line{
background-color: blue;
}
</style>
</head>
<body>
<div id="app">
<h2 v-bind:class="getClass()">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
message: "panda",
isActive: true,
isLine: true
},
methods:{
getClass: function(){
return {active:this.isActive,line:this.isLine}
}
}
})
</script>
</body>
</html>
|
动态绑定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 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.active{
color: red;
}
.line{
background-color: blue;
}
</style>
</head>
<body>
<div id="app">
<h2 v-bind:style="{fontSize: messageFontSize}">{{message}}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
message: "panda",
messageFontSize: "100px",
},
methods:{
}
})
</script>
</body>
</html>
|
v-for和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 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
.active{
color: red;
}
.line{
background-color: blue;
}
</style>
</head>
<body>
<div id="app">
<ul>
<li v-for="(zoom,index) in zooms">
<p v-bind:class="{active: curentIndex==index}" @click="ChangeClass($event,index)"> {{index }} - {{ zoom }} </p>
</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
zooms: ['cat','dog','pig'],
curentIndex:0,
isActive: false
},
methods:{
ChangeClass: function (event,index){
this.curentIndex =index
}
}
})
</script>
</body>
</html>
|
计算属性¶
可以根据已有的属性生成其他属性。
基本使用¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>{{ fullName }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
firstName: "jie di",
secondName: "zhao",
},
computed:{
fullName: function (){
return this.secondName + " " + this.firstName
}
}
})
</script>
</body>
</html>
|
复杂使用¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>{{ totalPrice }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
books: [
{id:1,name:'abc',price:100},
{id:2,name:'abc',price:101},
{id:3,name:'abc',price:102},
{id:4,name:'abc',price:103},
]
},
computed:{
totalPrice: function (){
let result=0
// for (let i=0; i< this.books.length; i++){
// result +=this.books[i].price
// }
for (let book of this.books){
result += book.price
}
return result
}
}
})
</script>
</body>
</html>
|
getter和setter¶
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 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<h2>{{ fullName }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
firstName: "jiedi",
secondName: "zhao",
},
computed:{
// fullName: function(){
// return this.firstName+ this.secondName
// },
fullName: {
get: function (){
return this.firstName + " " + this.secondName
},
set: function (newValue){
const names = newValue.split(" ")
this.firstName = names[0]
this.secondName =names[1]
}
}
}
})
</script>
</body>
</html>
|

计算属性和methods的对比¶
计算属性是缓存的, 方法是不缓存的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ fullName }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
<h2>{{ getFullName() }}</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
firstName: "jie di",
secondName: "zhao",
},
methods:{
getFullName: function(){
console.log("------getFullName------")
return this.secondName + " " + this.firstName
},
},
computed: {
fullName: function () {
console.log("------fullName------")
return this.secondName + " " + this.firstName
}
}
})
</script>
</body>
</html>
|

事件监听¶
事件监听用于在用户点击、拖拽等场景。
监听基本使用¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | <!doctype html>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<script src="../js/vue.js"></script>
<div id="app">
<h2>{{ cnt }}</h2>
<button @click="add">+</button>
<button @click="sub">-</button>
</div>
<script>
let app = new Vue({
el: "#app",
data: {
cnt:1,
},
methods:{
add: function (){
this.cnt+=1
console.log("-----add-------" )
},
sub: function(){
this.cnt-=1
console.log("-----sub-------" )
}
}
})
</script>
</body>
</html>
|
参数传递¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button @click="bntClick">按钮1</button>
<button @click="bntClick2(12,$event)">按钮2</button>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
cnt: 1,
},
methods:{
bntClick(event){
console.log(event)
},
bntClick2(abc,event){
console.log("第一个参数:" + abc)
console.log("第二个参数:" + event)
},
}
})
</script>
</body>
</html>
|

修饰符¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<div @click="divClick">
<button @click.stop="btnClick">button1</button>
</div>
<!-- <div @click="divClick">-->
<!-- <button @click="btnClick">button1</button>-->
<!-- </div>-->
<form action="baidu">
<input type="submit" value="提交" @click.prevent="submitClick">
</form>
<input type="text" value="提交2" @keyup.enter="keyup">
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
},
methods:{
btnClick(){
console.log("btn click")
},
divClick(){
console.log("div click")
},
submitClick(){
console.log("div click")
},
keyup(){
console.log("key up")
}
}
})
</script>
</body>
</html>
|

条件判断¶
v-if¶
简单的判定
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 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- <h2 v-if="isShow">{{ cnt }}</h2>-->
<h2 v-if="isShow">
<div>abc</div>
<div>abc</div>
<div>abc</div>
{{ message }}
</h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
isShow: true,
message: "abc",
}
})
</script>
</body>
</html>
|
v-else-if¶
稍微复杂的判定
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 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<h2 v-if="score>90">优秀 </h2>
<h2 v-else-if="score>80">良好</h2>
<h2 v-else-if="score>60">及格 </h2>
<h2 v-else> 不及格</h2>
<br>
<br>
<br>
<h2 > {{result}} </h2>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
score: 80
},
computed:{
result(){
let message=''
if (this.score >90){
message ="优秀"
}
else if (this.score >80){
message="良好"
}
else if (this.score >60){
message="及格"
}
else {
message = "不及格"
}
return message
},
}
})
</script>
</body>
</html>
|
用户登录案例¶
进行一个用户登录切换的案例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<span v-if="currentType == 'username'">用户名</span>
<span v-if="currentType == 'email'">用户邮箱</span>
<input type="text"> </input>
<button @click="btnClick"> 切登录方式</button>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
currentType: "username",
},
methods:{
btnClick(){
if (this.currentType == "username" ){
this.currentType="email"
}
else if (this.currentType == "email" ){
this.currentType="username"
}
}
}
})
</script>
</body>
</html>
|
v-show¶
当需要在显示和隐藏之间切回频繁的时候使用 v-show。只有一次切回使用v-if 。
循环¶
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 30 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(name,index) in names ">{{index }} {{ name}}</li>
</ul>
<ul>
<li v-for="(v,k,index) in person ">{{index }} {{ k}} {{ v}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
names: [ "panda","pdna02", "panda03"],
person:{
name: 'zhaojiedi',
age: 28,
weight: 60,
}
}
})
</script>
</body>
</html>
|
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 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(v,k,index) in person ">{{index }} {{ k}} {{ v}}</li>
</ul>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
person:{
name: 'zhaojiedi',
age: 28,
weight: 60,
}
}
})
</script>
</body>
</html>
|
v-for遍历添加key¶
添加key避免插入对象导致大量的对象移动。
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 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(name,index) in names " :key="name">{{index }} {{ name}}</li>
</ul>
<button @click="btnClick">添加</button>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
names: [ "panda","pdna02", "panda03"],
person:{
name: 'zhaojiedi',
age: 28,
weight: 60,
}
},
methods:{
btnClick(){
this.names.push("panda05")
},
}
})
</script>
</body>
</html>
|
v-for数组哪些是响应式的¶
目前一些数组操作是支持响应式的, 不是所有修改都是响应式的。 通过索引方式修改对象是无法响应式的。可以通过splice来实现。 或者使用vue.set方式。
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 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul>
<li v-for="(name,index) in names " :key="name">{{index }} {{ name}}</li>
</ul>
<button @click="btnClick">添加</button>
</div>
<script src="../js/vue.js"></script>
<script>
let app = new Vue({
el: "#app",
data: {
names: [ "panda","pdna02", "panda03"],
person:{
name: 'zhaojiedi',
age: 28,
weight: 60,
}
},
methods:{
btnClick(){
//push
// pop
// unshift
// splice
// sort
// reverse
this.names.push("panda05")
// 这是非响应式的。
this.names[0]="zhaojiedi"
// 这是响应式的
this.names.splice(1,1,"zhaojiedi")
//这是是响应式的
Vue.set(this.names,0,'zhaojiedi')
},
}
})
</script>
</body>
</html>
|
购入车案例¶
详细代码¶
下面展示各个代码的详细内容。
html¶
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | <!DOCTYPE html>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div id="app">
<div v-if="infos.length>=1">
<table>
<th>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td>购买数量</td>
<td>操作</td>
</th>
<tr v-for="(item,index) in infos" >
<td>{{index}}</td>
<td>{{item.name}}</td>
<td>{{item.date}}</td>
<td>{{item.price|formatPrice}}</td>
<td>
<button @click="sub(item)" :disabled="item.count<=1">-</button>
{{item.count}}
<button @click="add(item)">+</button>
</td>
<td><button @click="removeLine(index)">移除</button></td>
</tr>
</table>
总价: {{totalPrice|formatPrice}}
</div>
<h2 v-else>没有商品的</h2>
</div>
<script src="../js/vue.js"></script>
<script src="./main.js"></script>
</body>
</html>
|
style¶
1 2 3 4 5 6 7 8 9 10 11 12 13 | table{
border-spacing: 0;
}
th,td{
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
th{
background-color: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}
|
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 | let app = new Vue({
infos: [
{"name": "算法导论", "date": "2006-9", "count": 1, "price": 85},
{"name": "编程艺术", "date": "2006-2", "count": 1, "price": 59},
{"name": "编程珠玑", "date": "2008-10", "count": 1, "price": 39},
{"name": "代码大全", "date": "2006-3", "count": 1, "price": 128},
],
},
methods: {
add(item) {
console.log("add")
item.count++
},
sub(item) {
item.count--
},
removeLine(index) {
this.infos.splice(index, 1)
}
},
filters: {
formatPrice(price) {
return "¥ " + price.toFixed(2)
}
},
computed: {
totalPrice() {
let totalPriceSum = 0
for (let info of this.infos) {
totalPriceSum += info.count * info.price
}
return totalPriceSum
}
}
})
|
组件化开发¶
注册组件¶
详细代码实现¶
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 使用-->
<demo-cpt></demo-cpt>
<demo-cpt></demo-cpt>
<demo-cpt></demo-cpt>
</div>
<script src="../js/vue.js"></script>
<script>
// 创建
const demoCpt = Vue.extend(
{
template: `
<div>
<h2> 组件标题</h2>
<p> 组件内容</p>
</div>
`
}
)
// 注册
Vue.component("demo-cpt", demoCpt)
let app = new Vue({
el: "#app",
data: {
cnt: 1,
}
})
</script>
</body>
</html>
|
组件其他补充¶
局部组件¶
如果在特定的vue下的components属性指定的组件为局部组件,只能在特定的父组件使用的。
let app = new Vue({
el: "#app",
data: {
cnt: 1,
},
components:{
"demo-cpt2": demoCpt2
}
})
父子组件¶
组件和组件是有一定的层次关系的, 其中其中父子组件的是而非常重要的关系。

代码如下:
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 使用-->
<demo-cpt2>
<demo-cpt></demo-cpt>
</demo-cpt2>
</div>
<script src="../js/vue.js"></script>
<script>
// 创建
const demoCpt = Vue.extend({
template: `
<div>
<h2> 组件标题</h2>
</div>
`
})
const demoCpt2 = Vue.extend({
template: `
<div>
<h2> 组件标题2</h2>
<p>haha</p>
<demo-cpt></demo-cpt>
<p>haha</p>
</div>
`,
components: {
"demo-cpt": demoCpt
}
})
let app = new Vue({
el: "#app",
data: {
cnt: 1,
},
components: {
"demo-cpt2": demoCpt2
}
})
</script>
</body>
</html>
|
模块的分离写法¶
上面我们可以看到写一个组件内部还包含了html的代码,非常不方便管理和维护。可以通过如下方式进行改造。
2中方式在代码中体现:
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 使用-->
<demo-cpt></demo-cpt>
<demo-cpt2></demo-cpt2>
</div>
<script src="../js/vue.js"></script>
<script type="text/x-template" id="demoCpt">
<div>
<h2> 组件标题</h2>
</div>
</script>
<template id="demoCpt2">
<div>
<h2> 组件标题</h2>
</div>
</template>
<script>
// 创建
Vue.component('demo-cpt',
{
template: '#demoCpt'
}
)
Vue.component('demo-cpt2',
{
template: '#demoCpt2'
}
)
let app = new Vue({
el: "#app",
data: {
cnt: 1,
},
})
</script>
</body>
</html>
|
组件数据存放¶
组件内的数据有个data属性,但是这个是一个函数的,通过这个函数返回一个dict对象即可。
详细代码如下:
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<demo-cpt></demo-cpt>
</div>
<script src="../js/vue.js"></script>
<template id="demoCpt">
<div>
<button @click="sub">-</button>
{{count }}
<button @click="add">+</button>
</div>
</template>
<script>
// 创建
Vue.component('demo-cpt',
{
template: '#demoCpt',
data(){
// 组件是复用的,保障每组件实例对象是有独立的数据地址空间的。使用函数解决。
return {
count: 1
}
},
methods:{
add(){
return this.count++
},
sub(){
return this.count--
}
}
}
)
let app = new Vue({
el: "#app",
data: {
cnt: 1,
},
})
</script>
</body>
</html>
|
Note
组件的data必须是一个函数的,不能是通过的字典,因为我们组件是复用的,组件复用后的数据一定是独立的。
父子组件通信¶
官方文档中给出了父子组件的通信方式。
通过props向子组件传递数据
通过事件向父组件发送消息

父级向子级传递¶
父组件向子组件创建数据,可以通过子组件提供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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<label>
<input type="text" v-model="t1"> 第1个组件的值
</label>
<label>
<input type="text" v-model="t2"> 第2个组件的值
</label>
<!-- 使用-->
<label> 第一个组件实例</label>
<demo-cpt :title="t1"></demo-cpt>
<label> 第2个组件实例</label>
<demo-cpt :title="t2"></demo-cpt>
</div>
<script src="../js/vue.js"></script>
<template id="demoCpt">
<div>
<h2>{{title}}</h2>
</div>
</template>
<script>
const demoCpt = {
template: "#demoCpt",
props: {
"title": {
type: String,
default: "default title"
}
},
data() {
return {
}
},
}
let app = new Vue({
el: "#app",
data: {
t1: "abc",
t2: "def",
},
components: {
"demo-cpt": demoCpt
},
methods: {
}
})
</script>
</body>
</html>
|
子级向父级传递¶
自组件向父组件传递数据,通过发射事件,然后父组件绑定事件即可。参考如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<!-- 使用-->
<label> 第一个组件实例</label>
<demo-cpt @item-click="getSubInfo" ></demo-cpt>
<label >从子组件获取的值</label>
<h2> {{ subInfo}}</h2>
</div>
<script src="../js/vue.js"></script>
<template id="demoCpt">
<div>
<button v-for="item in categories" @click="bntClick(item)"> {{item.name }}</button>
</div>
</template>
<script>
const demoCpt = {
template: "#demoCpt",
props: {
"title": {
type: String,
default: "default title"
}
},
data() {
return {
categories:[
{id:"123","name":"热门推荐"},
{id:"124","name":"手机数码"},
{id:"125","name":"电脑办公"},
{id:"126","name":"家用家电"},
]
}
},
methods: {
bntClick(item) {
console.log(item)
this.$emit("item-click",item)
}
}
}
let app = new Vue({
el: "#app",
data: {
subInfo: {}
},
components: {
"demo-cpt": demoCpt
},
methods: {
getSubInfo(item){
this.subInfo= item.name
console.log(item)
}
},
})
</script>
</body>
</html>
|
父访问子组件数据¶
父组件访问子组件:使用$children或$refs
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button @click="getSubInfo">点击展示子组件信息</button>
<demo-cpt ref="aaa"></demo-cpt>
</div>
<script src="../js/vue.js"></script>
<template id="demoCpt">
<div>
<h2>{{title}}</h2>
</div>
</template>
<script>
const demoCpt = {
template: "#demoCpt",
props: {
"title": {
type: String,
default: "default title"
}
},
methods: {
showMessage(){
//console.log(this.title)
alert(this.title)
}
}
}
let app = new Vue({
el: "#app",
data: {
},
components: {
"demo-cpt": demoCpt
},
methods: {
getSubInfo(){
// console.log(this.$children)
this.$refs["aaa"].showMessage()
}
},
})
</script>
</body>
</html>
|
子访问父组件数据¶
子组件访问父组件:使用$parent
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<button @click="getSubInfo">点击展示子组件信息</button>
<demo-cpt ref="aaa"></demo-cpt>
</div>
<script src="../js/vue.js"></script>
<template id="demoCpt">
<div>
<h2>{{title}}</h2>
</div>
</template>
<script>
const demoCpt = {
template: "#demoCpt",
props: {
"title": {
type: String,
default: "default title"
}
},
methods: {
showMessage(){
//console.log(this.title)
alert(this.title)
}
}
}
let app = new Vue({
el: "#app",
data: {
},
components: {
"demo-cpt": demoCpt
},
methods: {
getSubInfo(){
// console.log(this.$children)
this.$refs["aaa"].showMessage()
}
},
})
</script>
</body>
</html>
|
插槽slot¶
编译作用域¶
父组件模板的所有东西都会在父级作用域内编译;子组件模板的所有东西都会在子级作用域内编译。
为什么使用slot¶
组件的插槽也是为了让我们封装的组件更加具有扩展性。
让使用者可以决定组件内部的一些内容到底展示什么。
slot的基本使用¶
在组件的模板定义中引入slot即可。
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<demo-cpt>
<button>haha</button>
</demo-cpt>
<demo-cpt>
<h2>abc</h2>
<h2>abc</h2>
<h2>abc</h2>
</demo-cpt>
<demo-cpt></demo-cpt>
</div>
<script src="../js/vue.js"></script>
<template id="demoCpt">
<div>
<h2>测试</h2>
<slot>
<button>默认button</button>
</slot>
</div>
</template>
<script>
const demoCpt = {
template: "#demoCpt",
}
let app = new Vue({
el: "#app",
data: {
"name": "panda"
},
components: {
"demo-cpt": demoCpt
},
})
</script>
</body>
</html>
|
具名slot¶
当子组件的功能复杂时,子组件的插槽可能并非是一个,怎么方便控制用户想替换哪个slot?
这就需要给slot起个名字,让用户选择给那个slot位置进行替换。
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 | <!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<demo-cpt>
<span slot="left">返回</span>
</demo-cpt>
</div>
<script src="../js/vue.js"></script>
<template id="demoCpt">
<div>
<slot name="left"></slot>
<slot name="center"></slot>
<slot name="right"></slot>
</div>
</template>
<script>
const demoCpt = {
template: "#demoCpt",
}
let app = new Vue({
el: "#app",
data: {
"name": "panda"
},
components: {
"demo-cpt": demoCpt
},
})
</script>
</body>
</html>
|
模块化¶
为什么需要模块化¶
起初js只是完成一些简单的脚本处理,随着ajax的出现,慢慢形成了前后端分离的阶段。 前段完成工作越来越多,代码被组织在多个js文件中,维护和管理是个严重的问题。
需要解决2个问题
复用性
可维护性
使用模块作为出口的规范¶
- CommonJS
commonJS服务器端(nodeJS)的js模块规范,同步加载方式。
- ADM
AMD是requireJS倡导的一种模块化规范,推崇依赖前置;在requireJS中模块是通过define来进行定义的,如果模块之间相互依赖,需要先将依赖模块导入进来,待导入完毕之后,在通过回调函数的方式执行后面的代码,有效的解决了模块依赖的问题。
- ES6Moudle
使用import/export语法,在文件顶部导入需要的模块,特点是:静态化
导出样例¶
CommonJS导出¶
1 2 3 4 5 6 7 | // 导出
module.exports = {
flag: flag,
max: function (a,b){
return a>b ? a:b
}
}
|
CommonJS导入¶
1 2 | var max = require("./01-模块化开发导出")
max(1,2)
|
ES6导出¶
1 2 3 4 5 6 7 8 9 | let name='xiaoming'
let sum = function (a,b){
return a+b
}
export {
name,sum
}
|
Tip
text 某些情况下,一个模块中包含某个的功能,我们并不希望给这个功能命名,而且让导入者可以自己来命名, 使用export default <object>
ES6导入¶
1 2 3 4 5 | import {name,sum} from "./xiaohong"
let c = sum(1,2)
console.log(c )
|
webpack¶
认识webpack¶
什么是webpack¶
webpack是一个现代的JavaScript应用的静态模块打包工具。
功能¶
将webpack中的各种资源模块进行打包合并成一个或多个包(Bundle)。
对资源进行处理,比如压缩图片,将scss转成css,将ES6语法转成ES5语法,将TypeScript转成JavaScript等等操作。
webpack和grunt/gulp的对比¶
grunt/gulp更加强调的是前端流程的自动化,模块化不是它的核心。
webpack更加强调模块化开发管理,而文件压缩合并、预处理等功能,是他附带的功能。

webpack的安装¶
前提环境是需要node的,然后需要有npm的, 最后通过npm安装webpack
npm install webpack --save-dev
其中 –save-dev 是表示开发时依赖的。
webpack的起步¶
目录说明
- dist
用于存放打包后的文件,也就是后续我们生产环境需要的文件夹,其他的生产环境不需要。
- src
源码文件夹,用于存放我们的开发文件。
- index.html
首页文件
- package.json
通过npm init生成的文件,

通过如下命令可以完成打包
# npm初始化
npm init
# 安装webpack
npm install webpack --save-dev
# 进行打包操作
webpack bundle --entry ./src/main.js -o ./dist/bundle.js
Tip
详细的具体代码点击右上角的github进入这个仓库找到工程进行测试。
webpack的配置¶
上面就是手工打包的一种方式了, 但是每次都要敲个命令去执行显然不是很方便的, 需要写成脚本方式的,然后执行才是正确做法。
webpack提供一个机制,可以配置一个文件,然后直接执行webpack 即可完成构建。
webpack.config.js样例¶
1 2 3 4 5 6 7 8 9 | const path = require('path');
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
}
};
|
package.json 样例¶
这个文件可以先通过npm init进行初始化,然后修改为如下。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | {
"name": "webpackconfig",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo ok ",
"build": "webpack"
},
"author": "",
"license": "ISC",
"devDependencies": {
"css-loader": "^5.0.1",
"mini-css-extract-plugin": "^1.3.3",
"style-loader": "^2.0.0",
"ts-loader": "^8.0.13",
"webpack": "^5.11.1"
}
}
|
构建¶
上面的2个文件都创建和修改完毕后, 我们执行`npm run build` 就会从package.json文件找到`build`对应的脚本`webpack`进行执行,webpack在执行的时候会读取`webpack.config.js`作为配置文件 进行构建。这样就构建起来非常方便了。
loader的使用¶
上面的构建我们webpack完成了js的文件构建打包,但是文件还有其他的css,html等,这些文件webpack本身是无法进行处理的,需要借助loader完成处理。
loader使用过程需要2个步骤。
通过npm安装需要使用的loader
在webpack.config.js中的modules关键字下进行配置
css文件处理¶
css的处理需要相关的css load 支持需要先安装对应的loader, 然后进行配置。
安装loader
进行配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | const path = require('path');
//const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
{loader: "style-loader"},
{loader: "css-loader"}
]
}
]
},
};
|
less文件处理¶
还是按照软件和对应的配置
npm install --save-dev less-loader less
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 | const path = require('path');
//const MiniCssExtractPlugin = require("mini-css-extract-plugin");
module.exports = {
entry: './main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'my-first-webpack.bundle.js'
},
module: {
rules: [
// {
//
// test: /\.css$/,
// use: [
// {loader: "less-loader"},
// { loader:"style-loader" },
// { loader:"css-loader" }
// ]
//
// },
{
test: /\.less$/,
use: [
{loader: "less-loader"},
{ loader:"style-loader" },
{ loader:"css-loader" }
]
},
]
},
};
|
webpack中配置Vue¶
安装loader
npm install --save-dev vue-loader vue-template-compiler
进行配置
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | const path = require('path')
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
}
|
plugin的使用¶
插件是完成额外的附属的一些功能,比如添加版权信息。
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 | const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
//"html-webpack-plugin": "^3.2.0",
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
plugins:[
new webpack.BannerPlugin({
banner: `
auth: zhaojiedi1992
email: zhaojiedi1992@outlook.com
protal: mit
`
}),
new HtmlWebpackPlugin({template: './src/index.html'})
]
}
|
搭建本地服务器¶
webpack提供了一个可选的本地开发服务器,这个本地服务器基于node.js搭建,内部使用express框架,可以实现我们想要的让浏览器自动刷新显示我们修改后的结果。
安装包
npm install --save-dev webpack-dev-server
配置
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 | const path = require('path')
const webpack = require('webpack')
const HtmlWebpackPlugin = require('html-webpack-plugin');
//"html-webpack-plugin": "^3.2.0",
module.exports = {
entry: './src/main.js',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'bundle.js',
publicPath: 'dist/'
},
module: {
rules: [
{
test: /\.vue$/,
use: ['vue-loader']
}
]
},
plugins:[
new webpack.BannerPlugin({
banner: `
auth: zhaojiedi1992
email: zhaojiedi1992@outlook.com
protal: mit
`
}),
new HtmlWebpackPlugin({
template: './src/index.html',
title: "app"
})
],
devServer:{
contentBase: path.join(__dirname, 'dist'),
compress: false ,
port: 9000
}
}
|
router¶
router 基本使用¶
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 | import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import About from '@/components/About'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect: "/home"
},
{
path: '/home',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
}
],
mode: 'history'
})
|
完成跳转¶
可以在组件内的一些方法中完成一些调整。
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 id="app">
<router-link to="/home" tag="button" >home</router-link>
<router-link to="/about" tag="button" >about</router-link>
<button @click="aboutClick">about2</button>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
methods:{
aboutClick(){
this.$router.push("/about")
// history.pushState("about")
},
}
}
</script>
<style>
.router-link-active{
color: red;
}
</style>
|
动态路由¶
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 | import Vue from 'vue'
import Router from 'vue-router'
import Home from '@/components/Home'
import About from '@/components/About'
import User from '@/components/User'
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect: "/home"
},
{
path: '/home',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
},
// {
// path: '/user',
// name: 'user',
// component: User
// },
{
path: '/user/:uid',
name: 'user',
component: User
}
],
mode: 'history'
})
|
懒加载¶
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 | import Vue from 'vue'
import Router from 'vue-router'
// import Home from '@/components/Home'
// import About from '@/components/About'
const Home = () => import ('@/components/Home')
const About = () => import ('@/components/About')
Vue.use(Router)
export default new Router({
routes: [
{
path: '/',
redirect: "/home"
},
{
path: '/home',
name: 'home',
component: Home
},
{
path: '/about',
name: 'about',
component: About
}
],
mode: 'history'
})
|
嵌套路由¶
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 | import Vue from 'vue'
import Router from 'vue-router'
// import Home from '@/components/Home'
// import About from '@/components/About'
const Home = () => import ('@/components/Home')
const About = () => import ('@/components/About')
const HomeNews = () => import ('@/components/HomeNews')
const HomeMessages = () => import ('@/components/HomeMessages')
Vue.use(Router)
export default new Router({
routes: [
{
path: '',
redirect: "/home",
},
{
path: '/home',
name: 'home',
component: Home,
children:[
{
path: '',
redirect: "news",
},
{
path: 'news',
component: HomeNews
},
{
path: 'messages',
component: HomeMessages
}
],
},
{
path: '/about',
name: 'about',
component: About
}
],
mode: 'history'
})
|
参数传递¶
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 | <template>
<div>
<h2>我是Profile</h2>
<p>我是Profile内容</p>
<p>第一种方式获取传递过来的uid为: {{Uid}}</p>
<p>第二种方式获取传递过来的uid为: {{Uid2}}</p>
</div>
</template>
<script>
export default {
name: "Profile",
computed:{
Uid(){
return this.$route.params.uid
},
Uid2(){
return this.$route.query.uid
}
}
}
</script>
<style scoped>
</style>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | <template>
<div id="app">
<router-link to="/home">home</router-link>
<router-link to="/about">about</router-link>
<router-link :to="UidUri">user</router-link>
<router-link :to="{path: '/profile', query:{uid: 'panda2'}}">Profile</router-link>
<router-view></router-view>
</div>
</template>
<script>
export default {
name: 'App',
data() {
return {
uid: 'panda'
}
},
computed: {
UidUri() {
return "/user/" + this.uid
}
}
}
</script>
<style>
</style>
|
vuex详解¶
vuex 基本使用¶
通过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 | import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter:10000
},
mutations: {
add(state){
state.counter +=1
},
sub(state){
state.counter-=1
}
},
actions: {},
getters: {},
modules: {},
})
export default store
|
vuex getter¶
getter 类似组件的属性,不会每次获取的时候都进行计算。
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 | import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
const store = new Vuex.Store({
state: {
counter:10000,
students:[
{id:1,firstName:"jiedi01", secondName: "zhao",age:21,height:165},
{id:2,firstName:"jiedi02", secondName: "zhao",age:22,height:170},
{id:3,firstName:"jiedi03", secondName: "zhao",age:25,height:175},
{id:4,firstName:"jiedi04", secondName: "zhao",age:30,height:180},
]
},
mutations: {
add(state){
state.counter +=1
},
sub(state){
state.counter-=1
}
},
actions: {},
getters: {
powerCounter(state){
return state.counter * state.counter
},
ageMore25Count(state){
return state.students.filter(student=>student.age>=25).length
},
StudentById(state){
// 这是返回一个函数, 参数是接受一个参数的
// 好理解的写法
// let infoByid=function (id){
// return state.students.find(s=>s.id===id)
// }
// return infoByid
// 简写的写法
return (id)=>state.students.find(s=>s.id===id)
}
},
modules: {},
})
export default store
|
vuex mutation¶
mutation 可以做一些同步操作,方便使用dev工具进行前段调整。 .. literalinclude:: ../../中级学习/07-vuex/02-vuexlearn-mutation/store/index.js
- encoding
utf-8
- language
javascript
- emphasize-lines
1
- linenos
vuex action¶
mutation 可以做一些同步操作,有些异步操作,就需要action了, 然后action操作mutation可以跟着变化。
vuex module¶
module是可以做多个模块的, 方便管理
vuex 文件拆解¶
随着项目越来越大, 单个index.js不太方便文件管理的,需要进行拆分管理。
ls -1 中级学习/07-vuex/06-vuexlearn-文件拆解/store/
actions.js
getters.js
index.js
modules
mutations.js
state.js