文章目录
6.1 Vue简介
Vue (读音 /vjuː/,类似于view) 是一套基于JavaScript,用于构建用户界面的渐进式框架。与其它大型框架不同的是,Vue 被设计为可以自底向上逐层应用。Vue 的核心库只关注视图层,不仅易于上手,还便于与第三方库或既有项目整合。另一方面,当与现代化的工具链 (opens new window)以及各种支持类库 (opens new window)结合使用时,Vue 也完全能够为复杂的单页应用提供驱动。
导入Vue的外部js文件就能够使用Vue框架了。
6.2 声明式渲染
6.2.1 概念
声明式是相对于编程式而言的。
- 声明式:告诉框架做什么,具体操作由框架完成
- 编程式:自己编写代码完成具体操作
渲染
上图含义解释:
- 蓝色方框:HTML标签
- 红色圆形:动态、尚未确定的数据
- 蓝色圆形:经过程序运算以后,计算得到的具体的,可以直接在页面上显示的数据、
- 渲染:程序计算动态数据得到具体数据的过程
6.2.2 Demo
HTML代码
<!-- 使用{{}}格式,指定要被渲染的数据 -->
<div id="app">{{message}}</div>
vue代码
// 1.创建一个JSON对象,作为new Vue时要使用的参数
var argumentJson = {
// el用于指定Vue对象要关联的HTML元素。el就是element的缩写
// 通过id属性值指定HTML元素时,语法格式是:#id
"el":"#app",
// data属性设置了Vue对象中保存的数据
"data":{
"message":"Hello Vue!"
}
};
// 2.创建Vue对象,传入上面准备好的参数
var app = new Vue(argumentJson);
查看声明式渲染的响应式效果
通过验证Vue对象的『响应式』效果,我们看到Vue对象和页面上的HTML标签确实是始终保持着关联的关系,同时看到Vue在背后确实是做了大量的工作。
6.3 Vue基本语法
6.3.1 绑定元素属性
v-bind:HTML标签的原始属性名
HTML代码
<div id="app">
<!-- v-bind:value表示将value属性交给Vue来进行管理,也就是绑定到Vue对象 -->
<!-- vueValue是一个用来渲染属性值的表达式,相当于标签体中加{{}}的表达式 -->
<input type="text" v-bind:value="vueValue" />
<!-- 同样的表达式,在标签体内通过{{}}告诉Vue这里需要渲染; -->
<!-- 在HTML标签的属性中,通过v-bind:属性名="表达式"的方式告诉Vue这里要渲染 -->
<p>{{vueValue}}</p>
</div>
Vue代码
// 创建Vue对象,挂载#app这个div标签
var app = new Vue({
"el":"#app",
"data":{
"vueValue":"太阳当空照"
}
});
6.3.2 双向数据绑定
页面上数据被修改后,Vue对象中的数据属性也跟着被修改
HTML代码
<div id="app">
<!-- v-bind:属性名 效果是从Vue对象渲染到页面 -->
<!-- v-model:属性名 效果不仅是从Vue对象渲染到页面,而且能够在页面上数据修改后反向修改Vue对象中的数据属性 -->
<input type="text" v-model:value="vueValue" />
<p>{{vueValue}}</p>
</div>
Vue代码
// 创建Vue对象,挂载#app这个div标签
var app = new Vue({
"el":"#app",
"data":{
"vueValue":"太阳当空照"
}
});
:value可以省略
<input type="text" v-model="vueValue" />
去除前后空格:trim修饰符
实际开发中,要考虑到用户在输入数据时,有可能会包含前后空格。而这些前后的空格对我们程序运行来说都是干扰因素,要去掉。在v-model后面加上.trim修饰符即可实现。
<input type="text" v-model.trim="vueValue" />
Vue会帮助我们在文本框失去焦点时自动去除前后空格。
6.3.3 条件渲染
根据Vue对象中,数据属性的值来判断是否对HTML页面内容进行渲染。
-
v-if
HTML代码
<div id="app"> <h3>if</h3> <img v-if="flag" src="/pro03-vue/./images/one.jpg" /> <img v-if="!flag" src="/pro03-vue/./images/two.jpg" /> </div>
Vue代码
var app = new Vue({ "el":"#app", "data":{ "flag":true } });
-
v-if和v-else
HTML代码
<div id="app02"> <h3>if/else</h3> <img v-if="flag" src="/pro03-vue/./images/one.jpg" /> <img v-else="flag" src="/pro03-vue/./images/two.jpg" /> </div>
Vue代码
var app02 = new Vue({ "el":"#app02", "data":{ "flag":true } });
-
v-show
HTML代码
<div id="app03"> <h3>v-show</h3> <img v-show="flag" src="/pro03-vue/./images/mi.jpg" /> </div>
Vue代码
var app03 = new Vue({ "el":"#app03", "data":{ "flag":true } });
6.3.4 列表渲染
-
迭代一个简单的数组
HTML代码
<div id="app01"> <ul> <!-- 使用v-for语法遍历数组 --> <!-- v-for的值是语法格式是:引用数组元素的变量名 in Vue对象中的数组属性名 --> <!-- 在文本标签体中使用{{引用数组元素的变量名}}渲染每一个数组元素 --> <li v-for="fruit in fruitList">{{fruit}}</li> </ul> </div>
Vue代码
var app01 = new Vue({ "el":"#app01", "data":{ "fruitList": [ "apple", "banana", "orange", "grape", "dragonfruit" ] } });
-
迭代一个对象数组
HTML代码
<div id="app"> <table> <tr> <th>编号</th> <th>姓名</th> <th>年龄</th> <th>专业</th> </tr> <tr v-for="employee in employeeList"> <td>{{employee.empId}}</td> <td>{{employee.empName}}</td> <td>{{employee.empAge}}</td> <td>{{employee.empSubject}}</td> </tr> </table> </div>
Vue代码
var app = new Vue({ "el":"#app", "data":{ "employeeList":[ { "empId":11, "empName":"tom", "empAge":111, "empSubject":"java" }, { "empId":22, "empName":"jerry", "empAge":222, "empSubject":"php" }, { "empId":33, "empName":"bob", "empAge":333, "empSubject":"python" } ] } });
6.3.5 事件驱动
-
字符串顺序反转
HTML代码
<div id="app"> <p>{{message}}</p> <!-- v-on:事件类型="事件响应函数的函数名" --> <button v-on:click="reverseMessage">Click me,reverse message</button> </div>
Vue代码
var app = new Vue({ "el":"#app", "data":{ "message":"Hello Vue!" }, "methods":{ "reverseMessage":function(){ this.message = this.message.split("").reverse().join(""); } } });
-
获取鼠标移动时的坐标信息
HTML代码
<div id="app"> <div id="area" v-on:mousemove="recordPosition"></div> <p id="showPosition">{{position}}</p> </div>
Vue代码
var app = new Vue({ "el":"#app", "data":{ "position":"暂时没有获取到鼠标的位置信息" }, "methods":{ "recordPosition":function(event){ this.position = event.clientX + " " + event.clientY; } } });
6.3.6 侦听属性
我们希望Vue对象的属性发生变化时,能够做出一些行为,此时需要对Vue对象的属性进行侦听,调用我们准备好的函数。
HTML代码
<div id="app">
<p>尊姓:{{firstName}}</p>
<p>大名:{{lastName}}</p>
尊姓:<input type="text" v-model="firstName" /><br/>
大名:<input type="text" v-model="lastName" /><br/>
<p>全名:{{fullName}}</p>
</div>
Vue代码
在watch属性中声明对firstName和lastName属性进行侦听的函数:
var app = new Vue({
"el":"#app",
"data":{
"firstName":"jim",
"lastName":"green",
"fullName":"jim green"
},
"watch":{
"firstName":function(inputValue){
this.fullName = inputValue + " " + this.lastName;
},
"lastName":function(inputValue){
this.fullName = this.firstName + " " + inputValue;
}
}
});
6.3.7 简化写法
-
v-bind的简化写法
正常写法:
<input type="text" v-bind:value="message" />
简化以后:
<input type="text" :value="message" />
-
v-on的简化写法
正常写法:
<button v-on:click="sayHello">SayHello</button>
简化以后:
<button @click="sayHello">SayHello</button>
6.4 Vue对象生命周期
6.4.1 概念
在我们各种语言的编程领域中,生命周期都是一个非常常见的概念。一个对象从创建、初始化、工作再到释放、清理和销毁,会经历很多环节的演变。比如我们在JavaSE阶段学习过线程的生命周期,今天学习Vue对象的生命周期,将来还要学习Servlet、Filter等Web组件的生命周期。
6.4.2 Vue对象的生命周期
6.4.3 生命周期钩子函数
Vue允许我们在特定的生命周期环节中通过钩子函数来加入我们的代码。
<div id="app">
<p id="content">{{message}}</p>
<button @click="changeValue">点我</button>
</div>
new Vue({
"el":"#app",
"data":{
"message":"hello"
},
"methods":{
"changeValue":function(){
this.message = "new hello";
}
},
// 1.实例创建之前
"beforeCreate":function(){
console.log("beforeCreate:"+this.message);
},
// 2.实例创建完成
"created":function(){
console.log("created:"+this.message);
},
// 3.数据挂载前
"beforeMount":function(){
console.log("beforeMount:"+document.getElementById("content").innerText);
},
// 4.数据已经挂载
"mounted":function(){
console.log("mounted:"+document.getElementById("content").innerText);
},
// 5.数据更新前
"beforeUpdate":function(){
console.log("beforeUpdate:"+document.getElementById("content").innerText);
},
// 6.数据更新之后
"updated":function(){
console.log("updated:"+document.getElementById("content").innerText);
}
});
6.5 书城前后端分离的部分代码
Java代码:
package book.controller;
import book.pojo.Book;
import book.pojo.Cart;
import book.pojo.CartItem;
import book.pojo.User;
import book.service.CartItemService;
import com.google.gson.Gson;
import javax.servlet.http.HttpSession;
public class CartController {
CartItemService cartItemService;
public String index(HttpSession session){
User user = (User) session.getAttribute("currUser");
Cart cart = cartItemService.getCart(user);
user.setCart(cart);
session.setAttribute("currUser", user);
return "cart/cart";
}
public String addCart(Integer bookId, HttpSession session){
User currUser = (User) session.getAttribute("currUser");
Cart cart = currUser.getCart();
cartItemService.addOrUpdateCartItem(new CartItem(new Book(bookId), 1, currUser), cart);
return "redirect:cart.do";
}
public String editCart(Integer cartItemId, Integer buyCount){
cartItemService.updateCartItem(new CartItem(cartItemId, buyCount));
return "";
}
/**
* 通过只发送json字符串与前端进行交互,实现前后端分离
*/
public String cartInfo(HttpSession session){
User user = (User) session.getAttribute("currUser");
Cart cart = cartItemService.getCart(user);
Gson gson = new Gson();
String cartJsonStr = gson.toJson(cart);
return "json:" + cartJsonStr;
}
}
JavaScript代码(Vue+Axios):
window.onload=function (){
let vue = new Vue({
el:"#cart_div",
data:{
cart:{}
},
methods:{
getCart:function (){
axios({
method:"POST",
url:"cart.do",
params:{
operate:'cartInfo'
}
})
.then(function (value){
vue.cart = value.data
})
.catch(function (reason){
});
},
editCart:function(cartItemId, buyCount){
axios({
method:"POST",
url:"cart.do",
params:{
operate:'editCart',
cartItemId:cartItemId,
buyCount:buyCount
}
})
.then(function (value){
vue.getCart();
})
.catch(function (reason){
});
}
},
mounted:function (){
this.getCart();
}
});
}
中央控制器代码:
package myssm.servlet;
import myssm.exception.DispatcherServletException;
import myssm.ioc.BeanFactory;
import myssm.util.StringUtils;
import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
@WebServlet("*.do")
public class DispatcherServlet extends ViewBaseServlet {
private BeanFactory beanFactory;
public DispatcherServlet(){
}
@Override
public void init() throws ServletException {
super.init();
ServletContext servletContext = getServletContext();
Object beanFactoryObj = servletContext.getAttribute("beanFactory");
if (beanFactoryObj != null){
this.beanFactory = (BeanFactory) beanFactoryObj;
} else {
throw new RuntimeException("IOC容器获取失败...");
}
}
@Override
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding("UTF-8");
String servletPath = request.getServletPath();
servletPath = servletPath.substring(1);
servletPath = servletPath.substring(0, servletPath.lastIndexOf(".do"));
// 获取要执行的方法的controller类对象
Object controllerBeanObj = beanFactory.getBean(servletPath);
String operate = request.getParameter("operate");
if(StringUtils.isEmpty(operate)){
operate = "index";
}
try {
// 获取controller类对象中要执行的方法
Method[] methods = controllerBeanObj.getClass().getDeclaredMethods();
for (Method method : methods) {
if (operate.equals(method.getName())){
Parameter[] parameters = method.getParameters();
Object[] parametersValues = new Object[parameters.length];
for (int i = 0; i < parameters.length; i++) {
if ("request".equals(parameters[i].getName())){
parametersValues[i] = request;
} else if ("response".equals(parameters[i].getName())){
parametersValues[i] = response;
} else if ("session".equals(parameters[i].getName())){
parametersValues[i] = request.getSession();
} else {
String parameterName = parameters[i].getName();
String parameterValue = request.getParameter(parameterName);
String typeName = parameters[i].getType().getName();
if (parameterValue != null){
if ("java.lang.Integer".equals(typeName)){
parametersValues[i] = Integer.parseInt(parameterValue);
} else {
parametersValues[i] = parameterValue;
}
}
}
}
method.setAccessible(true);
String methodReturn = (String) method.invoke(controllerBeanObj, parametersValues);
if (StringUtils.isEmpty(methodReturn)){
return;
}
if (methodReturn.startsWith("redirect:")){
String redirectStr = methodReturn.substring("redirect:".length());
response.sendRedirect(redirectStr);
} else if (methodReturn.startsWith("json:")){
// 此处添加返回值为json的判断,直接发送给前端
response.setCharacterEncoding("UTF-8");
response.setContentType("application/json;charset=UTF-8");
String jsonStr = methodReturn.substring("json:".length());
PrintWriter writer = response.getWriter();
writer.print(jsonStr);
writer.flush();
} else{
processTemplate(methodReturn, request, response);
}
}
}
} catch (Exception e) {
e.printStackTrace();
throw new DispatcherServletException("DispatcherServlet出现问题...");
}
}
}