将网页拆分成多个组件,然后各自开发
最后,再拼接各个组件,通过拼接组件的方式,完成页面的开发 (类似于:Spring拼接组件)
以前,很不规范的人在使用Jquery时,存在大量的针对DOM节点进行频繁的操作,这就导致浏览器在解析节点时,显得非常的卡顿
为了解决这个问题,所以前端提出了 Virtual DOM的说法,Virtual DOM实际上是在内存中,先定义一颗节点树,所有的操作先针对该节点树进行完成,操作完毕之后,再同步到真实DOM对象中,从而提升浏览器在解析节点时的性能浪费
官网下载:https://cn.vuejs.org/
1)引入本地的vue.js文件
2)引入网络,CDN加速vue.js
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.js"></script>
</head>
<body>
<div id="app">
<!-- 声明式渲染 -->
{{t1}}
</div>
</body>
<script>
//创建vue对象,参数是一个配置对象
var v = new Vue({
//用于指定Vue实例服务哪个容器
el:"#app",
//声明的属性值
data:{
t1:"test1",
},
//声明的方法
methods:{
add(){
alert("add....")
},
}
});
//Vue实例的el,也可以是用对象v的原型对象方法$mount(),进行挂载
//v.$mount("#app")
</script>
</html>
注意:一个Vue实例只可以对应一个容器,也就是如果el赋值了一个类选择器,也只会有一个生效;同样多个Vue实例也不可以对应同一个实例。
数据代理:通过对象v
可以调用属性t1
,实际上,对象v
的属性是由Object.defineProperty()
方法完成的对_data
属性(Vue将data
存入了自身的_data
属性)的代理,例如:
let myVue = {
data:{
name: "lucy",
address: "zh"
}
}
Object.defineProperty(myVue,"name",{
get(){
return myVue.data.name
},
set(value){
myVue.data.name = value
}
})
myVue.name = "tom" //此时修改的myVue的name属性就是调用set()方法修改的
console.log(myVue.name) //此时读取的myVue的name属性就是调用get()方法读取的
// tom
<a :href="'detailPage.html?workorderId=' + li.workorderId">详情</a>
mustache语法中,不仅仅可以写变量,也可以写简单的表达式
格式:{{ message }}
标签使用v-pre
属性的话,那么mustache语法不会被解析
标签可以使用v-cloak
属性的话,只有在vue解析该标签的话,这个标签才会进行展示并且删除该属性(需要和css进行搭配,[v-cloak]{display:none}
)
如果标签添加这个属性,那么该标签只会展示首次的数据,不会随变量改变而发生界面改变
v-html可以给当前标签添加文本,并解析html标签元素
v-text可以给当前标签添加文本,但是不解析标签元素
v-on可以给节点添加事件
<!--方法没有形参的情况下()可以省略-->
<button v-on:click="add">botton</button>
<button v-on:click="add(1)">botton</button>
<!-- 简写 -->
<button @click="add">botton</button>
<button @click="add(1)">botton</button>
<div id="app">
<!-- 如果调用方法没有()的话,那么默认方法形参为当次触发事件的event对象 -->
<button @click="cli">click</button>
<!-- 如果需要event对象,也需要其他参数(多参数),那么使用$event -->
<button @click="cli($event,lucy)">click</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
let v = new Vue({
el:"#app",
methods: {
//方法定义了形参
cli:function(event){
console.log(event);
}
}
})
</script>
@click.stop=""
,阻止当前事件的冒泡
@click.prevent=""
,阻止默认事件,例如点击提交按钮后form表单的默认提交事件
@keyup.keyCode|keyAlias=""
,监听键盘的点击
@click.once=""
,当前事件只会触发一次
@click.self=""
,只有当前事件target是当前元素时才会触发
@click.capture=""
,当前元素在捕获阶段处理事件
@click.native=""
,用于给组件绑定原生的事件
v-bind命令的作用: 可以用来定义标签的属性,单向绑定,也就是变量如果发生变化,那么页面随之发生变化,但是如果页面变化,变量不会变化
<input type="text" v-bind:value="t1"/>
<!-- 简写 -->
<input type="text" :value="t1"/>
<style>
.redColor{
color:red;
}
</style>
<div id="app">
<!-- 此处:class可以通过一个对象,来绑定多个class,{类名1:boolean,类名2:boolean} -->
<h1 :class="{redColor:isRed}">hello world!</h1>
<button @click="isRed = !isRed">切换颜色</button>
</div>
<script>
let v = new Vue({
el:"#app",
data:{
isRed:true
}
})
</script>
:class
也可以通过一个数组来动态绑定,:class="['类名1','类名2']"
v-model 主要可以做到:view 与model 之间,双向绑定,只可以作用在表单元素上,也就是model的数据变化,view那边可以跟着变化; view的数据变化,model的数据跟着也会发生变化,实际是v-bind和v-value的结合
<input type="text" v-model="t1"/>
v-if是条件渲染指令,它根据表达式的真假来删除和插入元素
<!--此元素会从dom中删除-->
<input type="text" v-if="1 < 0"/>
v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else>
Not A/B/C
</div>
v-show可以做到DOM节点,进行条件显示,频繁切换建议使用v-show
style="display:none"
来实现的<!--会给此元素加style="display:none"-->
<input type="text" v-show="1 < 0"/>
遍历循环添加元素
<!--goods:[{name:"apple",price:18},{name:"banana",price:22}]-->
<!--g为遍历出来的每个对象,index为索引-->
<tr v-for="(g,index) in goods">
<td>{{g.name}}</td>
<td>{{g.price}}</td>
</tr>
<!--t1:{name:"apple",price:18}-->
<!--value为对象的属性值,key为对象属性名-->
<div v-for="(value,key) in t1">
{{value}}==={{key}}
</div>
是用Vue配置项directives
进行声明
<body>
<div id="app">
<div v-log="123"></div>
</div>
</body>
<script>
Vue.config.productionTip = false;
new Vue({
el:"#app",
directives: {
log(element,binding){
console.log("自定义指令");
console.log(element);
console.log(binding);
}
}
});
//自定义指令
//div dom对象
//{name: 'log', rawName: 'v-log', value: 123, expression: '123', modifiers: {…}, …}
</script>
定义全局指令
Vue.directive("log",function(element,binding){
console.log("自定义指令");
console.log(element);
console.log(binding);
})
生命周期:就是指Vue对象从产生到服务到死亡(GC回收)的完整过程。
在Vue的整个生命周期过程中,跟Servlet一样会执行很多的默认方法(init(),service(),destroy()) ,同样也定义了非常多的默认方法,在前端,他们把这些默认方法,称为:钩子函数
$(function(){ }))
,此时异步请求数据除了vue的方法以外,还可以使用jquery或js的方法来获取
<div id="app">
<input ref="name">
<button @click="m1">get</button>
</div>
<script>
let vm = new Vue({
el:"#app",
methods:{
m1(){
//使用this.$refs.DOM元素ref属性值,获取该DOM元素
console.log(this.$refs.name.value);
}
}
});
</script>
使用watch属性,进行监听属性
var vm = new Vue({
el: '#app',
data: {
counter: 1
}
});
//监听counter这个属性改变前后的值
vm.$watch('counter', function(after, before) {
alert('改变前为:' + before + ' ,改变后为: ' + after);
});
//一个形参代表改变后的值
vm.$watch('counter', function(after) {
alert('改变后为:' + after);
});
var vue = new Vue({
el:"div",
data:{
test:"111",
},
watch:{
test:function (after, before){
alert('改变前为:' + before + ' ,改变后为: ' + after);
}
}
});
立即监听,也就是组件创建完成后就进行一次监听
var vue = new Vue({
el:"div",
data:{
test:"111",
},
watch:{
//此时监听属性的值应该是一个对象,才可以添加配置项
test:{
immediate: true,
handler(after, before){
alert('改变前为:' + before + ' ,改变后为: ' + after);
}
}
}
});
深度监视,也就是可以监听多层结构的数据
var vue = new Vue({
el:"div",
data:{
test:{
a: 1,
b: 2
},
},
watch:{
//此时监听属性的值应该是一个对象,才可以添加配置项
test:{
deep: true,
handler(after, before){
alert('改变前为:' + before + ' ,改变后为: ' + after);
}
}
}
});
虽然在模板中可以直接插入data中的数据,但是有些时候,我们需要对数据进行一些转化,然后才可以使用,或者需要将data中的多个数据结合起来使用,所以需要使用computed实例
<div id="app">
<!-- 使用不需要加小括号,因为是一个属性 -->
<h1>{{fullName}}</h1>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
let v = new Vue({
el:"#app",
data:{
firstName:"Kobe",
lastName:"Bryant"
},
computed:{
//计算属性,结果可以看做为一个属性
fullName:function(){
return this.firstName + " " + this.lastName;
}
}
})
</script>
计算属性的本质是一个数据代理对象,有getter和setter两个方法,我们直接使用属性名,实际是调用了get方法,我们一般也只会实现getter方法,这个属性也成为只读属性
computed:{
fullName{
get:function(){
},
set:function(newValue){
}
}
}
1、使用methods的话,在每次调用,都会执行一次方法
2、使用computed的话,在首次调用,会执行一次,但是后续调用该属性,如果函数里面的数据没有发生改变的话,那么vue会使用自带的缓存
用来对数据进行过滤,例如,价格保留两位小数,并加单位(元):
<div id="app">
<!-- 显示格式为:"data | 过滤器" -->
{{price | showPrice}}
</div>
<script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script>
<script>
let v = new Vue({
el:"#app",
data: {
price:98
},
filters: {
showPrice(price){
return price.toFixed(2) + "元";
}
}
})
</script>
全局过滤器
Vue.filter("showPrice",function(value){
return price.toFixed(2) + "元";
})
计算属性
1、计算属性适合用在单个属性的计算; 2、计算属性只能在单个vue实例中使用; 3、计算属性不能接收参数,只能使用data中定义的变量进行计算; 4、计算属性有缓存机制,可减少调用次数; 5、计算属性相当于定义一个变量
过滤器
1、过滤器适合多个同样计算方法的属性的计算; 2、过滤器可以定义为全局过滤器,在多个vue实例中使用; 3、过滤器可以接收多个参数进行计算; 4、过滤器没有缓存机制,每调用一次都会计算一次; 5、过滤器相当于定义一个特殊的方法
语法:$nextTick(function(){})
作用:在下一次DOM更新结束再执行其回调函数
用处:由于Vue并不是在数据更改后就立刻更新DOM,而是在当前的函数执行完后才更新,所以如果当前操作需要依托更新后的DOM,那么就需要使用这个方法