1.Vue入门
- 遇到的问题汇总:P4-19:20,演示插值闪烁{{}}v-text。P5-14:00,v-on事件传递参数。P7-19:13,创建6个th标签,tr>th*6 + Tab键快速生成。P7-34:00,v-model双向绑定机制。
P7-38:00,v-model指令使用之表单提交。P8-12:50,向名为lists的数组中添加数据:this.lists.push()。P10-13:00,@click="incrementCount(index)"的实现,传递数组下标比较好。19:11,计算总价格。28:34,添加购物车方法。P14-42:00,创建默认实例发送异步请求。
1-1.开发版本与生产版本
//开发版本:
<!-- 开发环境版本,包含了有帮助的命令行警告 -->
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
//生产版本:
<!-- 生产环境版本,优化了尺寸和速度 -->
<script src="https://cdn.jsdelivr.net/npm/vue"></script>
1-2.第一个入门案例
# 没用Vue之前,获取<input id="username"/>标签中的value时,通过js技术和jQuery框架技术:
1.js技术:document.getElementById("username").value
赋值操作:document.getElementById("username").value=jun
2.jQuery技术:$("#username").val()
赋值操作:$("username").val("jun")
<head>
<meta charset="UTF-8">
<title>Vue基础入门</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<span>{{msg}}</span>
<h3><span><div>{{msg}} <span><a href="">{{msg}}</a></span></div></span></h3>
<h4>{{count}}</h4>
<h4>{{count+3}}</h4>
<h4>{{content.toUpperCase()}}</h4>
<h4>{{content.length}}</h4>
<h4>{{content == "hello vue"}}</h4>
<h1>{{user.id}}==={{user.name}}==={{user.age}}==={{user.salary}}</h1>
<h1>{{schools[0]=='白沙洲小学'}}==={{schools[1]}}==={{schools[2].length}}</h1>
<h1>{{users[0].id}}==={{users[2].name}}</h1>
</div>
</body>
</html>
<!--引入vue核心js文件-->
<script src="js/vue.js"></script>
<!--一般把Vue代码放到最后-->
<script>
var app = new Vue({
el:"#app", //el表示element元素,代表vue实例的作用范围
data:{ //data数据:可以在里面自定义各种数据
msg:"junHR",
count:15,
content:"hello vue",
user: {id: 21, name: "junHR", age: 20, salary: 13000.23},
schools: ["白沙洲小学","实验小学","希望小学"],
users:[
{id: 21, name: "junHR", age: 21, salary: 13000.23},
{id: 22, name: "junHR2", age: 22, salary: 14000.23},
{id: 23, name: "junHR3", age: 23, salary: 15000.23},
]
}
}); //创建一个vue实例
</script>
1-2.总结
- 一个页面中只能存在一个Vue实例 不能创建多个vue实例。
- vue实例中el属性代表vue实例的作用范围,日后在vue实例作用范围内可以使用{{data属性中变量名}},直接获取data中变量名对应的属性值。
- vue实例中data属性用来给当前vue实例绑定自定义数据,日后绑定数据可以在vue实例作用范围内直接使用{{变量名}}方式获取。
- 使用{{}}进行data中的数据获取时,可以在{{}}取值语法中进行算数运算、逻辑运算以及调用相关类型的相关方法。
- vue实例中el属性可以书写任何css选择器(class="name",比如el:".name"),但是推荐使用id选择器,因为一个vue实例只能作用于一个具体作用范围。
2.v-text和v-html指令
v-text用来获取data中的数据并以文本的形式渲染到指定标签内部,类似于javascript中的 innerText。v-html用来获取data中的数据,将数据中含有的html标签先解析再渲染到指定标签的内部,类似于javascript中的 innerHTML。
<body>
<div id="app">
<!--
1.使用v-text取值会清空标签原始数据。
2.{{}}(插值表达式)和v-text获取数据的区别在于:
a.使用v-text取值会将标签中原有的数据覆盖,使用插值表达式的形式不会覆盖标签原有的数据。
b.使用v-text可以避免在网络环境较差的情况下出现插值闪烁,{{}}存在插值闪烁。
-->
<h3>{{msg}} junHR {{msg}}</h3>
<h3>junHR <span v-text="msg"></span></h3>
<h3 v-html="msg">junHR</h3>
<span v-text="content"></span><br>
<span v-html="content"></span>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app", //指定vue实例作用范围
data:{ //用来自定义一系列数据
msg:"hello vue",
content:"<a href='http://www.baidu.com'>点我刷新数据</a>"
}
});
</script>
3.v-on事件绑定
3-1.绑定事件的基本语法
<body>
<div id="app">
<!--
js中事件(event)三要素:
1.事件源:发生特定动作html标签
2.事件:发生特定动作事件,如单击事件onclick ondblclick onmouseover onmouseout keyup keydown .....
3.监听器:事件处理程序,一般在js中是事件处理函数 function(){}
原始js中事件处理:<button onclick="test()">点击提交</button> 在script标签中:function test(){alert();}
Vue中的v-on指令,用来给页面中标签绑定事件用的。语法: 在对应标签上使用v-on:事件名="事件处理函数名"
-->
<h2>{{msg}}</h2>
<h3>{{count}}</h3><!--双向绑定机制MVVM=Model<==>ViewModel(视图模型,监听器)<==>View(视图)-->
<button v-on:click="test" v-on:mouseover="test1">点击刷新</button>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app", //指定vue实例作用范围
data:{ //用来自定义一系列数据
msg:"Hello Vue",
count:0,
},
methods:{ //用来给Vue实例绑定一系列函数,方法
test: function () {
//alert("已刷新页面");
console.log(this.msg);
console.log(this.count);
//this.count = this.count + 1;
this.count++;
//触发aa事件
this.aa();
},
test1: function () {
console.log('test1 mouseover');
},
aa: function () {
console.log("aa事件被触发了!");
}
}
});
</script>
3-2.v-on事件传递参数和@简化事件绑定机制
<body>
<div id="app">
<h2>{{msg}}</h2>
<h3>法力值:{{count}}</h3>
<button v-on:click="test">点击法力值+1</button>
<!--简化写法-->
<button @click="test2(5)">点击法力值+5</button>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app", //指定vue实例作用范围
data:{ //用来自定义一系列数据
msg:"Hello Vue",
count:0,
},
methods:{ //用来给Vue实例绑定一系列函数,方法
test: function () { //原始定义函数:函数名:function(){} ==》简化函数:函数名(){}
this.count++;
},
test2(count){
this.count+=count;
}
}
});
</script>
4.v-show、v-if、v-bind
4-1.v-show和v-if指令的使用
<body>
<div id="app">
<h2>{{msg}}</h2>
<!--v-if和v-show指令,用来通过vue方式控制页面中哪些标签展示和隐藏:
语法: 控制那个标签显示隐藏直接在那个标签上 加入v-if="true|false|逻辑运算表达式" v-show="true|false"-->
<h3 name="if" v-if="isShow">{{msg}}</h3>
<h3 name="show" v-show="isShow">{{msg}}</h3>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app", //指定vue实例作用范围
data:{ //用来自定义一系列数据
msg:"Hello Vue",
isShow:false //如果为true,则if和show的语句都能展示
}
});
</script>
区别:
- v-if 底层通过控制dom树上元素节点实现页面标签的展示和隐藏 (dom树)
- v-show 底层通过控制标签css中display属性实现标签的展示和隐藏 (css样式) 使用总结:一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。 因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用v-if较好。 总之就是变化快,用v-show;变化慢,用v-if。
4-2.v-show和v-if案例
<body>
<div id="app">
<h1>{{msg}}</h1>
<!--管理状态-->
<h2 v-show="isShow">{{msg}}</h2>
<button @click="hideH2">点击隐藏h2标签</button>
<button @click="showH2">点击显示h2标签</button>
<button @click="hideShowH2">点击显示|隐藏h2标签</button>
<button @click="isShow=!isShow">点击显示|隐藏h2标签(直接操作data中的属性)</button>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app", //指定vue实例作用范围
data:{ //用来自定义一系列数据
msg:"Hello Vue",
isShow:true
},
methods:{
hideH2() {
this.isShow = false;
},
showH2() {
this.isShow = true;
},
hideShowH2() {
this.isShow = !this.isShow;
// if (this.isShow) {
// this.isShow = false;
// } else {
// this.isShow = true;
// }
}
}
});
</script>
4-3.v-bind指令的使用
<body>
<div id="app">
<h1>{{msg}}</h1>
<!--v-bind:用来绑定html标签中某个属性交给vue实例进行管理-->
<img v-bind:width="width" v-bind:height="height" v-bind:src="src"
@mouseover="changATM" @mouseout="changeMN">
<br>
<button @click="changATM">修改图片</button>
</div>
</body>
</html>
<!--引入vue.js核心文件-->
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",//代表vue实例作用范围
data:{ //用来vue实例绑定数据
msg:"Hello Vue",
src:"https://img2.baidu.com/it/u=1909694165,3400923478&fm=26&fmt=auto&gp=0.jpg",
width:200,
height:200
},
methods: { //用来给vue实例定义一些列的相关方法
changATM(){
this.src= "https://img2.baidu.com/it/u=1597751553,3886687560&fm=26&fmt=auto";
this.width = 150;
},
changeMN(){
this.src="https://img2.baidu.com/it/u=1909694165,3400923478&fm=26&fmt=auto&gp=0.jpg";
this.width=200;
}
}
});
</script>
4-3.v-bind指令的使用之class样式绑定
<head>
<meta charset="UTF-8">
<title>vue课程入门</title>
<style>
.aa{
width: 200px;
height: 200px;
border: 10px red solid;
}
.bb{
width: 200px;
height: 200px;
border: 10px green dashed;
}
</style>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<!--v-bind: 用来将html标签属性绑定vue实例,日后通过修改vue实例中的属性以达到动态修改标签属性的效果-->
<div v-bind:class="cls?'aa':'bb'" @mouseover="changeClsBB" @mouseout="changeClsAA"></div>
<button @click="changeClsAA">修改样式为AA</button>
<button @click="changeClsBB">修改样式为BB</button>
<br>
<img src="https://img2.baidu.com/it/u=1597751553,3886687560&fm=26&fmt=auto"
width="150" v-bind:alt="message">
</div>
</body>
</html>
<!--引入vue.js核心文件-->
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",//代表vue实例作用范围
data:{ //用来vue实例绑定数据
msg:"Hello Vue",
cls: true,
message:"我应该显示的是ATM"
},
methods: { //用来给vue实例定义一系列的相关方法
changeClsAA(){
this.cls = true;
},
changeClsBB(){
this.cls = false;
},
}
});
</script>
4-4.v-bind指令的简化写法
<!--
v-bind:将html标签某个属性绑定给vue实例进行管理
简化写法: :属性名="属性值" (推荐)
-->
<div v-bind:class="cls" @mouseover="cls='bb'" @mouseout="cls='aa'"></div>
<br>
<div :class="cls" @mouseover="cls='bb'" @mouseout="cls='aa'"></div>
5.v-for指令的使用
<body>
<div id="app">
<h1>{{msg}}</h1>
<!--
v-for指令:用来在页面中实现vue中定义数据的遍历
语法: 直接在对应标签上加入v-for指令
a.遍历对象: v-for="value,key,index in data中变量名"
b.遍历数组: v-for="item(普通类型元素),index in data中变量名"
c.遍历数组对象: v-for="item(对象),index in data中变量名"
【注意】:建议尽可能在使用 v-for指令时提供 key的属性。 key属性唯一
-->
<h3>遍历对象</h3>
<span v-for="value,key,index in user"> [{{index}} {{key}} {{value}}] </span>
<h3>遍历数组</h3>
<ul>
<li v-for="item,index in schools">{{index+1}}--- {{item}}</li>
</ul>
<h4>遍历数组里面的对象</h4>
<table border="1" width="100%">
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>工资</th>
<th>城市</th>
<th>操作</th>
</tr>
<tr v-for="user,index in users" :key="user.id" >
<td>{{user.id}}</td>
<td v-text="user.name"></td>
<td v-html="user.age"></td>
<td>{{user.salary}}</td>
<td>{{user.city}}</td>
<td><a href="">删除</a><a href="">修改</a></td>
</tr>
</table>
</div>
</body>
</html>
<!--引入vue.js核心文件-->
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",//代表vue实例作用范围
data:{ //用来vue实例绑定数据
msg:"Hello Vue",
user:{id:21,name:"junHR",age:23,salary:23000.23},//定义一个对象
schools:["河南校区","北京校区","天津校区"],
users:[
{id:21,name:"zhangsan",age:23,salary:23000.23,city:"上海"},
{id:22,name:"lisi",age:24,salary:23000.23,city:"广州"},
{id:23,name:"wangwu",age:25,salary:23000.23,city:"北京"},
]
},
methods: { //用来给vue实例定义一些列的相关方法
}
});
</script>
6.v-model指令使用之表单提交
- 用来将标签value属性绑定给vue实例进行管理。是最能直观体现双向绑定原理的指令。
<body>
<div id="app">
<h1>{{msg}}</h1>
<form>
用户名: <input type="text" v-model="user.username"> <br>
密码: <input type="text" v-model="user.password"><br>
邮箱: <input type="text" v-model="user.email"><br>
QQ: <input type="text" v-model="user.qq"><br>
验证码: <input type="text" v-model="user.code"><br>
<input type="button" @click="reg" value="注册"/>
</form>
</div>
</body>
</html>
<!--引入vue.js核心文件-->
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app", //代表vue实例的作用范围
data:{ //用来给vue实例绑定数据
msg:"hello vue111",
user:{},
},
methods: { //用来给vue实例定义一系列的相关方法
reg(){
console.log(this.user); //1.获取form数据
$.post(url, this.user); //2.发送ajax请求
}
}
});
</script>
7.案例一:实现备忘录功能
<body>
<div id="app">
<!--
1.备忘录列表中的数据交给vue管理(列表中的数据不能写死)
2.添加备忘录
3.删除备忘录
4.清空备忘录
5.备忘录总条数
-->
请输入内容: <input type="text" v-model="content">
<button @click="saveContent">添加到备忘录</button><br>
<ul v-if="lists.length!=0">
<li v-for="(content,index) in lists" :key="index">
{{index+1}}. {{content}}
<a href="javascript:;" @click="delContent(index)">删除</a>
</li>
</ul>
<ul v-if="lists.length==0">
<li><span style="color:red;">当前备忘录中还没有任何数据!!!</span></li>
</ul>
<a v-show="lists.length!=0" href="javascript:;" @click="lists=[]">清空备忘录</a>
<h3>当前备忘录共: {{lists.length}} 条</h3>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{//定义原始备忘列表
lists:["下午高等数学复习!","晚上记100个单词!","上午第三节课签到!"],
content:"",
},
methods:{
saveContent(){//保存方法
if(!this.content){alert('请输入内容...');return false;}
this.lists.push(this.content);
this.content="";
},
delContent(index){
//console.log(index);
this.lists.splice(index,1);//根据下标删除:参数1:从哪个位置开始删除,参数2:删除几个
}
}
})
</script>
8.案例二:购物车功能实现(computed计算属性)
<body>
<div id="app">
<h1>{{msg}}</h1>
编号:<input type="text" v-model="item.id">
名称:<input type="text" v-model="item.name">
价格:<input type="text" v-model="item.price">
数量:<input type="text" v-model="item.count">
<button @click="addCart">添加到购物车</button>
<br><br><br><br>
<table border="1">
<tr> <!--tr>th*5-->
<th>编号</th>
<th>名称</th>
<th>价格</th>
<th>购买数量</th>
<th>小计</th>
</tr>
<tr v-for="item,index in items" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.price}}</td>
<td>
<input type="button" value="+" @click="incrementCount(index)">
{{item.count}}
<input type="button" value="-" @click="decrementCount(index)">
</td>
<td>{{(item.count * item.price).toFixed(2)}}</td>
</tr>
</table>
<!--
computed:计算属性
作用:用来在vue实例中完成相关业务的计算工作。
日后在将某个数据渲染到页面时如果该数据需要经过业务处理之后再渲染就可以使用computed
好处:用来提升vue运行性能,主要使用computed进行计算相关处理,
会将第一次计算结果进行缓存,便于日后页面多次使用。
用法:{{属性名}}
-->
<!-- <h3>总价格: {{totalPrice()}} </h3>-->
<h3>总价格: {{totalPrice}} </h3>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{
msg: "购物车案例",
item:{},
items:[
{id:1,name:"梨子",price:10,count:1},
{id:2,name:"苹果",price:20,count:1},
]
},
methods: {
incrementCount(idx) {
this.items[idx].count++;
},
decrementCount(idx) {
if(!(this.items[idx].count > 1)) {
alert('购买的商品数量不能少于1件!!');
return false;
}
this.items[idx].count--;
},
totalPriceMethods() {
var totalPrice = 0;
for (var i = 0; i < this.items.length; i++) {
totalPrice += this.items[i].count * this.items[i].price;
}
return totalPrice.toFixed(2);
},
addCart() {
if(!this.item.id){alert('请输入编号!');return false;}
if(!this.item.name){alert('请输入名称!');return false;}
if(!this.item.price){alert('请输入价格!');return false;}
if(!this.item.count){alert('请输入数量!');return false;}
if(!(this.item.count > 0)){alert('请输入正确数量!');return false;}
this.items.push(this.item); //放入数组
},
},
computed:{ //计算属性
totalPrice() {
//1.调用methods
return this.totalPriceMethods();
//2.自己计算
// var totalPrice = 0;
// for (var i = 0; i < this.items.length; i++) {
// totalPrice += this.items[i].count * this.items[i].price;
// }
// return totalPrice.toFixed(2);
}
}
})
</script>
9.事件修饰符
<body>
<div id="app">
<h1>{{msg}}</h1>
<button @click="test">点我</button>
<!--事件修饰符
.stop作用: 用来阻止事件冒泡(继续向外传递)
.prevent作用: 用来阻止标签的默认行为
.self作用: 只监听自身标签触发的事件
.once 作用: 该事件只触发一次
语法:@事件名事件修饰符="事件处理函数"======> @click.stop="test"
-->
<h3>stop修饰符</h3>
<div style="width: 200px;height: 200px;background: red"
@click="parent">
<div style="width: 100px;height: 100px;background: aquamarine"
@click.stop="child">
<div style="width: 50px;height: 50px;background:royalblue"
@click="child1">
</div>
</div>
</div>
<h3>prevent修饰符</h3>
<a href="http://www.baidu.com" @click.prevent="testa">点我</a>
<a href="javascript:;" @click.prevent="testa">点我</a>
<h3>self修饰符(事件修饰符可以连用)</h3>
<div style="width: 200px;height: 200px;background: red"
@click.self="parent">
<div style="width: 100px;height: 100px;background: aquamarine"
@click.self.stop="child">
<div style="width: 50px;height: 50px;background:royalblue"
@click="child1">
</div>
</div>
</div>
<h3>once修饰符</h3>
<button @click.once="test">点我我是按钮,我的单击只触发一次</button>
</div>
</body>
</html>
<script src="js/vue.js"></script>
<script>
var app = new Vue({
el:"#app",
data:{msg:"事件修饰符"},
methods:{
test(){console.log("test");},
parent(){console.log("parent");},
child(){console.log("child");},
child1(){console.log("child1");},
testa(){console.log("testa");}
},
computed:{},//用来在vue实例中定义一些列计算属性{{属性名}}
})
</script>
10.axios异步请求技术
- axios用来在前端页面发起一个异步请求,请求之后页面不动,响应回来后刷新页面局部。
11.Vue实例的生命周期函数
- Vue实例从创建到销毁过程中自动触发一些列函数 ====> Vue生命周期函数(钩子)
- Vue 实例生命周期阶段:1.初始化阶段、2.运行阶段、3.销毁阶段
beforeCreate():这个函数执行时,仅仅完成自身内部事件和生命周期函数注入。created():这个函数执行时,完成自身内部事件和生命周期函数注入,包括自定义data methods computed等属性注入和校验工作。beforeMount():这个函数执行时,el指向的html还是一个原始模板,并没有完成数据渲染工作。mounted():这个函数执行时,vue会根据模板创建虚拟dom并进行数据渲染,最后将虚拟dom替换。beforeUpdate():这个函数执行时,data数据发生变化,此时页面数据还是原始数据。updated():这个函数执行时,data数据页面数据保持一致。beforeDestroy():这个函数执行时,vue实例刚刚开始销毁。destroyed():全部销毁。P16-44:00
12.案例三:员工列表展示
- Vue + axios + springboot + mybatis + mysql
- P18-24:37,前端向后端发送请求查询数据并展示到页面。P18-43:00,删除员工信息。P19-13:37,修改一个员工的信息。P19-17:34。P19-21:25,添加的时候不需要id展示。P19-24:09,取消修改,执行添加操作。P19-31:36,请求拦截器,响应拦截器。P20-8:48,bootstrap中自己改变表格边框的操作。
- BootStrap修改页面样式
12-1.CSS页面展示
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Vue练习</title>
<!-- 最新版本的 Bootstrap 核心CSS文件 -->
<link rel="stylesheet"
href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css"
integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu"
crossorigin="anonymous">
</head>
<body>
<div id="app">
<!--bootstrap栅格系统-->
<div class="container">
<!--栅格系统,处理标题-->
<div class="row">
<div class="col-sm-12" style="text-align: center">
<h1>{{msg}}</h1>
</div>
</div>
<!--处理添加按钮-->
<div class="row">
<div class="col-sm-12">
<button class="btn btn-primary btn-sm" @click="addRow">添加</button>
</div>
</div>
<br>
<!--栅格系统,处理表格-->
<div class="row">
<div class="col-sm-12">
<table width="100%" class="table table-striped table-bordered table-hover">
<tr>
<th>编号</th>
<th>姓名</th>
<th>年龄</th>
<th>工资</th>
<th>操作</th>
</tr> <!--:key是给Vue的一个追踪-->
<tr :class="index%2==0?'warning':'danger'" style="text-align: center;" v-for="emp,index in emps" :key="emp.id">
<td>{{emp.id}}</td>
<td>{{emp.name}}</td>
<td>{{emp.age}}</td>
<td>{{emp.salary}}</td>
<td>
<a class="btn btn-danger btn-sm" href="javascript:;" @click="delRow(emp.id)">删除</a>
<a class="btn btn-info btn-sm" href="javascript:;" @click="detailRow(emp.id)">修改</a>
</td>
<!--阻止默认行为-->
<!--<td><a href="" @click.prevent="delRow">删除</a></td>-->
</tr>
</table>
</div>
</div>
<!--处理表单-->
<div class="row">
<div class="col-sm-12">
<form action="">
<div v-show="emp.id"> <!--0 "" null undefined 都为false-->
<div class="form-group">
<label>编号:</label>
<input type="text" class="form-control" readonly v-model="emp.id">
</div>
</div>
<div class="form-group">
<label>姓名:</label>
<input type="text" class="form-control" v-model="emp.name">
</div>
<div class="form-group">
<label>年龄:</label>
<input type="text" class="form-control" v-model="emp.age">
</div>
<div class="form-group">
<label>工资:</label>
<input type="text" class="form-control" v-model="emp.salary">
</div>
<input type="button" class="btn btn-info btn-sm btn-block" value="提交信息" @click="saveOrEdit">
</form>
</div>
</div>
</div>
</div>
</body>
</html>
12-2.前端JS操作
</html>
<script src="js/axios.min.js"></script>
<script src="js/vue.js"></script>
<script>
//创建axios的默认配置对象
var instance = axios.create({
//默认axios希望后端在1s内返回请求数据,业务复杂时无法在1s内返回
timeout:5000, //修改请求的超时时间
baseURL:"http://localhost:8082"
});
//请求拦截器,响应拦截器
instance.interceptors.response.use(function (res) {
return res;
}, function (err) {
alert('后端服务出错了,请稍后再试!');
});
var app = new Vue({
el: "#app",
data: {
msg:"员工列表",
emp:{}, //定义对象
emps:[], //定义员工列表
},
methods: {
addRow() {
this.emp = {}; //赋值为空
},
delRow(id) {
//console.log(id);
//发送axios请求根据id删除员工信息
if (window.confirm("您确定要删除这条数据吗?")) {
var _this = this;
instance.delete("/emps/"+id).then(function (res) {
//alert('删除成功!'); //删除完成之后,希望自动刷新页面。
_this.findAll(); //重新发起一次查询请求
}); //.catch(function (error) {alert('员工信息删除失败,请稍后尝试!');});
}
},
findAll() { //查询所有
//改成箭头函数:
instance.get("/emps").then(res => this.emps=res.data);
//var _this = this; //箭头函数没有自己的this
//instance.get("/emps").then(function (res) {
//console.log(this);
//console.log(_this);
//console.log(res.data);
// _this.emps = res.data;
//});//.catch(function (error) {alert('查询员工列表出现错误,请稍后再试!');});
},
saveOrEdit() { //保存或者编辑员工信息
//console.log(this.emp);
if(!this.emp.name){alert('请输入员工姓名!');return false}
if(!this.emp.age){alert('请输入员工年龄!');return false}
if(!this.emp.salary){alert('请输入员工工资!');return false}
//发送异步请求,保存员工信息
var _this = this;
instance.post("/emps", this.emp).then(function (res) {
//保存完成之后,立马清空输入框中的数据(根据双向绑定原理)
_this.emp = {};
//保存完成之后立马刷新页面
_this.findAll();
});//.catch(function (error) {alert('保存失败,请稍后再试!');});
},
detailRow(id) { //根据id查询一个员工信息
//console.log('查询到的员工id是:' + id);
//发送axios请求,根据id查询一个员工的信息
var _this = this;
instance.get("/emps/" + id).then(function (res) {
//console.log(res.data);
_this.emp = res.data;
});//.catch(function (error) {alert('查询失败,请稍后重试!');});
}
},
computed:{},
created() {
//this.emps = [{id:1,name:"李四",age:24, salary: 5800}];
//发送axios请求查询所有员工列表
this.findAll();
}
});
</script>
12-2.后端数据处理
- EasyCode 快速生成代码
application.properties
server.port=8082
spring.application.name=vue_practice_back
# 配置mybatis
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/vue_chenyn?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=UTF-8&useSSL=true
spring.datasource.username=root
spring.datasource.password=xxx
# 配置mapper文件的位置
mybatis.mapper-locations=classpath:com/jun/mapper/*.xml
mybatis.type-aliases-package=com.jun.entity
启动类 & EmpController.java
@SpringBootApplication
@MapperScan("com.jun.dao")
public class PracticeBackApplication {...}
//com.jun.controller
@RestController
//@RequestMapping("emp")
@CrossOrigin //解决跨域问题
public class EmpController {
private static final Logger log = LoggerFactory.getLogger(EmpController.class);
@Resource
private EmpService empService;
//1.根据id查询员工信息
@GetMapping("/emps/{id}")
public ResponseEntity<Emp> queryById(@PathVariable("id") Integer id) {
return ResponseEntity.ok(this.empService.queryById(id));
}
//2.查询所有员工信息的方法
@GetMapping("/emps")
public List<Emp> emps() {
List<Emp> emps = empService.queryAll();
log.info("查询所有员工列表条数:{}",emps.size());
return emps;
}
//3.根据id删除员工信息
@DeleteMapping("/emps/{id}")
public ResponseEntity<Boolean> deleteById(@PathVariable("id") Integer id) {
log.info("要删除的员工id:{}",id);
return ResponseEntity.ok(this.empService.deleteById(id));
}
//4.保存或者修改员工信息 (如果前端传来的数据中有id,则说明是修改操作;如果没有id,则是添加操作)
@PostMapping("/emps") //需要把JSON转换成后端所接受的对象@RequestBody
public ResponseEntity<Emp> update(@RequestBody Emp emp) {
//利用Spring中的一个工具类。StringUtils
if (StringUtils.isEmpty(emp.getId())) { //添加操作
log.info("当前保存的员工信息:{}"+emp.toString());
return ResponseEntity.ok(this.empService.insert(emp));
} else { //修改操作
log.info("当前修改的员工信息:{}"+emp.toString());
return ResponseEntity.ok(this.empService.update(emp));
}
}
}
EmpDao.xml
//resources:com/jun/mapper
<mapper namespace="com.jun.dao.EmpDao">
<resultMap type="com.jun.entity.Emp" id="EmpMap">
<result property="id" column="id" jdbcType="INTEGER"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="age" column="age" jdbcType="INTEGER"/>
<result property="salary" column="salary" jdbcType="VARCHAR"/>
</resultMap>
<!--查询所有-->
<select id="queryAllList" resultMap="EmpMap">
select * from emp;
</select>
<!--查询单个-->
<select id="queryById" resultMap="EmpMap">
select id, name, age, salary from emp where id = #{id}
</select>
<!--新增所有列-->
<insert id="insert" keyProperty="id" useGeneratedKeys="true">
insert into emp(name, age, salary) values (#{name}, #{age}, #{salary})
</insert>
<!--通过主键修改数据-->
<update id="update">
update emp
<set>
<if test="name != null and name != ''">
name = #{name},
</if>
<if test="age != null">
age = #{age},
</if>
<if test="salary != null and salary != ''">
salary = #{salary},
</if>
</set>
where id = #{id}
</update>
<!--通过主键删除-->
<delete id="deleteById">
delete from emp where id = #{id}
</delete>
</mapper>
13.es6的语法基本使用
- P21-18:57,设置IDEA,让其支持es6的语法格式。
<script>
/**
* 1)es6中变量声明:使用var声明变量存在作用范围混淆问题。
* let:用来声明局部变量。好处:作用范围严谨,从代码声明出开始到代码块结束,
* 一般在声明基本变量时推荐使用let。
* const:用来声明js中的常量。声明js中对象(包括数组)时推荐使用const。好处:一旦被赋值不能被修改。
* 2)es6以前在使用匿名函数时作为参数的时候:function(){}
* 推荐使用es6中箭头函数:(参数,参数)=>{函数体}
*
*/
//3)es6模板字符串,只要在js中写HTML标签的时候就用,使用语法: ` `
let html = "<button onclick=\"test('+id+')\">点我</button>" +
"<button onclick=\"test('+id+')\">点我</button>" ;
console.log(html);
let html1 = `<div>
<h1>Vue Hello</h1>
<button onclick="test()">点击此处</button>
</div>`;
console.log(html1);
//4)es6中关于对象的定义 ,在定义对象时如果对象属性名和变量名一致,写一个即可。
let id = 21;
let name = "张三";
let age = 23;
//es5.x
const emp = {id:id,name:name,age:age};
console.log("es5",emp);
//es6.x
const emp1 = {id,name,age}
console.log("es6",emp1);
//2.演示 => 函数
/** 注意:
* 1.当箭头函数没有参数时或者参数大于1个,必须加()。
* 2.当箭头函数只有一个参数时 () 可以省略不写。
* 3.当函数体中只有一行代码时,函数体{},可以省略不写。
* 4.箭头函数和匿名函数最大的区别:箭头函数没有自己的this,匿名函数存在自己的this。
*/
//axios.get("url").then(function(res){}).catch(function(err){});
//axios.get("url").then((res)=>{}).catch((err)=>{});
//1.演示let、const
function test(){
for (let i = 0; i < 10; i++) {console.log("for in",i);}
//console.log("for out",i); //如果用var i = 0;会污染变量
// const name = "junhr";
// console.log(name);
// name = "lisi";
//const在定义对象时指的是对象的地址不变,但对象中属性可以改变。
const student = {id:21,name:"zhangsan"};
console.log(student);
student.name="zhangsan2";
console.log(student);
student.age=23;
console.log(student);
//const在定义数组时指的数组地址不能改变,但是数组中元素可以改变。
const schools = ["北京","天津"];
console.log(schools);
schools.push("河南");
console.log(schools);
}
test();//调用函数
const app = new Vue({
el:"#app",
data:{
msg:"ES6中的基本语法",
},
methods:{},
computed:{},
});
</script>