笔者是PHP开发出身,前端掌握的技术只有基础的HTML/CSS/JS/JQ,之前一直以为Vue就是另一个jQuery,就没有去认真了解这门技术。最近组里一个前端大佬在项目中引入了Vue并封装了一些组件,为了推广使用新技术,笔者这才去菜鸟教程认认真真学了一遍Vue基础,在学习过程中慢慢体验到Vue和jQuery是截然不同的,jQuery仅仅是一个JS类库,只是封装简化了JS的一些常用操作,在使用JQ时的开发思路依然是和使用原生JS一样是面向过程的,几乎每个动作都要先获取节点元素再对它的一些属性进行操作,而Vue才是真正的前端框架,它将DOM节点抽象为一个个对象,在初始化时只需要将节点和对象绑定一次,就可以通过操作对象来操作节点了,开发思路是面向对象的。
学习Vue,首先要做的就是忘记JQ的那种围绕DOM节点的开发模式,以下示例为一个普通列表页面,本来项目里使用PHP+HTML混合开发的,同事用Vue进行了改写:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-测试列表</title>
<link href="https://cdn.staticfile.org/twitter-bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet">
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<style type="text/css">
.pagination>li>span{
cursor: pointer;
}
.pagination>li.active>span{
cursor: auto;
}
#content{
width: 80%;
margin-left: 10%;
}
</style>
<body>
<div id="content">
<!-- 数据列表 -->
<div class="table-responsive" v-loading="tableLoading">
<table class="table table-bordered table-hover" style="table-layout: fixed">
<thead>
<tr>
<td>ID</td>
<td>姓名</td>
</tr>
</thead>
<tbody>
<tr v-for="v in list ">
<td>{{v.id}}</td>
<td>{{v.name}}</td>
</tr>
</tbody>
</table>
</div>
<!-- 数据列表 -->
<!-- 分页列表 -->
<div class="row">
<div class="col-sm-6 text-left">
<ul class="pagination" v-if="total>pagesize">
<template v-for="v in pagelist ">
<li @click="getList(v.value)" :class="{active:v.value == page }"><span >{{v.name}}</span></li>
</template>
</ul>
</div>
<div class="col-sm-6 text-right">
显示开始 {{(page-1)*pagesize+1}} 到 {{Math.min(page*pagesize,total)}} 共 {{total}} (总{{Math.ceil(total/pagesize)}}页)
</div>
</div>
<!-- 分页列表 -->
</div>
<script>
var vm = new Vue({
el:'#content',
data:{
tableLoading:false,
total:0,
page:1,
pagesize:20,
pagelist:[],
list:[]
},
methods:{
// 设置地址栏URL
updateUrl(data){
let getParams = this.getFuc();
let url = window.location.pathname + '?';
let params = Object.assign({ },getParams,data);
for (var key in params) {
if (params[key] !== '')
url +=key+ '='+encodeURI(params[key]) +'&';
}
history.pushState({ },0,url.substring(0,url.length-1));
},
// 获取GET参数
getFuc(){
let query = window.location.search.substring(1);
let vars = query.split("&");
let get = {};
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if (pair[0])
get[pair[0]] = decodeURI(pair[1]);
}
return get;
},
// 设置分页列表格式
setPageList(){
page = Number(this.page) ;
pagesize = Number(this.pagesize);
total = Number(this.total);
let res = [];
if (page>1){
res = [
{
value:1,
name:'|<'
},
{
value:page-1,
name:'<'
}
];
}
//总页码
let count = 0;
let totalPagesize = Math.ceil(total/pagesize) ;
for (let i = page-4;i<=page;i++){
if (i>0){
count++;
res.push({
value:i,
name:i
});
}
}
for (let i = page+1 ;i<= 9-count+page ; i++){
if (i<=totalPagesize)
res.push({
value:i,
name:i
});
}
if (page < totalPagesize){
res.push({
value:page+1,
name:'>'
});
res.push({
value:totalPagesize,
name:'>|'
});
}console.log(res)
this.pagelist = res;
},
// 请求接口获取列表数据
getList(page){
if (!page){
page = this.page;
}
this.tableLoading = true;
this.updateUrl({'page':page});
this.$http.get('/getList.php?page='+page).then((response) => {
this.tableLoading = false;
let res = response.body;
if (res.retcode == 200){
this.list = res.data;
this.total = res.total;
this.page = page;
this.setPageList();
}else{
this.list = [];
}
}, (response) => {
// error callback
this.list = [];
this.tableLoading = false;
});
}
},
mounted(){
this.getList();
},
created(){
let $_GET = this.getFuc();
this.page = $_GET['page'] === undefined ? this.page : $_GET['page'];
},
});
</script>
</body>
</html>
<?php
// 模拟接口
header('content-type:application/json');
$page = $_GET['page'] ?? 1;
$json = ['data'=>[],'total'=>110,'retcode'=>200];
$pagesize = 20;
for ($i=($page-1)*$pagesize+1; $i <= min($page*$pagesize,$json['total']); $i++) {
$json['data'][] = ['id'=>$i,'name'=>'name'.$i];
}
echo json_encode($json);
?>
- 绑定DOM元素和Vue对象
new Vue()实例化一个Vue对象,el:'#content'将对象与id="content"的元素绑定,元素内部就可以使用对象的数据(data)和方法(method)了。
- 使用指令绑定data与元素相关属性
- v-if判断是否插入元素,与<?php if (condition): ?>效果类似
- v-for="v in pagelist"循环,与<?php foreach ($variable as $value): ?>效果类似
- @click绑定事件到对象方法
- :class绑定元素属性到对象数据
- 渲染数据
用双大括号{{表达式}}渲染数据,当大括号内的对象数据发送改变时,被绑定的DOM节点属性也会一同改变。
- 提取数据,实现方法
主方法为getList,HTTP请求接口数据,修改对象数据。
- 实现生命周期钩子函数
created在对象初始化完成后调用,mounted在对象与元素绑定后调用。
- 自定义指令
v-loading为自定义指令,可以控制在HTTP请求时控制列表显示加载时的样式,element ui中有现成的轮子,可以引入使用。