知识点14--vue-axios与element ui配合示例
前面几篇知识点已经被大家介绍了vue的element和axios,但是只是在各自介绍时顺带着有两个demo,并不是很全面,本篇使用两个模块一起开发几个功能demo,帮助大家在理解上更容易一点,项目沿用知识点13在知识点13的项目中,我们将前后端分离模块式开发,并使用两者展现了一个列表,下面我们在当前列表页面下,再扩展几个功能demo我们使用element的对话框功能实现添加,其实就是bootstr
前面几篇知识点已经被大家介绍了vue的element和axios,但是只是在各自介绍时顺带着有两个demo,并不是很全面,本篇使用两个模块一起开发几个功能demo,帮助大家在理解上更容易一点,项目沿用知识点13
在知识点13的项目中,我们将前后端分离模块式开发,并使用两者展现了一个列表,下面我们在当前列表页面下,再扩展几个功能demo
在扩展的demo中只会解释所用组件的核心重点属性,其他属性官网上自己看
功能一:添加
我们使用element的对话框功能实现添加,其实就是bootstrap的模态框
第一步:使用我们前面知识点说过的普通布局组件以及在合适的地方配合按钮组件准备一个添加用户的按钮,并在js中准备一个点击事件函数,函数里面先空着
<el-row>
<el-col :span="2">
<!--添加按钮-->
<el-button type="primary" @click="openInsertDialog()">添加用户</el-button>
</el-col>
<el-col :span="22"></el-col>
</el-row>
这个方法不要写错位置,它应该出现在methods中
openInsertDialog: function(){
}
第二步:在官网上找一个顺眼的对话框和表单组件,按照合适的逻辑修改为自己的,把它放在我们的页面上
<!--添加对话框的开始//-->
<el-dialog :visible.sync="addUserDialog" title="添加用户" width="60%" center>
<!--form表单-->
<el-form :model="insertUserFrm" label-width="120px" ref="insertUserFrm">
<el-form-item label="用户姓名" prop="name">
<el-input v-model="insertUserFrm.name" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="用户邮箱" prop="email">
<el-input v-model="insertUserFrm.email" placeholder="请输入邮件"></el-input>
</el-form-item>
<el-form-item label="出生日期" prop="brith">
<el-date-picker style="width: 100%;" value-format="yyyy-MM-dd" v-model="insertUserFrm.brith"
placeholder="请选择日期"></el-date-picker>
</el-form-item>
<el-form-item>
<!--添加的按钮事件-->
<el-button type="primary" @click="insertObject">添加用户</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!--添加对话框的结束//-->
随后我们要在js的data中初始化对话框中需要的参数
addUserDialog: false, //控制对话框是否显示
insertUserFrm: { //对话框中表单所需的一个绑定对象
name: '',
brith: '',
email: ''
}
此时去修改添加按钮的事件,使得点击按钮时对话框出现,还要准备好表单中的添加事件,当然方法体同样暂时为空
openInsertDialog: function(){
this.addUserDialog=true;
}
insertObject: function(){
}
此时你就可以启动前端项目,看一下展示对话框的功能是否正常
第三步:如果展示效果无异常,那就可以开始前后端交互的开发了,首先你要去开发点击事件触发的函数
insertObject: function() {
this.axios.post('http://localhost:91/users/add', this.insertUserFrm).then((response) => {
if (response.data) {
//表单数据还原,$refs['insertUserFrm']这种写法其实就相当于给表单添加一个选择器,特点就是参数是个数组一次性可以操作多个
this.$refs['insertUserFrm'].resetFields();
//对话框关闭
this.addUserDialog = false;
//重新查询数据
this.initData();
this.$message({
type: 'success',
message: '添加成功'
});
} else {
this.$message({
type: 'info',
message: '添加失败'
});
}
});
}
然后,后端去准备对应的接口,后端项目同知识点13一样继续沿用,并准备一个后端的接口
@RequestMapping("/add")
public Boolean add(@RequestBody User user){
return userService.save(user.getUser());
}
启动后台运行,前端页面测试
对于添加案例的代码,要注意的是Element的表单,和原生html表单不一样,它本质上是一个vue框架的组件,这就导致一个特点,它只能用vue的绑定数据去承载数据,且使用时它取出来的是一个json对象,而不是像使用普通HTML+jquery形式取出来的常规请求体,它的可控性被定死了,只能用post请求依靠body的形式提交表单
如果不信大家可以用get请求去试一试,你会发现用get请求发送的时候,由于是一个json字符串,他没有引用名称,值格式也不是请求体,所以后台不认识就不知道应该传到哪个Controller上,这样就会报500错误,而如果你再直接给一个引用名称,你会发现后台无法识别这个参数对应的值类型而报400错误,这也是所有框架的一个通病越高的封装能够实现的开发层度就越潜
这个时候或许会有一个疑惑,就是万一在日后的开发中用到了,不止要传这个表单的参数,还要传其他的参数,那怎么传?真有这种情况也很好解决。我们可以在后台接口接参数的时候,设置一个嵌套类型,核心代码就像下面这样
前台包装一层json对象
this.axios.post('http://localhost:91/users/add', {user:this.insertUserFrm,aaa:'test'})
接口中接收一个嵌套参数
@RequestMapping("/add")
public Boolean add(@RequestBody TestUser user){
return userService.save(user.getUser());
}
嵌套类型如下
package com.wy.scjg.bean;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import java.io.Serializable;
@ToString
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class TestUser implements Serializable {
private User user;
private String aaa;
}
这种方式就可以正常接收不同的参数了,但是注意决定不可以单独包一层json只传表单数据,那要就等于后台需要接收一个String了,也会500错误的
功能二:删除数据
我们先来做单删
第一步:在页面预留的删除按钮中绑定一个点击事件
<el-button size="mini" type="danger" @click="removeObject(scope.row.id)">删除</el-button>
第二步:编辑删除事件JS
removeObject:function(id){
this.$confirm('确定要删除你选中的数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//发送消息
this.axios.post('http://localhost:91/users/delete', null, {
params: {
ids: id
}
}).then((response) => {
//判断结果
if (response.data) {
this.$message({
type: 'success',
message: '删除成功!'
});
//重新初始化数据
this.initData();
} else {
this.$message({
type: 'info',
message: '删除失败'
});
}
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
}
第三步:后台准备一个删除用的控制器
@RequestMapping("/delete")
public boolean delete(Integer ids[]){
return userService.removeByIds(Arrays.asList(ids));
}
启动项目看结果,删除时跳出如下界面
取消时给予提示
删除成功时给予提示
现在我们开始做批删
第一步:element的表单组件为我们提供了一个自带的绑定事件属性,用来操作多选框被选中时的触发事件,我们只需要直接使用它就可以,把它写在表单组件中
<el-table :data="tableData" style="width: 100%;" @selection-change="handleSelectionChange">
第二步:在data中准备一个集合,将被选中的单选框所代表的的数据存放在里面
rows: []
第三步:定义修改事件
handleSelectionChange(val) {
this.rows = val;
console.log(this.rows)
}
此时我们可以看一下前台的效果,本质上是将每一行的数据作为一个对象装载在数组中
明白了这一点,我们就可以完善JS事件了
第四步:在页面中准备一个批量删除按钮
<el-col :span="2">
<el-button type="danger" @click="removeObjects()">批量删除</el-button>
</el-col>
第五步:定义批删JS事件
removeObjects: function() {
//判断是否有选中数据
if (this.rows != null && this.rows.length > 0) {
//调用单个删除
this.removeObject(this.rows.map((row) => row.id).join(","));
} else {
this.$message({
message: '请选择你要删除的记录数数据',
type: 'warning'
});
}
}
测试看结果即可
此时会有一个bug,当你操作最后一页删除,且最后一页数据删除完,你会发现页码正常减少一页,但数据却没有展示上一页而是页面为空,这点我给大家解释一下,我们的表格组件和分页组件,它并不是一个整体的,本质上它是两个组件,只是我们通过js的让它们之间产生了联系,达到了在下面点击分页就会去请求后台,拿到对应页数的数据,从而映射到表格组件上,问题就出现在这里,vue的分页组件有一个特点,这个特点也就造成了这个bug的存在,这个特点就是,分页组建的当前页属性,它不会随着你的添加、删除等相关操作而去改变,我们上一个功能做了添加,可以移动到任意一页操作一个添加,在我们js中写的事件是添加完成之后会重新请求后台拿到数据,但是当你去操作一遍,你会发现vue不会去重置当前页的值,这就导致你在做删除操作的时候,如果你删除的是非最后一页的任意一页都会正常显示,但是如果你删除最后一页内容且删空了,那么再次显示数据的时候当前页就会大于总页数,这就导致页面上没有数据,所以我们要在后台列表controller优化一部分代码,我们查询的时候做一个判断,如果查出来的数据为空且当前页大于总页数,则让当前页减一
@RequestMapping("/list")
public IPage<User> list(HttpServletRequest request,HttpServletResponse response, @RequestParam(defaultValue = "1") long current, @RequestParam(defaultValue = "3") long size, User user){
//创建分页对象
Page<User> page =new Page<>(current,size);
IPage<User> pageInfo = userService.getUserList(page, user);
//判断最后一页是否有数据
if(current>pageInfo.getPages() && pageInfo.getRecords().size()==0){
page.setCurrent(page.getCurrent()-1);
pageInfo = userService.getUserList(page,user);
}
return pageInfo;
}
功能三:条件查询
基于当前的代码查询功能就很简单了,只需要改一下前台的代码,就可以了
第一步:在element ui官网找一个顺眼的表单组件放到页面上
<!--form表单 v-bind-->
<el-form :inline="true" :model="searchFrm">
<el-form-item label="用户名称">
<el-input v-model="searchFrm.name" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="出生日期">
<!--日期的指定格式-->
<el-date-picker value-format="yyyy-MM-dd" v-model="searchFrm.value" type="daterange" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
<el-form-item label="部门名称">
<el-select v-model="searchFrm.deptId" placeholder="请选中部门">
<el-option v-for="dept in depts" :label="dept.name" :value="dept.id"></el-option>
</el-select>
</el-form-item>
<el-button type="success" icon="el-icon-search" @click="initData()">搜索</el-button>
</el-form>
第二步:在data中准备表单中需要的绑定数据
searchFrm: {
name: '',
value: '',
deptId: ''
},
depts: []
第三步:表单中的查询需要部门数据,我们在钩子函数里面拿到部门数据
created: function() { //必须使用function(){} this才代表的是vueComponent
//初始化数据
this.initData();
this.initDepts();
}
//这个函数放在methods里面
initDepts: function() {
this.axios.get('http://localhost:91/users/deptAll').then((response) => {
//部门的赋值
this.depts = response.data;
})
}
第四步:修改查询的代码,首先将initData参数的代码修改一下,携带查询条件
params: {
current: this.current, //当前页
size: this.size, //每页显示的记录数
stime: this.searchFrm.value[0], //查询条件 字段名称 实体属性名称 查询字段值,是双向v-model绑定的值
etime: this.searchFrm.value[1],
name: this.searchFrm.name,
did: this.searchFrm.deptId
}
第五步:修改后台代码,首先添加获取全部部门的控制器
@RequestMapping("/deptAll")
public List<Dept> getDeptAll(){
return deptService.list();
}
随后在用户列表控制器的User实体Bean中添加两个参数
@TableField(exist = false)
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date stime;
@TableField(exist = false)
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date etime;
最后修改Mapper中的语句
<select id="getUserList" resultMap="BaseResultMap" >
select u.*,d.name dname from user u left join dept d on u.did=d.id
<where>
<if test="user.name!=null and user.name!='' ">
and u.name like concat('%',#{user.name},'%')
</if>
<if test="user.brith!=null">
and u.brith=#{user.brith}
</if>
<if test="user.stime!=null">
and u.brith >= #{user.stime}
</if>
<if test="user.etime!=null">
and u.brith <= #{user.etime}
</if>
<if test="user.did!=null">
and u.did = #{user.did}
</if>
</where>
</select>
最后补充一个bug,在table组件里面出生日期取值应该是brith,我我前面代码写成了birth,虽然单词缺失错了,这是因为后台代码错了,懒得改了就一直用的brith
最后运行看效果
页面上还有两个功能,详情和编辑就留给大家自己扩展了,也不复杂,详情给后台一个id,展示在对话框里面,修改沿用详情的页面一样的流程
最后我将所有的代码留在下面,上面没看明白的自己研究
前台:
<template>
<div>
<!--form表单 v-bind-->
<el-form :inline="true" :model="searchFrm">
<el-form-item label="用户名称">
<el-input v-model="searchFrm.name" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="出生日期">
<!--日期的指定格式-->
<el-date-picker value-format="yyyy-MM-dd" v-model="searchFrm.value" type="daterange" range-separator="至"
start-placeholder="开始日期" end-placeholder="结束日期">
</el-date-picker>
</el-form-item>
<el-form-item label="部门名称">
<el-select v-model="searchFrm.deptId" placeholder="请选中部门">
<el-option v-for="dept in depts" :label="dept.name" :value="dept.id"></el-option>
</el-select>
</el-form-item>
<el-button type="success" icon="el-icon-search" @click="initData()">搜索</el-button>
</el-form>
<el-row>
<el-col :span="4">
<!--添加按钮-->
<el-button type="primary" @click="openInsertDialog()">添加用户</el-button>
</el-col>
<el-col :span="4">
<el-button type="danger" @click="removeObjects()">批量删除</el-button>
</el-col>
<el-col :span="16"></el-col>
</el-row>
<!--表格组件-->
<el-table :data="tableData" style="width: 100%;" @selection-change="handleSelectionChange">
<el-table-column type="selection"></el-table-column>
<el-table-column prop="id" label="编号"></el-table-column>
<el-table-column label="用户头像">
<template slot-scope="scope">
<el-avatar shape="square" :size="100" :src="scope.row.zp"></el-avatar>
</template>
</el-table-column>
<el-table-column prop="name" label="用户名"></el-table-column>
<el-table-column prop="age" label="年龄"></el-table-column>
<el-table-column prop="email" label="邮箱"></el-table-column>
<el-table-column prop="dname" label="所在部门"></el-table-column>
<el-table-column prop="brith" label="出生日期">
<!--插槽
<template slot-scope="scope">
<span>{{scope.row.birth}}</span>
</template>
-->
</el-table-column>
<el-table-column label="操作" width="300">
<template slot-scope="scope">
<el-button size="mini" type="success">详情</el-button>
<el-button size="mini" type="primary">编辑</el-button>
<el-button size="mini" type="danger" @click="removeObject(scope.row.id)">删除</el-button>
</template>
</el-table-column>
</el-table>
<!--分页组件-->
<el-pagination @size-change="handleSizeChange" @current-change="handleCurrentChange" :total="total"
:current-page="current" :page-size="size" :page-sizes="pageSizes"
layout="total,sizes,prev,pager,next,jumper" background></el-pagination>
<!--添加对话框的开始//-->
<el-dialog :visible.sync="addUserDialog" title="添加用户" width="60%" center>
<!--form表单-->
<el-form :model="insertUserFrm" label-width="120px" ref="insertUserFrm">
<el-form-item label="用户姓名" prop="name">
<el-input v-model="insertUserFrm.name" placeholder="请输入用户名"></el-input>
</el-form-item>
<el-form-item label="用户邮箱" prop="email">
<el-input v-model="insertUserFrm.email" placeholder="请输入邮件"></el-input>
</el-form-item>
<el-form-item label="出生日期" prop="brith">
<el-date-picker style="width: 100%;" value-format="yyyy-MM-dd" v-model="insertUserFrm.brith"
placeholder="请选择日期"></el-date-picker>
</el-form-item>
<el-form-item>
<!--添加的按钮事件-->
<el-button type="primary" @click="insertObject">添加用户</el-button>
</el-form-item>
</el-form>
</el-dialog>
<!--添加对话框的结束//-->
</div>
</template>
<script>
export default {
data() {
return {
total: 0,
size: 3,
current: 1,
pageSizes: [3, 5, 8],
tableData: [],
addUserDialog: false,
insertUserFrm: {
name: '',
brith: '',
email: ''
},
rows: [],
searchFrm: {
name: '',
value: '',
deptId: ''
},
depts: []
}
},
created: function() { //必须使用function(){} this才代表的是vueComponent
//初始化数据
this.initData();
this.initDepts();
},
methods: {
initDepts: function() {
this.axios.get('http://localhost:91/users/deptAll').then((response) => {
//部门的赋值
this.depts = response.data;
})
},
initData: function() {
//axios 的get请求方式 必须使用箭头函数 this 代表的是vueComponent
this.axios.get("http://localhost:91/users/list", {
params: {
current: this.current, //当前页
size: this.size, //每页显示的记录数
stime: this.searchFrm.value[0], //查询条件 字段名称 实体属性名称 查询字段值,是双向v-model绑定的值
etime: this.searchFrm.value[1],
name: this.searchFrm.name,
did: this.searchFrm.deptId
}
}).then((response) => {
//列表数据
this.tableData = response.data.records;
//分页相关的数据
this.total = response.data.total;
this.current = response.data.current;
this.size = response.data.size;
});
},
handleSizeChange(val) {
this.size = val; //记录每页显示的记录数
this.initData();
},
handleCurrentChange: function(val) {
this.current = val; //记录当前页
this.initData();
},
openInsertDialog: function() {
this.addUserDialog = true;
},
insertObject: function() {
this.axios.post('http://localhost:91/users/add', this.insertUserFrm).then((response) => {
if (response.data) {
//表单数据还原,$refs['insertUserFrm']这种写法其实就相当于给表单添加一个选择器,特点就是参数是个数组一次性可以操作多个
this.$refs['insertUserFrm'].resetFields();
//对话框关闭
this.addUserDialog = false;
//重新查询数据
this.initData();
this.$message({
type: 'success',
message: '添加成功'
});
} else {
this.$message({
type: 'info',
message: '添加失败'
});
}
});
},
removeObject: function(id) {
this.$confirm('确定要删除你选中的数据吗?', '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
//发送消息
this.axios.post('http://localhost:91/users/delete', null, {
params: {
ids: id
}
}).then((response) => {
//判断结果
if (response.data) {
this.$message({
type: 'success',
message: '删除成功!'
});
//重新初始化数据
this.initData();
} else {
this.$message({
type: 'info',
message: '删除失败'
});
}
});
}).catch(() => {
this.$message({
type: 'info',
message: '已取消删除'
});
});
},
//全选选中改变事件
handleSelectionChange(val) {
this.rows = val;
},
removeObjects: function() {
//判断是否有选中数据
if (this.rows != null && this.rows.length > 0) {
//调用单个删除
this.removeObject(this.rows.map((row) => row.id).join(","));
} else {
this.$message({
message: '请选择你要删除的记录数数据',
type: 'warning'
});
}
}
}
}
</script>
<style>
</style>
后台框架实用Springboot
package com.wy.scjg.controller;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.wy.scjg.bean.Dept;
import com.wy.scjg.bean.User;
import com.wy.scjg.service.DeptService;
import com.wy.scjg.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Arrays;
import java.util.List;
@RestController
@CrossOrigin(originPatterns = "*",allowCredentials = "true")
@RequestMapping("/users")
public class UsersController {
@Autowired
private UserService userService;
@Autowired
private DeptService deptService;
@RequestMapping("/add")
public Boolean add(@RequestBody User user){
return userService.save(user);
}
/**
* 出列表
* @param request
* @param current
* @param size
* @param user
* @return
*/
@RequestMapping("/list")
public IPage<User> list(HttpServletRequest request,HttpServletResponse response, @RequestParam(defaultValue = "1") long current, @RequestParam(defaultValue = "3") long size, User user){
//创建分页对象
Page<User> page =new Page<>(current,size);
IPage<User> pageInfo = userService.getUserList(page, user);
System.out.println(user);
//判断最后一页是否有数据
if(current>pageInfo.getPages() && pageInfo.getRecords().size()==0){
page.setCurrent(page.getCurrent()-1);
pageInfo = userService.getUserList(page,user);
}
return pageInfo;
}
/**
* 删除用户
* @param ids
* @return
*/
@RequestMapping("/delete")
public boolean delete(Integer ids[]){
System.out.println(ids);
return userService.removeByIds(Arrays.asList(ids));
}
@RequestMapping("/deptAll")
public List<Dept> getDeptAll(){
return deptService.list();
}
}
mapper语句
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wy.scjg.mapper.UserMapper">
<resultMap id="BaseResultMap" type="com.wy.scjg.bean.User">
<id column="id" property="id" />
<result column="name" property="name" />
<result column="age" property="age" />
<result column="email" property="email" />
<result column="brith" property="brith" />
<result column="did" property="did" />
<result column="dname" property="dname" />
</resultMap>
<select id="getUserList" resultMap="BaseResultMap" >
select u.*,d.name dname from user u left join dept d on u.did=d.id
<where>
<if test="user.name!=null and user.name!='' ">
and u.name like concat('%',#{user.name},'%')
</if>
<if test="user.brith!=null">
and u.brith=#{user.brith}
</if>
<if test="user.stime!=null">
and u.brith >= #{user.stime}
</if>
<if test="user.etime!=null">
and u.brith <= #{user.etime}
</if>
<if test="user.did!=null">
and u.did = #{user.did}
</if>
</where>
</select>
</mapper>
UserBean实例
package com.wy.scjg.bean;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.experimental.Accessors;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
import org.springframework.format.annotation.DateTimeFormat;
import java.io.Serializable;
import java.util.Date;
@ToString
@Data
@EqualsAndHashCode(callSuper = false)
@Accessors(chain = true)
public class User implements Serializable {
/**
* 主键ID
*/
@TableId(value = "id", type = IdType.AUTO)
private Long id;
/**
* 姓名
*/
private String name;
/**
* 年龄
*/
private Integer age;
/**
* 邮箱
*/
private String email;
/**
* 生日
*/
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date brith;
private Integer did;
//表中不存在的字段
@TableField(exist = false)
private String dname;
/**
* 照片
*/
private String zp;
/**
* 个人照,任意张
*/
private String grz;
@TableField(exist = false)
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date stime;
@TableField(exist = false)
@DateTimeFormat(pattern = "yyyy-MM-dd")
@JsonFormat(pattern = "yyyy-MM-dd")
private Date etime;
}
到本次的Vue案例就结束了,总计14篇博文,希望对学习Vue的同行有所帮助,在最后我要补充一点,Vue在目前用的比较多,但它只是之一不是唯一,Vue除了项目运行快、企业用工成本低这些表面的原因导致市场占比大之外,其实学习中大家还可以发现Vue本身整合了很多我们需要的技术与一体,比如较早的Jquery虽然也很优秀,但是它无法完成页面的灵活开发,也就是if、for等这些开发方式,再这一点上是用了Java的标签库进行的弥补,反观Vue就不一样了它自带了模板指令解决,所以Vue本身就像是一个技术整合商一样解决了大部分问题,因此才造就了它的火热
更多推荐
所有评论(0)