Vue
1、介绍
仅学皮毛,能看懂即可
实现前后端分离
Hello World
进入网页 https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js ,Ctrl+S 下载 vue.js
创建一个 static web 工程
<script src="../../vue/vue.js"></script>
</head>
<body>
<!--html页面模板-->
<div id="app">
<!-- {{}} vue的内容取值,填充data中定义的message属性 -->
{{ message }}
</div>
<script>
//vue实例,用于渲染模板跟家在数据用
var app = new Vue({ //这个Vue对象用来控制某一个标签里面的数据
el: '#app', //指定 vue 渲染模板位置
data: {
message: 'Hello Vue!' //定义一个数据,在id为app的标签内部去使用
}
})
</script>
</body>
上面的代码做了什么事情?
创建Vue对象的时候,传入了一个对象:{}
- {}中的 el 属性:该属性决定了这个Vue对象挂载到哪一个元素上这里挂载到了 id为app 的元素上
- {}中的 data 属性:该属性中通常会存储一些数据,好像上面例子中的 message 就是直接定义出来的数据
2、常见指令
指令带有前缀 v- ,以表示它们是 vue 提供的特殊 attribute
{{属性}}
{{属性}} 只能在标签之间使用,不可用于标签属性位置使用
里面可以使用表达式
<div id="test">
<ul>
<li v-for="item in arr">
{{item == 1?"可以":"不可以"}}
</li>
</ul>
</div>
<script>
var vv = new Vue({
el:"#test",
data:{
arr:[1,2,1,1,2,2]
}
});
</script>
<!--html页面模板-->
<div id="app">
<!-- {{}} vue的内容取值,填充data中定义的message属性 -->
{{ message }}
</div>
<script>
//vue实例,用于渲染模板跟家在数据用
var app = new Vue({ //这个Vue对象用来控制某一个标签里面的数据
el: '#app', //指定 vue 渲染模板位置
data: {
message: 'Hello Vue!' //定义一个数据,在id为app的标签内部去使用
}
})
</script>
可在浏览器动态更改信息
显示数据(v-bind)
v-bind 表示通知vue在渲染标签时,将 bind 绑定的属性和 vue 实例 data 中同名属性值保持一致
v-bind: 属性绑定指令,用于标签属性位置
绑定图片: v-bind:src 或者 :src
绑定样式: v-bind:class 或者 :class
绑定链接: v-bind:href 或者 :href
<script src="../../vue/vue.js"></script>
</head>
<body>
<!-- {{}} 只能在标签开始与结束之间位置是一个-->
<!--
v-bind: 属性绑定指令,用于标签属性位置
绑定图片: v-bind:src 或者 :src
绑定样式: v-bind:class 或者 :class
绑定链接: v-bind:href 或者 :href
-->
<div id="app">
<span v-bind:title="title">{{msg}}</span>
<br/>
<!--简写方式-->
<span :title="title">{{msg}}</span>
</div>
<script>
var d = new Vue({
el:"#app",
data:{
msg:"动态信息",
title:"哈哈"
}
});
</script>
</body>
数据双向绑定数据(v-model)
与 v-bind 类似,不过数据可以同步改动
v-model 可以动态修改 vue 示例 data 数据
<div id="app">
<!-- v-bind 单向属性绑定指令,属性数据改动不会影响vue实例data数据-->
用户名:<input type="text" v-bind:value="defaultValue">
<br/>
<!-- v-model 双向属性绑定指令,属性数据改动会影响vue实例data数据
出现defaultValue的位置全部都改
一般用于表单标签操作使用
-->
用户名:<input type="text" v-model:value="defaultValue">
<br/>
{{defaultValue}}
</div>
<script>
var d = new Vue({
el:"#app",
data:{
defaultValue:"动态信息",
}
});
</script>
显示数据(v-html)
<!-- v-html 将数据解析成html格式并输出-->
<div id="app" v-html="msg">
<!-- {{}} 会将数据原样输出-->
<!-- 输出:<span style='color: red;'>字符串</span> -->
{{msg}}
此标签会被覆盖,这里内容不会显示
</div>
<script>
var d = new Vue({
el:"#app",
data:{
msg:"<span style='color: red;'>字符串</span>",
}
});
</script>
判断(v-if)
<script src="../../vue/vue.js"></script>
</head>
<body>
<!-- v-html 将数据解析成html格式并输出-->
<!-- 需求:data中有age属性,根据age属性显示不同内容
age > 18 :欢迎光临
age < 18 :禁止
age == 18 :考虑一下
-->
<div id="app">
<span v-if="age>18">欢迎光临</span>
<span v-else-if="age<18">禁止</span>
<span v-else>考虑一下</span>
</div>
<script>
var d = new Vue({
el:"#app",
data:{
age:0, //这里需要设置值,相当于默认值赋值,否则空指针
}
});
</script>
</body>
循环指令(v-for)
<script src="../../vue/vue.js"></script>
<div id="app">
<ul>
<!--类似于for(String i:arrs),item是自定义变量名-->
<li v-for="item in arrs">{{item}}</li>
</ul>
<ul>
<!-- 加上索引值:(左边是元素,右边是索引) -->
<li v-for="(item,index) in arrs">{{item}}====>{{index}}</li>
</ul>
<ul>
<!-- 遍历对象集合 -->
<li v-for="(u,index) in user">
{{u.id}}、 {{u.name}}、 {{u.age}}====>{{index}}
</li>
</ul>
</div>
<script>
var d = new Vue({
el:"#app",
data:{
arrs:[18,12,88,"a"],
user:[
{id:1, name:"xcm1", age:111},
{id:2, name:"xcm2", age:222},
{id:3, name:"xcm3", age:333},
{id:4, name:"xcm4", age:444},
]
}
});
</script>
绑定事件(v-on)
可缩写成 @
比如: v-on:click 绑定单击事件,缩写成 @click
<script src="../../vue/vue.js"></script>
<script src="../../vue/jquery-1.7.2.js"></script>
<div id="app">
<!-- 原生html -->
<button onclick="clickMe()">点我</button>
<!-- 当使用 vue 方式处理事件时,必须将事件函数定义在 vue 实例中-->
<button v-on:click="clickMe()">vue点我</button>
</div>
<script>
//事件函数
function clickMe() {
alert("被点了")
}
var d = new Vue({
el:"#app",
data:{
arrs:[18,12,88,"a"],
},
methods:{ //vue定义方法的位置,业务处理方法定义
clickMe:function () {
alert("vue被点了")
}
}
});
</script>
3、Vue 事件
事件函数
v-on 可缩写成 @
比如: v-on:click 绑定单击事件,缩写成 @click
事件对象
事件对象:系统封装整个事件信息的一个对象
在事件函数的方法内使用 $even
<script src="../../vue/vue.js"></script>
<script src="../../vue/jquery-1.7.2.js"></script>
<div id="app">
<!-- $event:vue封装的事件对象
当事件触发时系统自动创建此对象并赋值给全局变量 $even,变量名是固定的
-->
<button v-on:click="clickMe($event)">vue点我</button>
</div>
<script>
var d = new Vue({
el:"#app",
data:{
arrs:[18,12,88,"a"]
},
methods:{ //vue定义方法的位置,业务处理方法定义
clickMe:function (e) {
console.log(e); //快捷键 e.log
alert("vue被点了")
}
}
});
</script>
获取事件源
事件源:触发事件的标签
在vue实例中使用 e.currentTarget
<div id="app">
<!-- $event:vue封装的事件对象
当事件触发时系统自动创建此对象并赋值给全局变量 $even,变量名是固定的
-->
<button v-on:click="clickMe($event)">vue点我</button>
</div>
<script>
var d = new Vue({
el:"#app",
data:{
arrs:[18,12,88,"a"]
},
methods:{ //vue定义方法的位置,业务处理方法定义
clickMe:function (e) {
console.log(e); //快捷键 e.log
//以前获取事件源:console.log(this);
//在 vue 事件函数中,this等价于vue的实例变量 d,this==d
//vue中获取事件源
console.log(e.currentTarget);
alert("vue被点了")
}
}
});
</script>
事件传参
<div id="app">
<ul>
<!-- $event:vue封装的事件对象
当事件触发时系统自动创建此对象并赋值给全局变量 $even,变量名是固定的
函数需要获取页面参数时,只需将其作为事件函数的参数传入即可
还可以传入对象
-->
<li v-for="(u,index) in user" v-on:click="clickMe($event, u.id,u.name, u)">
{{u.id}}、 {{u.name}}、 {{u.age}}====>{{index}}
</li>
</ul>
</div>
<script>
//事件函数
function clickMe() {
alert("被点了")
}
var d = new Vue({
el:"#app",
data:{
arrs:[18,12,88,"a"],
user:[
{id:1, name:"xcm1", age:111},
{id:2, name:"xcm2", age:222},
{id:3, name:"xcm3", age:333},
{id:4, name:"xcm4", age:444},
]
},
methods:{ //vue定义方法的位置,业务处理方法定义
clickMe:function (e,id,name, u) {
alert(id +","+ name +"==="+ u.age +","+ u.id )
}
}
});
</script>
4、Vue的属性
el
用来指示 vue 编辑器什么地方开始解析
<div id="test"/>
<script>
var vv = new Vue({
el:"#test",
data:{
}
});
</script>
data
vue渲染过程中需要用到的数据
<div id="test"/>
<script>
var vv = new Vue({
el:"#test",
data:{
arr:[1,2,3]
}
});
</script>
methods
放置页面中的业务逻辑,js 函数一般都放置在 methods 中
<script>
var vv = new Vue({
el:"#test",
data:{
arr:[1,2,3]
},
methods:{
fun1:function () {
}
fun2:function () {
}
}
});
</script>
filters
vue 过滤器集合
<div id="test">
<ul>
<li v-for="item in arr">
{{item == 1?"可以":"不可以"}}
</li>
</ul>
</div>
<script>
var vv = new Vue({
el:"#test",
data:{
arr:[1,2,1,1,2,2]
}
});
</script>
<div id="test">
<ul>
<!-- | 是管道操作符,左边数据作为右边函数的参数值-->
<li v-for="(u, index) in users" >
{{u.sex | sexFilter}}
</li>
</ul>
</div>
<script>
var vv = new Vue({
el:"#test",
data:{
users:[
{id:1,name:"aa",sex:"0"},
{id:2,name:"bb",sex:"1"},
{id:3,name:"cc",sex:"1"},
{id:4,name:"dd",sex:"0"}
]
},
filters:{ //一般用于数据格式化、数据加工
sexFilter:function (value) {
return value == 1 ? "男" : "女";
}
}
});
</script>
mounted
需要用Ajax,就需要导入 jQuery 文件
之前 data 里面的数据都是固定的,但是平时使用的数据都是来自于数据库,此时就用到mounted
mounted 是一个函数,在 vue 实例创建完成之后立即调用(html加载完成后立即执行)
一般用于初始化data中的数据
<script src="../../vue/vue.js"></script>
<script src="../../vue/jquery-1.7.2.js"></script>
<div id="test">
<ul>
<!-- | 是管道操作符,左边数据作为右边函数的参数值-->
<li v-for="(u, index) in datauu" >
{{u.sex | sexFilter}}
</li>
</ul>
</div>
<script>
var vv = new Vue({
el:"#test",
data:{
datauu:[]
},
filters:{ //一般用于数据格式化、数据加工
sexFilter:function (value) {
return value == 1 ? "男" : "女";
}
},
mounted:function () {
//mounted是一个函数,html加载完毕、vue准备渲染数据时调用
//一般用于初始化data中的数据
//异步请求拿数据
$.get("/vuetest/views/users.json",{},function (dd) {
vv.datauu = dd;
})
}
});
</script>
拓展
created
computed
template
render
watch
5、Vue生命周期
综合案例
mongdb项目
依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-mongodb</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
实体类
@AllArgsConstructor
@NoArgsConstructor
@Data
@Document("users") //设置文档所在的集合
public class User {
//文档的id建议使用 String 类型,一般使用ObjectId类型来封装,并且贴上@Id注解
// 自动映射为 _id 自动封装ObjectId
@Id
private String id;
private String name;
private Integer age;
//数组推荐使用 ArrayList
private List<String> hobby = new ArrayList<>();
}
实现类
package com;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* @author shkstart
* @create 2022/3/1-17:16
*/
// spring封装操作模板,MongodbTemplate 类,直接使用即可
@Service
public class UserServiceImpl implements IUserService{
//直接使用,容器已经创建好了
@Autowired
private MongoTemplate template;
@Override
public void save(User user) {
template.save(user);
}
@Override
public void delete(String id) {
template.remove(id);
}
@Override
public void update(User user) {
template.save(user);
}
@Override
public User get(String id) {
return template.findById(id, User.class);
}
@Override
public List<User> list() {
return template.findAll(User.class);
}
}
后端控制器
@RestController
public class MyController {
@Autowired
private IUserService service;
//注意:项目开发中,一般不会用标准的 RESTful 风格定义路径
@GetMapping("/list")
public Object list(){
return service.list();
}
}
正常访问:
请求跨域
两个项目相互发起请求,如果项目对应请求的协议、ip、端口 三者存在一个不一样,称之为跨域请求
项目间相互访问需要考虑安全性,所以服务端定义的准入规定:跨域协议(CROS policy),用于规范访问
默认情况下,所有跨域请求不允许访问
解决:
在启动类里添加如下代码:
//跨域访问
@Bean
public WebMvcConfigurer corsConfigurer(){
return new WebMvcConfigurer(){
//重写父类提供的跨域请求处理的接口
@Override
public void addCorsMappings(CorsRegistry registry) {
//添加映射路径
registry.addMapping("/**")
//放行哪些原始域
.allowedOriginPatterns("*")
//是否发送Cookie信息
.allowCredentials(true)
//放行哪些原始域(请求方式)
.allowedMethods("GET","POST","DELETE","OPTIONS")
//放行哪些原始域(头部信息)
.allowedHeaders("*")
//暴露哪些头部信息(因为跨域访问默认不能获取全部头部信息)
.exposedHeaders("Header1","Header2");
}
};
}
展示所有用户
<div id="test">
<ul>
<!-- | 是管道操作符,左边数据作为右边函数的参数值-->
<li v-for="u in users" >
{{u.id}}--{{u.name}}--{{u.age}}--{{u.hobby}}
</li>
</ul>
</div>
<script>
var vv = new Vue({
el:"#test",
data:{
users:[]
},
mounted:function () {
//Ajax异步获取用户列表数据
$.get("http://localhost:8888/list",{},function (dd) {
vv.users = dd;
})
}
});
</script>
用户添加
后端
定义一 个类,用于接收结果
@NoArgsConstructor
@AllArgsConstructor
@Data
public class JsonResult {
private boolean success = true;
private String msg;
}
后端控制器
@RestController
public class MyController {
@Autowired
private IUserService service;
@PostMapping("/update")
public Object update(User user){
//id 是String类型,判空使用StringUtils.hasLength()
if (StringUtils.hasLength(user.getId())){
service.update(user);
}else {
service.save(user);
}
return new JsonResult();
}
}
前端
前端表单提交需要是异步提交
异步提交表单需要使用 jQuery.form.js 静态资源,使用 ajaxForm、ajaxSubmit
原页面
注意 页面跳转 要有 工程路径
<a href="/vuetest/views/_01hello/input.html">添加<a/>
新增页面
注意表单异步提交需要引入 jquery.form.js
注意不可以有id的输入框,输入框会给id赋值""空字符串,会将MongoDB自动生成的id覆盖
<script src="../../vue/vue.js"></script>
<script src="../../vue/jquery-1.7.2.js"></script>
<script src="../../vue/jquery.form.js"></script>
<div id="app">
<form id="formId">
注意不可以有id的输入框,输入框会给id赋值""空字符串,会将MongoDB自动生成的id覆盖
<!-- <input type="hidden" name="id"> -->
名称:<input type="text" name="name"><br/>
年龄:<input type="text" name="age"><br/>
爱好:
<input type="checkbox" name="hobby" value="c">c
<input type="checkbox" name="hobby" value="java">java<br/>
<!-- 添加更新操作,后端返回的都是 JSON 格式
要想跳转去list页面,必须根据返回的结果来决定
所以提交操作不能是同步提交,必须是异步提交
-->
<input type="button" id="btn" @click="submitF" value="提交">
</form>
</div>
<script>
var vv = new Vue({
el:"#app",
methods:{
submitF:function () {
//表单异步提交
//ajaxForm 将表单转换为异步表单,不提交
//ajaxSubmit 将表单转换为异步表单,并提交
$("#formId").ajaxSubmit({
url:"http://localhost:8888/update",
type:"POST",
success:function (data) {
if (data.success){
window.location.href="/vuetest/views/_01hello/hello.html";
}
}
});
}
}
});
</script>
注意
注意,注意不可以有id的输入框,输入框会给id赋值""空字符串,会将MongoDB自动生成的id覆盖
然后抛出异常:
com.mongodb.MongoWriteException:
Write operation error on server localhost:27017.
Write error:
WriteError{code=11000, message='E11000 duplicate key error collection: mongodemo.users index: _id_ dup key: { _id: "" }', details={}}.
出现原因:
是重写了 MongoDb 生成_id的策略,这种情况在$group中很常见的错误
用户编辑
用户编辑
仅仅通过前端页面之间的跳转,实现跳转时用户信息显示在输入框中
步骤:
-
添加编辑链接,直接跳转到编辑页面,不通过后端,跳转时需要带上当前编辑的用户 id
-
为了能在编辑的页面上显示用户的信息,页面上需要拿到地址栏中的参数 id
因为没有经过后端控制器,直接在页面间跳转,需要用到下面获取页面参数的代码
-
通过 id 查询并返回用户对象数据
-
将用户数据回显在页面上
在展示页面上添加编辑链接 (注意写法)
因为要带上 vue 对象中 mounted 属性获取的数据,需要使用 v-bind:href 绑定链接
<li v-for="u in users" >
{{u.id}}--{{u.name}}--{{u.age}}--{{u.hobby}}
<a v-bind:href="'/vuetest/views/_01hello/input.html?uid=' + u.id">编辑</a>
</li>
跳转页面之后,在 input.html 页面需要获取到地址栏上的 uid
需要添加以下函数
获取页面参数
//获取 url 上的请求参数
function getParam() {
//获取问号及问号后面的内容
var url = window.location.search;
//定义一个空对象变量,接收参数内容
var params = new Object();
//判断地址栏上是否有参数
//indexOf:如果查询到返回索引,反之返回-1
if (url.indexOf("?") != -1){
//截取问号后面的内容,再使用 & 分割多个属性
//substr(1):从第二位开始截取到最后
//"a|b|c|d|e|f".split('|'):会得到 a,b,c,d,e,f
//[uid=12312,name=shili]
var arr = url.substr(1).split("&");
for (var i = 0;i < arr.length;i ++){
//使用=分割参数键值对的key、value
//[uid,12312]
var keyValue = arr[i].split("=");
// params[uid] = 12312
// params.uid = 12312
params[keyValue[0]] = keyValue[1];
}
}
return params;
}
//打印得到 {uid: '621c8fe6fb279b933fd47625'}
console.log(getParam());
后端控制器
@GetMapping("/get")
public Object get(String uid){
return service.get(uid);
}
因为需要点击编辑,跳转进 input 页面立即就回显用户数据,所以这个异步提交查询的操作应该是在 mounted 里
同时注意,因为此时添加操作和编辑操作在同一个页面,当编辑操作时才会发起请求,回显用户数据
<script>
//获取 url 上的请求参数
function getParam() {
//获取问号及问号后面的内容
var url = window.location.search;
//定义一个空对象变量,接收参数内容
var params = new Object();
//判断地址栏上是否有参数
//indexOf:如果查询到返回索引,反之返回-1
if (url.indexOf("?") != -1){
//截取问号后面的内容,再使用 & 分割多个属性
//substr(1):从第二位开始截取到最后
//"a|b|c|d|e|f".split('|'):会得到 a,b,c,d,e,f
//[uid=12312,name=shili]
var arr = url.substr(1).split("&");
for (var i = 0;i < arr.length;i ++){
//使用=分割参数键值对的key、value
//[uid,12312]
var keyValue = arr[i].split("=");
// params[uid] = 12312
// params.uid = 12312
params[keyValue[0]] = keyValue[1];
}
}
return params;
}
var vv = new Vue({
el:"#app",
data:{
users:{
hobby:[]
}
},
methods:{
submitF:function () {
//表单异步提交
//ajaxForm 将表单转换为异步表单,不提交
//ajaxSubmit 将表单转换为异步表单,并提交
$("#formId").ajaxSubmit({
url:"http://localhost:8888/update",
type:"POST",
success:function (data) {
if (data.success){
window.location.href="/vuetest/views/_01hello/hello.html";
}
}
});
}
},
mounted:function () {
if (getParam().uid){ //编辑操作才发请求,添加操作时id为null,接口会报错
//异步请求获取参数,用于初始化
$.get("http://localhost:8888/get",
{userId:getParam().uid},function(data){
vv.users = data;
})
}
}
});
</script>
需要将数据会显在输入框中
注意,这里必须是 v-model ,而不是 v-bind ,需要实现双向绑定数据
<div id="app">
<form id="formId">
名称:<input type="text" name="name" v-model="users.name"><br/>
年龄:<input type="text" name="age" v-model="users.age"><br/>
爱好:
<input type="checkbox" name="hobby" value="c" v-model="users.hobby">c
<input type="checkbox" name="hobby" value="java" v-model="users.hobby">java
<br/>
<input type="button" id="btn" @click="submitF" value="提交">
</form>
</div>
注意
1、在编辑操作中,初始化回显数据时,需要判断是否是编辑操作(即id是否为null),如果是添加操作,id就是null
mounted:function () {
if (getParam().uid){ //编辑操作才发请求,添加操作时id为null,接口会报错
//异步请求获取参数,用于初始化
$.get("http://localhost:8888/get",{userId:getParam().uid},function (data) {
vv.users = data;
})
}
}
2、在编辑操作时,初始化了data属性,如下:
data:{
users:[]
}
如果是添加操作,那么这里的 users 就不会有数据(id 为 null,不执行初始化回显数据操作)
这样会导致 users 中的 hobby 字段默认赋值为 true ,就导致复选框要么全部被选中,页面全部不选中,无法单个选择
此时就需要在初始化data里面指定 hobby 字段是一个数组类型
data:{
users:{
hobby:[]
}
}
案例完整代码
目录结构:
hello.html
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"
xmlns:v-html="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../../vue/vue.js"></script>
<script src="../../vue/jquery-1.7.2.js"></script>
</head>
<body>
<a href="/vuetest/views/_01hello/input.html">添加</a>
<div id="test">
<ul>
<li v-for="u in users" >
{{u.id}}--{{u.name}}--{{u.age}}--{{u.hobby}} <a v-bind:href="'/vuetest/views/_01hello/input.html?uid=' + u.id">编辑</a>
</li>
</ul>
</div>
<script>
var vv = new Vue({
el:"#test",
data:{
users:[]
},
mounted:function () {
//Ajax异步获取用户列表数据
$.get("http://localhost:8888/list",{},function (dd) {
vv.users = dd;
})
}
});
</script>
</body>
</html>
input.html
<!DOCTYPE html>
<html lang="en" xmlns:v-bind="http://www.w3.org/1999/xhtml" xmlns:v-model="http://www.w3.org/1999/xhtml"
xmlns:v-html="http://www.w3.org/1999/xhtml" xmlns:v-on="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../../vue/vue.js"></script>
<script src="../../vue/jquery-1.7.2.js"></script>
<script src="../../vue/jquery.form.js"></script>
</head>
<body>
<div id="app">
<form id="formId">
名称:<input type="text" name="name" v-model="users.name"><br/>
年龄:<input type="text" name="age" v-model="users.age"><br/>
爱好:
<input type="checkbox" name="hobby" value="c" v-model="users.hobby">c
<input type="checkbox" name="hobby" value="java" v-model="users.hobby">java<br/>
<!-- 添加更新操作,后端返回的都是 JSON 格式
要想跳转去list页面,必须根据返回的结果来决定
所以提交操作不能是同步提交,必须是异步提交
-->
<input type="button" id="btn" @click="submitF" value="提交">
</form>
</div>
<script>
//获取 url 上的请求参数
function getParam() {
//获取问号及问号后面的内容
var url = window.location.search;
//定义一个空对象变量,接收参数内容
var params = new Object();
//判断地址栏上是否有参数
//indexOf:如果查询到返回索引,反之返回-1
if (url.indexOf("?") != -1){
//截取问号后面的内容,再使用 & 分割多个属性
//substr(1):从第二位开始截取到最后
//"a|b|c|d|e|f".split('|'):会得到 a,b,c,d,e,f
//[uid=12312,name=shili]
var arr = url.substr(1).split("&");
for (var i = 0;i < arr.length;i ++){
//使用=分割参数键值对的key、value
//[uid,12312]
var keyValue = arr[i].split("=");
// params[uid] = 12312
// params.uid = 12312
params[keyValue[0]] = keyValue[1];
}
}
return params;
}
var vv = new Vue({
el:"#app",
data:{
users:{
hobby:[]
}
},
methods:{
submitF:function () {
//表单异步提交
//ajaxForm 将表单转换为异步表单,不提交
//ajaxSubmit 将表单转换为异步表单,并提交
$("#formId").ajaxSubmit({
url:"http://localhost:8888/update",
type:"POST",
success:function (data) {
if (data.success){
window.location.href="/vuetest/views/_01hello/hello.html";
}
}
});
}
},
mounted:function () {
if (getParam().uid){ //编辑操作才发请求,添加操作时id为null,接口会报错
//异步请求获取参数,用于初始化
$.get("http://localhost:8888/get",
{userId:getParam().uid},function (data) {
vv.users = data;
})
}
}
});
</script>
</body>
</html>
MyController
package com.controller;
import com.IUserService;
import com.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class MyController {
@Autowired
private IUserService service;
//注意:项目开发中,一般不会用标准的 RESTful 风格定义路径
@GetMapping("/list")
public Object list(){
return service.list();
}
@PostMapping("/update")
public Object update(User user){
//id 是String类型,判空使用StringUtils.hasLength()
if (StringUtils.hasLength(user.getId())){
service.update(user);
}else {
service.save(user);
}
return new JsonResult();
}
@GetMapping("/get")
public Object getuser(String userId){
return service.get(userId);
}
}
UserServiceImpl
package com;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.MongoTemplate;
import org.springframework.stereotype.Service;
import java.util.List;
// spring封装操作模板,MongodbTemplate 类,直接使用即可
@Service
public class UserServiceImpl implements IUserService{
//直接使用,容器已经创建好了
@Autowired
private MongoTemplate template;
@Override
public void save(User user) {
template.insert(user);
//insert: 若新增数据的主键已经存在,则会报错 DuplicateKeyException
}
@Override
public void delete(String id) {
template.remove(id);
}
@Override
public void update(User user) {
template.save(user); //save: 若新增数据的主键已经存在,则会进行修改
}
@Override
public User get(String id) {
return template.findById(id, User.class);
}
@Override
public List<User> list() {
return template.findAll(User.class);
}
}