vue.js干活的基本格式
这一年从年初实习到现在算是把 vue.js 这个东西用的挺多的,这里放上自己写 vue.js 的一些套路。
提示:由于 vue.js 全家桶的配置每个项目每个公司都会有所不同,所以这里不对 vuex 这种东西做讲解(就个人经验来说,只接触过路由的配置,没啥深入体验)。
结构讲解
以下的代码使我在这个学期 ANU 项目课实现的一个课拖拽的表格的代码。由于我们在vue.js中采用组件化开发的思想,所以我们写的每一个.vue文件实际上都是页面显示一部分,例如我在下面写的就是一个会弹出桌面供用户进行拖拽操作的按钮。这个按钮会镶嵌到另一个页面,或另一个组件中。不得不说,这一思路确实很好地做到了软件工程所宣扬的高内聚,低耦合。只要功能分配合理,对整个页面就是组件之间进行模块化的拼接与安装。
页面样式
在具体的实现层面上,整个文件可以分成两大部分,一个是组件的外在样子,也就是用html以及vue.js提供的一些语法糖进行页面的最前端的开发;另一个就是页面的前端运算单元,具体的功能包括通过ajax与后端进行数据的交互,应付一些前端用户操作,控制一些反馈(比如控制加载动画,在用户输入异常信息提示错误等待)。首先先说template模块。在template这一标签下大部分的页面结构实现与一般的html无异(至少我所经历的是差不多的)。其中可以称作是vue.js所特有的部分,是诸如v-for,v-if,v-bind,v-onclick这种用来动态显示数据以及数据绑定的特殊标签。
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<template>
<div>
<a class="button btn btn-primary text-white" data-toggle="modal" data-target="#assignModal">
<i class="fas fa-th"></i>
Easy sort
</a>
<div class="modal fade bd-example-modal-lg" id="assignModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-lg" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Add New Team</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div v-for="(element, index) in arrTeamPlayers" :key="index" class="list-group col-md-2 float-left min-height">
<h5 class="text-center">{{element['team_name']}}</h5>
<draggable v-model="element['players']" :options="{group:'people'}" class="min-height">
<div v-for="(element, index) in element['players']" :key="index" class="list-group-item text-center" v-bind:class="{'list-group-item-danger': !element['is_approved']}">
{{element['user_name']}}
</div>
</draggable>
</div>
</div>
<div class="modal-footer">
<button type="submit" data-dismiss="modal" aria-label="Close" class="btn btn-primary form-control" @click="submit">Submit the assignment</button>
</div>
</div>
</div>
</div>
</div>
</template>值得一提的是,在组件内部自己定义CSS样式的时候,这些样式只会作用于该组件,不会外溢。所以如果外部整体的CSS觉得功能不齐全,尽可以放心大胆在自己要用的组件定义需要的CSS。
1
2
3
4
5<style>
.min-height {
min-height: 100px;
}
</style>数据运算
麻雀虽小,五脏俱全。下面的代码,虽然干的事情并不多,但结构是完整的。下面来一个个介绍相应的组件及其功能。components
这里存放调用的其他组件,任何其他组件在调用的时候,都需要先引入,再在此进行注册,然后方能使用。props
这里负责存放与外部进行交互的数据,该组件的父组件可通过:name_props = “value”这一形式将参数传入该组件,实现数据交互。data()
data是函数,data是函数,data是函数,重要事情说三遍。它负责存放用于组件内部的数据。无论是调用props还是data,由于它们都绑定到了this对象,所以使用的时候,必须写成this.data的形式。mounted()
这里就涉及到vue.js的生命周期了,在这里我们可以指定组件在页面的生成阶段要做的事情,比如调用ajax从后端拿数据等待。methods
这里存放所有定义好的函数,调用的时候和data以及props一样,需要写成this.function的形式。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<script>
import draggable from "vuedraggable";
export default {
components: {
draggable
},
props: {
competition_id: Number
},
data: () => {
return {
arrTeamPlayers: [],
nNumberOfColonm: 0,
};
},
mounted() {
this.getData();
},
methods: {
getData() {
axios
.get("/api/team/member", {
params: { competition_id: this.competition_id }
})
.then(response => {
console.log(response["data"]["data"])
let data = response["data"]["data"]
data["teams"].forEach(team => {
this.arrTeamPlayers.unshift({
team_id: team["id"],
team_name: team["name"],
players: []
});
});
this.arrTeamPlayers.forEach(record => {
data["plays"].forEach(play => {
if (play["team_id"] == record["team_id"]) {
record["players"].push({
user_id: play["id"],
user_name: play["name"],
is_approved: play["paid"] == 0 ? false : true
});
}
});
});
});
},
submit() {
axios
.post("/api/team/new", {
params: {
competition_id: this.competition_id,
arrTeamPlayers: this.arrTeamPlayers
}
})
.then(response => {
console.log(response)
});
}
}
};
</script>
后记:一些踩过的坑的回忆
JS的AJAX请求是一种异步操作,所以当处理每一个返回的response时,尽量将里面的操作别做成几个进程来回相互要数据,至少我一直没实现过,我也不知道JS怎么去定义互斥锁。
在对数据监听的时候,如果监听对象是数组或对象,或者是数组对象中的某一属性,一定要用深监听,否则一般的监听没法侦测到区别。