一、MVVM 模型
- MVVM 最早由微软提出来,它借鉴了桌面应用程序的 MVC 思想,AngularJS,KnockoutJS、Vue 等都是比较成熟的 MVVM 框架;
- Model ---- 在前端页面中,把 Model 用纯 JavaScript 对象表示;
- View ---- 页面展示,是纯 Html;
- ViewModel ---- 负责把 Model 的数据同步到 View 显示出来,还负责把 View 的修改同步回 Model;
1.展示动态页面
1.1方式一
页面控制器,返回页面,将页面展示的数据包装到modelmap中:
1.2方式二
页面控制器(返回页面)
页面数据由数据接口提供
展示页面 : 通过Ajax方式,调用数据接口 (从页面表单获得值,封装到对象,Ajax提交对象,渲染后台返回的结果) ---------- 局部渲染到页面上
1.3方式三(重点)
页面控制器(返回页面)
页面数据由数据接口提供
展示页面 : 通过Ajax方式,调用数据接口(Vue 的双向渲染技术 -------直接提交vue 定义的对象-------Ajax返回结果集只需赋值动作即可)
二、vue简介
- Vue 是一套用于构建用户界面的渐进式 JavaScript 框架,易用、灵活、高效;
- 轻量级框架:只关注视图层,是一个构建数据的视图集合,大小只有几十 KB;
- 简单易学:国人开发,中文文档,不存在语言障碍 ,易于理解和学习;
- 双向数据绑定:保留了 Angular 的特点,在数据操作方面更为简单;
- 组件化:保留了 React 的优点,实现了 Html 的封装和重用,在构建单页面应用方面有着独特的优势;
- 视图,数据,结构分离:使数据的更改更为简单,不需要进行逻辑代码的修改,只需要操作数据就能完成相关操作;
- 虚拟 DOM:Dom 操作是非常耗费性能的, 不再使用原生的 Dom 操作节点,极大解放 Dom 操作,但具体操作的还是 Dom 不过是换了另一种方式;
- 运行速度更快:相比较与 React 而言,同样是操作虚拟 Dom,就性能而言,Vue 存在很大的优势;
- 在学习之前,需要了解以下内容:
-
- 你会用 Html + Css + JavaScript 写一些网页;
- 你知道什么是 DOM 和 BOM ;
-
-
- DOM(Document Object Model):文档对象模型,简单来说就是我们代码,<html>、<head>、<body>,这些 HTML 标签和属性都是其中的组成部分;
- BOM(Browser Object Model):浏览器对象模型,其核心是浏览器窗口(Window),Window 包含 DOM 对象,以及 Screen、History、Location Navigator、Frame 等;
-
- 你知道 Vue.js 是一个框架而不是一个新语言;
三、安装
- 本地:<script src="/jsvue.min.js" type="text/javascript"></script>;
- ==========================================================
- ***CND(内容分发网络):
- <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js" type="text/javascript"></script>; 用这种方式
- =====================================================================
- Npm(NodeJs 管理工具,安装比较慢):npm install vue;
- --------------
- 要使用 Vue 标签,需要在 Html 标签引入相应的命名空间:xmlns:v-bind="http://www.w3.org/1999/xhtml";
四、Vue 实例
1.定义模型
- 每一个 Vue 应用都需要一个实例化来实现,用 new Vue({}) 新建 Vue 实例,初始化时,需要指定的参数;
-
- el:指定页面元素 id;
- data(optional):定义 vue 实例属性,和页面元素一一绑定;
- methods(optional):定义页面事件对应的函数;
- ……
<script>
var myVue = new Vue({
el:"#myVue",// 绑定div
//实例属性
data:{
company:"SFAC",
user:{
name:"ljr",
age:20,
gender:"female",
roles:[],
city:"成都",
},
roles:[
{id:1,name:"admin"},
{id:2,name:"manager"},
{id:3,name:"staff"}
],
genders:["male","female"],
cities:[
{id:1,anme:"成都"},
{id:2,anme:"重庆"},
{id:3,anme:"武汉"},
{id:4,anme:"深圳"},
{id:5,anme:"杭州"}
]
},
//函数
methods:{
test1:function(){
console.log("This is test 1 function");
},
test2:function(){
console.log("This is test 2 function");
},
}
});
</script>
2.数据单向绑定
- Text:{{}} 双大括号语法,页面文本绑定 Vue Data 中的数据;
-
- <h3>{{title}}</h3>
- Html:v-html 语法,页面绑定 Html 内容;
-
- <p>Using v-html directive: <span v-html="rawHtml"></span></p>
- Attribute:v-bind:(缩写:)语法,页面标签属性绑定 Vue Data 中的数据,属于 Vue 到 Dom 的单向绑定;
-
- <p>UserName: <input type="text" v-bind:value="user.userName" /></p>
- <p>Password: <input type="password" :value="user.password" /></p>
- <div v-bind:id="'list-' + id"></div>
- 对象语法
-
- <div v-bind:class="{ active: isActive }"></div>
- <div v-bind:class="{ active: isActive, 'text-danger': hasError }" ></div>
- <div v-bind:class="classObject"></div>
- <div v-bind:style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
- <div v-bind:style="styleObject"></div>
- 数组语法
-
- <div v-bind:class="[activeClass, errorClass]"></div>
- <div v-bind:class="[isActive ? activeClass : '', errorClass]"></div>
- <div v-bind:class="[{ active: isActive }, errorClass]"></div>
- <div v-bind:style="[baseStyles, overridingStyles]"></div>
- JavaScript:Vue 对于所有的数据绑定,提供了完全的 JavaScript 表达式支持;
-
- {{ number + 1 }}
- {{ ok ? 'YES' : 'NO' }}
- {{ message.split('').reverse().join('') }}
<p>========数据的单项绑定===========</p>
<h4>{{company}}</h4>
<p>{{user.name}}</p>
<p>{{user.age}}</p>
<p>{{user.gender}}</p>
<p>{{user.roles}}</p>
<p>{{user.city}}</p>
<form>
<input type="text" :value="user.name"/>
</form>
3.数据双向绑定
v-model 语法:页面表单控件绑定 Vue Data 中的数据,属于 Vue 和 Dom 的双向绑定;
v-model 修饰符 .lazy: change 事件之后进行同步,<input v-model.lazy="msg">; .number:自动将用户的输入值转为数值类型,<input v-model.number="age" type="number">; .trim:自动过滤用户输入的首尾空白字符,<input v-model.trim="msg">;
<h3>This is Vue test page.</h3>
<p>========数据的双项绑定===========</p>
<form>
<p><input type="text" v-model.trim="user.name" /></p>
<p><input type="number" v-model.number="user.age"/></p>
<p><input type="radio" value="male" v-model="user.gender"/> 男</p>
<p><input type="radio" value="female" v-model="user.gender"/> 女</p>
<p>
<input type="checkbox" value="1" v-model="user.roles"> admin
<input type="checkbox" value="2" v-model="user.roles"> manager
<input type="checkbox" value="3" v-model="user.roles"> staff
</p>
<p>
<select v-model="user.city">
<option value="1" >成都</option>
<option value="2" >重庆</option>
<option value="3" >武汉</option>
<option value="4" >深圳</option>
<option value="5" >杭州</option>
</select>
</p>
</form>
4.条件渲染
- v-if:指令用于条件性地渲染一块内容;
-
- <div v-if="type == 'A'">A</div>
- <div v-else-if="type == 'B'">B</div>
- <div v-else>Not A/B</div>
- <div v-for="(item, index) in data" v-if="index < 6">
- v-show:元素始终会被渲染并保留在 DOM 中,v-show 只是简单地切换元素的 CSS 属性中的 display;
-
- <h1 v-show="ok">Hello!</h1>
- 区别
-
- v-if 是“真正”的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建;
- v-if 也是惰性的:如果在初始渲染时条件为假,则什么也不做,直到条件第一次变为真时,才会开始渲染条件块;
- 相比之下,v-show 就简单得多。不管初始条件是什么,元素总是会被渲染,并且只是简单地基于 CSS 进行切换;
- 一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好;
<p>=========条件渲染===========</p>
<p><span v-if = "user.name == 'ljr'">今天是个好日子</span></p>
<p><span v-if = "user.name == 'hfa'">今天是个雨天......</span></p>
5.列表渲染
- v-for:页面标签绑定 Vue Data 中的 List 数据,循环处理;
- 使用 v-for 的时候需要添加 key 属性,Vue 在更新渲染 Dom 的时候是根据新旧 Dom 树进行对比的,使用 key 来给每个节点做一个唯一标识;
<!--列表渲染-->
<p>========列表渲染===========</p>
<p>
<span v-for="item in genders">
<input type="radio" :value="item" :key="item" v-model="user.gender"/> {{item}}
</span>
</p>
<p>
<span v-for="item in roles">
<input type="checkbox" :value="item.id" :key="item.id" v-model="user.roles"> {{item.name}}
</span>
</p>
<p>
<select v-model="user.city">
<option v-for="(item,index) in cities " :value="item.id" :key="item.id" >{{item.name}} -- {{index}}}</option>
</select>
</p>
<p>
<ul>
<li v-for="item in cities" id="item.id" :key="item.id">{{item.name}}</li>
</ul>
</p>
<p>
<table>
<tr>
<td>ID</td>
<td>Name</td>
</tr>
<tr v-for="item in cities">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
</tr>
</table>
</p>
6.事件绑定
- v-on:(缩写@),页面标签绑定事件,执行 JS 或调用函数;
-
- 绑定多个函数:@click="initSortingStatistics(), initScatterStatistics()";
<p>========事件绑定========== </p>
<p>
<button @click="test1">test1</button>
</p>
<!-- 带参数的事件绑定 -->
<p>
<button name="btn" data="qqqqqqq" @click="test2">test2</button>
</p>
//函数
methods:{
test1:function(){
console.log("This is test 1 function");
},
test2:function(even){
console.log(event.currentTarget.name);
console.log(event.currentTarget.attributes.data.value);
console.log("This is test 2 function");
,
}
7.总体代码
<div id="myVue" class="right_col" role="main">
<h3>This is Vue test page.</h3>
<p>========数据的单项绑定===========</p>
<h4>{{company}}</h4>
<p>{{user.name}}</p>
<p>{{user.age}}</p>
<p>{{user.gender}}</p>
<p>{{user.roles}}</p>
<p>{{user.city}}</p>
<form>
<input type="text" :value="user.name"/>
</form>
<p>========数据的双项绑定===========</p>
<form>
<p><input type="text" v-model.trim="user.name" /></p>
<p><input type="number" v-model.number="user.age"/></p>
<!-- <p><input type="radio" value="male" v-model="user.gender"/> 男-->
<!-- <input type="radio" value="female" v-model="user.gender"/> 女-->
<!-- </p>-->
<!--列表渲染-->
<p>========列表渲染===========</p>
<p>
<span v-for="item in genders">
<input type="radio" :value="item" :key="item" v-model="user.gender"/> {{item}}
</span>
</p>
<p>
<span v-for="item in roles">
<input type="checkbox" :value="item.id" :key="item.id" v-model="user.roles"> {{item.name}}
</span>
</p>
<p>
<select v-model="user.city">
<option v-for="(item,index) in cities " :value="item.id" :key="item.id" >{{item.name}} -- {{index}}}</option>
</select>
</p>
<p>
<ul>
<li v-for="item in cities" id="item.id" :key="item.id">{{item.name}}</li>
</ul>
</p>
<p>
<table>
<tr>
<td>ID</td>
<td>Name</td>
</tr>
<tr v-for="item in cities">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
</tr>
</table>
</p>
<!-- <input type="checkbox" value="1" v-model="user.roles"> admin-->
<!-- <input type="checkbox" value="2" v-model="user.roles"> manager-->
<!-- <input type="checkbox" value="3" v-model="user.roles"> staff-->
<!-- <p>-->
<!-- <select v-model="user.city">-->
<!-- <option value="1" >成都</option>-->
<!-- <option value="2" >重庆</option>-->
<!-- <option value="3" >武汉</option>-->
<!-- <option value="4" >深圳</option>-->
<!-- <option value="5" >杭州</option>-->
<!-- </select>-->
<!-- </p>-->
</form>
<p>=========条件渲染===========</p>
<p><span v-if = "user.name == 'ljr'">今天是个好日子</span></p>
<p><span v-if = "user.name == 'hfa'">今天是个雨天......</span></p>
<p>========事件绑定========== </p>
<p>
<button @click="test1">test1</button>
</p>
<!-- 带参数的事件绑定 -->
<p>
<button name="btn" data="qqqqqqq" @click="test2">test2</button>
</p>
</div>
<script>
var myVue = new Vue({
el:"#myVue",// 绑定div
//实例属性
data:{
company:"SFAC",
user:{
name:"ljr",
age:20,
gender:"female",
roles:[1,2],
city:1
},
roles:[
{id:1,name:"admin"},
{id:2,name:"manager"},
{id:3,name:"staff"}
],
genders:["male","female"],
cities:[
{id:1,name:"成都"},
{id:2,name:"重庆"},
{id:3,name:"武汉"},
{id:4,name:"深圳"},
{id:5,name:"杭州"}
]
},
//函数
methods:{
test1:function(){
console.log("This is test 1 function");
},
test2:function(even){
console.log(event.currentTarget.name);
console.log(event.currentTarget.attributes.data.value);
console.log("This is test 2 function");
},
}
});
</script>
8.监听器
commanyError:监听company
userNameError:用户名监听
<p>========数据的单项绑定===========</p>
<p><span style="color: red">{{commanyError}}</span></p>
<h4>{{company}}</h4>
<p><span style="color: red">{{userNameError}}</span></p>
<p>{{user.name}}</p>
<p>{{nameComputed}}</p>
<p>{{user.age}}</p>
<p>{{user.gender}}</p>
<p>{{user.roles}}</p>
<p>{{user.city}}</p>
<form>
<input type="text" :value="user.name"/>
</form>
data:{
company:"SFAC",
commanyError:"",
user:{
name:"ljr",
age:20,
gender:"female",
roles:[1,2],
city:1
},
userNameError:"",
roles:[
{id:1,name:"admin"},
{id:2,name:"manager"},
{id:3,name:"staff"}
],
watch:{
company(newValue,oldValue){
this.commanyError = newValue.length > 6 ?"公司名太长":"";
},
'user.name'(newValue,oldValue){
this.userNameError = newValue.length > 6 ?"用户名太长":"";
}
},
8.计算器
computed
<p><span style="color: red">{{userNameError}}</span></p>
<p>{{user.name}}</p>
<p>{{nameComputed}}</p>
<p>{{user.age}}</p>
<p>{{user.gender}}</p>
<p>{{user.roles}}</p>
<p>{{user.city}}</p>
computed:{
nameComputed:function () {
return this.user.name.toLocaleUpperCase();
}
}
9.过滤器filters
//局部过滤器
filters:{
filter2:function (value) {
if (!value){
return "";
}
return value.replaceAll("b","-");
}
}
});
Vue.filter("filter1",function (value) {
//全局过滤器
if (!value){
return "";
}
return value.replaceAll("a","*")
});
<p>{{user.name | filter1 | filter2}}</p>
10、过渡 & 动画
- Vue 在插入、更新或者移除 DOM 时,提供多种不同方式的应用过渡效果,Vue 提供了内置的过渡封装组件,该组件用于包裹要实现过渡效果的组件;
- 语法格式:<transition name = "nameOfTransition"><div></div></transition>;
- Vue 在元素显示与隐藏的过渡中,提供了 6 个 class 来切换:
-
- v-enter:定义进入过渡的开始状态;
- v-enter-active:定义进入过渡生效时的状态;
- v-enter-to: 2.1.8 版及以上 定义进入过渡的结束状态;
- v-leave: 定义离开过渡的开始状态;
- v-leave-active:定义离开过渡生效时的状态;
- v-leave-to: 2.1.8 版及以上 定义离开过渡的结束状态;
- 注:在实际的样式中 ,v 替换为 nameOfTransition;
<p>==============动画==============</p>
<p><button @click="show = !show">点击改变动画</button></p>
<transition name="fade">
<p v-show="show">显示动画</p><!-- 进行隐藏-->
</transition>
===============================
<style>
.fade-enter-active, .fade-leave-active {
transition: opacity 2s
}
.fade-enter, .fade-leave-to {
opacity: 0
}
</style>
=================================
show:true,
五、生命周期
- beforeCreate:在实例初始化之前,数据观测 data observer 和 event/watcher 事件配置之前被调用;
- created:在实例创建完成后被立即调用;
- beforeMount:在挂载开始之前被调用,相关的 render 函数首次被调用;
- mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子;
- beforeUpdate:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。 你可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程;
- updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子;
- beforeDestroy:实例销毁之前调用;
- destroyed:Vue 实例销毁后调用,调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁,该钩子在服务器端渲染期间不被调用;
- errorCaptured
created:vue初始化完成,将vue种赋值的函数赋值给window
mounted:vue实例和页面进行绑定完成
updated:
destroyed:
$(function () {
alert("111111111111");
test1();
});
========================
//vue实例初始化完成
create(){
window.test1=this.test1();
},
//vue实例加载完成,并且和页面元素进行绑定成功
mounted(){
this.test1();
}
六、一个页面的开发流程
1.写后台接口
把所有的可能涉及的接口全部写出来,顺序:
Entity------dao----service-----serviceImpl-----controller
2.页面控制器
通过拆解模板,然后修改成我们需要的页面,进行vue的书写,定义作用范围,数据模板,函数和生命周期。创建组件与编码,配置组件路由。
3.数据交互
从后面
渲染数据
七、表格处理
- 表格处理
页面渲染:当前页表格数据、分页、配许、查询、改变页长
新增
===================08.30====================
表格处理
修改:
删除:
上传图片: - 步骤
1.记载页面--------
- 加载vue实例------
- vue实例和页面进行绑定------
- 调用/api/users接口,取得列表数据----
- 封装行数据结构------
- 将行数据封装表格数据-----
- 数据回显
八、举例资源权限的增删改查
1.写与该页面相关的后台接口
127.0.0.1/api/resouce---------- post resouce json result ----新增
127.0.0.1/api/resouce---------- put resouce json result ----修改
127.0.0.1/api/resource/{id} ---------- delete id path result ----删除
127.0.0.1/api/resouce/{id} ---------- get id path resouce ----根据id查询resouce
127.0.0.1/api/resouces --------- post search json pageinfo ----多条件查询resouces分页信息
127.0.01/api/resouces ------------get null List<resouce> -----查询所有的resouces
2.准备resource页面
表格页面,去模板去找
引入css、js
引入表格代码段
准备页面控制器
修改sidebar,该也页面的链接
测试
3.数据交互
表格展示:初始化表格,按钮提交
新增:
新增按钮 --------模态了 --------新增面板
提交新增数据
修改功能
删除功能