Vue
最近浏览码云上的热门项目,发现很多前端框架都是基于Vue的,作为一名合格的后端开发人员,应该静下心来好好学习一下。争取日后将公司的笨重项目前后端分离,升级重构一波,从被jsp、jquery支配的恐惧中解放出来!
一、Vue简单指令
1、入门 Hello World
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<div>{{1+2}}</div>
<div>{{msg +'--------'+123}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue'
}
});
</script>
</body>
</html>
2、v-cloak指令
可以解决插值闪动的问题
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
[v-cloak]{
display: none;
}
</style>
</head>
<body>
<!--v-cloak用于解决闪动问题,
先通过样式隐藏内容,然后在内存中进行值的替换,
替换好之后显示最终的结果
-->
<div id="app">
<div v-cloak> <!-- v-cloak-->
{{msg}}
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue'
}
});
</script>
</body>
</html>
3、v-text指令
填充纯文本
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div v-text="msg"></div> <!-- 直接引用data中的数据-->
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue'
}
});
</script>
</body>
</html>
4、v-html指令
解析
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- 注意:v-hmtl指令存在安全隐患,慎用 -->
<div id="app">
<div v-text="msg"></div>
<div v-html="msg1"></div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue',
msg1:'<h1>vue</h1>'
}
});
</script>
</body>
</html>
5、v-pre指令
跳过编译
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- v-pre 显示原始的信息,跳过编译过程 -->
<div id="app">
<div v-pre>{{msg}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue',
msg1:'<h1>vue</h1>'
}
});
</script>
</body>
</html>
6、v-once指令
数据响应式相关
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- v-once只渲染一次,
如果显示的信息后续不需要再修改,可以使用v-once
可以提高性能
后面的msg的值如果修改了,渲染的值不变
-->
<div id="app">
<div v-once>{{msg}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue',
msg1:'<h1>vue</h1>'
}
});
</script>
</body>
</html>
7、v-model指令
实现双向数据绑定
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- v-model绑定msg,实现动态变化
input输入框中值的变化会引起msg的变化
-->
<div id="app">
<div>{{msg}}</div>
<input type="text" v-model="msg" />
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue',
msg1:'<h1>vue</h1>'
}
});
</script>
</body>
</html>
二、Vue事件指令
1、v-on指令
绑定事件
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- v-on 事件绑定
简写 @click
-->
<div id="app">
<div>{{num}}</div>
<button type="button" v-on:click="num++">点击1</button>
<!-- 方法的调用可以加() -->
<button type="button" @click="fun1">点击2</button>
<button type="button" @click="fun1()">点击3</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
num:0
},
methods:{ //方法必须定义在methods这个属性当中
fun1:function(){
//这里的this其实是vue的实例对象vm
this.num++;
}
}
});
</script>
</body>
</html>
2、事件绑定的参数传递
使用函数名以及函数名()调用方法的区别与规则
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!--
1、如果事件直接绑定函数名字,那么默认会传递事件对象作为事件函数的第一个参数
2、如果事件绑定函数调用(),那么事件对象就是最后一个参数,名称是 $event
这是这两种方式的区别
-->
<div id="app">
<button type="button" @click="fun1">点击1</button>
<button type="button" @click="fun2(1,2,$event)">点击2</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
num:0
},
methods:{
fun1:function(event){
console.log(event.target.innerHTML)
},
fun2:function(x,y,event){
console.log(x,y)
console.log(event.target.innerHTML)
}
}
});
</script>
</body>
</html>
3、事件修饰符
- .stop 可以阻止事件冒泡行为
- .prevent 可以阻止默认行为
- 其他的事件修饰符参考官方文档
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<!-- 事件冒泡的发生,我点击的是里面的div,但是还是调用了fun1
解决办法使用stop
-->
<div id="app">
<div >{{num}}</div>
<div v-on:click="fun1">
<!-- 使用stop修饰符阻止冒泡 -->
<button type="button" @click.stop="fun2">点击</button>
</div>
<!-- 使用prevent防止跳转到百度页面 -->
<a href="http://www.baidu.com" @click.prevent="fun3">百度一下</a>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
num:1
},
methods:{
fun1:function(){
this.num++
},
fun2:function(){
console.log("hehe")
},
fun3:function(){
console.log("点击了")
}
}
});
</script>
</body>
</html>
4、按键事件修饰符
- .enter 回车键
- .delete 删除键
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- 这里绑定一个删除键的修饰符 -->
用户名:<input type="text" v-model="uname" @keydown.delete="clearContent" /> <br />
<!-- 这里绑定一个回车键的修饰符 @keydown.enter -->
密码:<input type="text" v-model="password" @keydown.enter="submit"/><br />
<button type="button" @click="submit">登入</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
uname:'pihao',
password:'123456'
},
methods:{
submit:function(){
alert("登入成功")
},
clearContent:function(){
this.uname=''
this.password=''
}
}
});
</script>
</body>
</html>
5、属性绑定
v-bind 用于绑定html标签的属性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- v-bind 可以绑定html标签的属性 -->
<a v-bind:href="url">百度一下</a>
<button type="button" @click="change">切换</button>
<!-- v-bind也可以简写 -->
<a :href="url">百度一下2</a>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
url:'http://www.baidu.com'
},
methods:{
//修改url地址
change:function(){
this.url='http://taobao.com'
}
}
});
</script>
</body>
</html>
使用v-bind和事件监听实现数据的双向绑定
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- v-bind 可以绑定html标签的属性 -->
<a v-bind:href="url">百度一下</a>
<button type="button" @click="change">切换</button>
<!-- v-bind也可以简写 -->
<a :href="url">百度一下2</a>
<hr >
<!-- 使用v-bind 与事件监听来实现v-model数据双向绑定 -->
{{msg}} <br>
<input type="text" v-bind:value="msg" v-on:input="handle" /> <br>
<input type="text" v-bind:value="msg" v-on:input="msg=$event.target.value" /><br>
<input type="text" v-model="msg" />
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
url:'http://www.baidu.com',
msg:'hello vue'
},
methods:{
//修改url地址
change:function(){
this.url='http://taobao.com'
},
handle:function(event){
this.msg = event.target.value
}
}
});
</script>
</body>
</html>
6、样式绑定
通过vue来控制CSS的样式
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
.active {
border: 1px solid deeppink;
width: 100px;
height: 100px;
}
.error {
background-color: orange;
}
</style>
</head>
<body>
<div id="app">
<!-- 绑定class属性,对象的规则 -->
<div v-bind:class="{active:isActive,error:isError}">测试1</div>
<button type="button" @click="change">切换</button>
<!-- 绑定class属性,数组的规则 -->
<div v-bind:class="[activeClass,errorClass]">测试2</div>
<button type="button" @click="handle">切换</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
isActive:true,
isError:true,
activeClass:'active',
errorClass:'error'
},
methods:{
change:function(){
//控制isActive的值在true和false之间切换
this.isActive = !this.isActive
this.isError = !this.isError
},
handle:function(){
this.errorClass=''
}
}
});
</script>
</body>
</html>
7、style样式处理
其实就是v-bind绑定style属性
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- 直接绑定style -->
<div :style="styleObj"></div>
<button type="button" @click="change">change</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
styleObj:{
border:'1px solid pink',
width:'200px',
height:'100px'
}
},
methods:{
change:function(){
this.styleObj.width='100px'
}
}
});
</script>
</body>
</html>
三、分支循环结构
1、分支结构
- v-if
- v-else-if
- v-else
- v-show
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div v-if="score >= 90">优秀</div>
<div v-else-if="score < 90 && socre >= 80">良好</div>
<div v-else-if="score < 80 && score >=60 ">及格</div>
<div v-else>不及格</div>
<!--
v-if 和 v-show的区别
v-if控制元素是否渲染到页面
v-show控制元素是否显示(已经渲染到页面上)
-->
<div v-show="flag">测试v-show</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
score:30,
flag:false
}
});
</script>
</body>
</html>
2、循环结构
- v-for遍历数组
- key的作用:帮助Vue区分不同的元素,从而提高性能
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<li v-for="item in fruits">{{item}}</li>
<!-- item和key都是自定义的名字 -->
<li v-for="(item,key) in fruits">{{item +'-----' +key}}</li>
<!-- 绑定的key的属性一般是唯一的id -->
<li :key='item.id' v-for="item in myFruits">{{item.cname +'------'+ item.ename}}</li>
<!-- 对象的遍历 (值,键,索引)-->
<li v-for="(value,key,index) in obj">{{key+"--------"+value+"--------"+index}}</li>
<hr>
<!-- 还能与v-if结合使用 -->
<li v-if="value==24" v-for="(value,key,index) in obj">{{key+"--------"+value+"--------"+index}}</li>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
fruits:['apple','orange','banana'],
myFruits:[{
id:1,
ename:'apple',
cname:'苹果'
},{
id:2,
ename:'orange',
cname:'橙子'
},{
id:3,
ename:'banana',
cname:'香蕉'
}],
obj:{
name:'张三',
gender:'male',
age:24
}
}
});
</script>
</body>
</html>
四、Vue常用特性
- 表单操作
- 自定义指令
- 计算属性
- 过滤器
- 侦听器
- 生命周期
1、表单操作
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<form action="http://www.baidu.com">
<div>
<span>姓名:</span>
<span>
<input type="text" v-model="uname" />
</span>
</div>
<div>
<span>性别:</span>
<span>
<input type="radio" id="male" value=1 v-model="gender"/>
<label for="male">男</label>
<input type="radio" id="female" value=0 v-model="gender"/>
<label for="female">女</label>
</span>
</div>
<div>
<span>爱好:</span>
<span>
<input type="checkbox" id="ball" value=1 v-model="hobby"/>
<label for="ball">篮球</label>
<input type="checkbox" id="sing" value=2 v-model="hobby"/>
<label for="sing">唱歌</label>
<input type="checkbox" id="code" value=3 v-model="hobby"/>
<label for="code">写代码</label>
</span>
</div>
<div>
<span>职业:</span>
<select v-model="occupation">
<option value="0">请选择职业:</option>
<option value="1">java开发工程师</option>
<option value="2">测试工程师</option>
<option value="3">运维工程师</option>
</select>
</div>
<div>
<span>个人简介:</span>
<!-- <textarea v-model="description"></textarea> -->
<textarea v-text="description"></textarea><!-- 这种方式就没有双向绑定 -->
</div>
<div id="">
<!-- 防止跳转到页面 -->
<input type="submit" value="提交" @click.prevent="handle"/>
</div>
</form>
</div>
<script type="text/javascript">
var vm = new Vue({
el:"#app",
data:{
uname:'皮浩',
gender:1,
hobby:[2,3],
occupation:'1',
description:"你好啊"
},
methods:{
handle:function(){
console.log("执行了,并且使用了prevent默认跳转")
console.log("gender是: "+ this.gender)
console.log("hobby是:"+this.hobby.toString())
console.log("occupation是:"+this.occupation)
console.log(this.description)
}
}
})
</script>
</body>
</html>
表单操作里面还有一个表单域修饰符
- number:转化为数值
- trim:去掉开始和末尾的空格
- lazy:将input事件切换为change事件,失去焦点才会触发
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<!-- number修饰符,将字符串转化为数字 -->
<input type="text" v-model.number="age" />
<!-- trim修饰符,取出首尾的空格 -->
<input type="text" v-model.trim="info" />
<!-- lazy 将input事件切换为change事件
简单的说就是失去焦点的时候才会触发,
而input事件是值变化了就会触发
-->
<div>{{msg}}</div>
<input type="text" v-model.lazy="msg"/>
<button type="button" @click="handle">点击</button>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
age:'',
info:'',
msg:''
},
methods:{
handle:function(){
// console.log(this.age+1000)
console.log(this.info.length)
}
}
});
</script>
</body>
</html>
2、自定义指令
Vue内置的指令不满足需求的时候,我们可以自定义指令
内置指令语法规则
# 不带参数的 v-focus
Vue.directive('focus',{
//这里的inserted是固定写法,具体看官网介绍
inserted:function(el){
//获取元素的焦点
el.focus();
}
})
# 带参数的 v-color='msg'
Vue.directive('color',{
inserted:function(el,binding){
//打印binding,发现value属性才是我们想要的值
console.log(binding.value) // pink,在vue的data中的值 msg:‘pink’
//设置背景色
el.style.backgroundColor=binding.value
}
})
实例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="text" v-focus/>
<input type="text" v-color="msg"/>
</div>
<script type="text/javascript">
/* 自定义指令,不带参数 */
Vue.directive('focus',{
inserted:function(el){
//获取元素的焦点
el.focus();
}
})
/* 自定义指令,带参数 */
Vue.directive('color',{
inserted:function(el,binding){
//打印binding,发现value属性才是我们想要的值
console.log(binding.value) // pink
//设置背景色
el.style.backgroundColor=binding.value
}
})
var vm = new Vue({
el: '#app',
data:{
msg:'deeppink'
}
});
</script>
</body>
</html>
局部指令的写法
directive,其实这种写法还更容易接受,就跟data、methods一样
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="text" v-color="msg"/>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'pink'
},
/* 局部指令,把指令当做组件注册到vue中 ,之前的那种写法是全局指令*/
directives:{
color:{
inserted:function(el,binding){
el.style.backgroundColor=binding.value
}
}
}
});
</script>
</body>
</html>
3、计算属性
为何引入计算属性呢?表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简洁,渲染的效率更高
简单的说,计算属性就是基于data中的数据来操作的
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div>{{msg}}</div>
<!-- 现在有一个需求,就是想要反转msg的内容显示 -->
<div>{{msg.split('').reverse().join('')}}</div>
<!-- 使用插值表达式,虽然也可以做到,但是可读性不好,在这里可以
使用计算属性来做到 -->
<div>{{reverseMsg}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue 123'
},
//计算属性,要有返回值
computed:{
reverseMsg:function(){
return this.msg.split("").reverse().join("");
}
}
});
</script>
</body>
</html>
我们发现计算属性和方法是非常类似的,那么两者有什么区别呢?
- 计算属性是基于它们的依赖进行缓存的
- 方法不存在缓存
4、侦听器
侦听器用于监视绑定的数据,数据一旦发生变化就通知侦听器所绑定的方法
使用场景:数据变化时执行异步或者开销大的操作
基本使用
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div>
<span>姓:</span>
<span>
<input type="text" v-model="firstName" />
</span>
</div>
<div>
<span>名:</span>
<span>
<input type="text" v-model="lastName" />
</span>
</div>
<div>全名:{{fullName}}</div>
<!-- ok.现在需求是当firstName或者lastName数据发生变化的时候fullName跟着变化 -->
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
firstName:'pi',
lastName:'hao',
fullName:'pi hao'
},
/* 监听 ,一单监听的值发生变化那么就会触发下面的动作*/
watch:{
//firstName和上面的属性一致,这里的var就是变化后的最新的值
firstName:function(val){
this.fullName = val + " " +this.lastName;
},
lastName:function(val){
this.fullName = this.firstName+ " " +val;
}
},
/* 其实通过计算属性也能完成上面的需求 */
computed:{
//{{allName}}即可
allName:function(){
return this.firstName+" " +this.lastName;
}
}
});
</script>
</body>
</html>
侦听器的综合小案例
做一个登入校验的案例
- 通过v-model实现数据绑定
- 需要提供提示信息
- 需要通过侦听器监听输入的变化
- 需要修改触发的事件(失去焦点才触发)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<span><input type="text" v-model.lazy="uname" /></span>
<span>{{tip}}</span>
</div>
<script type="text/javascript">
/*
1、采用侦听器监听用户名的变化
2、调用后台接口进行验证
3、根据验证的结果调整提示信息
*/
var vm = new Vue({
el: '#app',
data:{
uname:'',
tip:''
},
methods:{
checkName:function(uname){
//调用接口,但是可以使用定时任务的方式模拟接口调用
var that = this; //在setTimeout中的this是window对象
setTimeout(function(){
//模拟接口调用
if(uname == 'admin'){
that.tip = "用户名已经存在,请更换一个";
}else{
that.tip='用户名可以使用'
}
},2000)
}
},
watch:{
uname:function(val){
//调用后台接口验证用户名的合法性
this.checkName(val)
//修改提示信息
this.tip="正在验证..."
}
}
});
</script>
</body>
</html>
5、过滤器
Vue中的过滤器主要是用于格式化数据,比如将字符串首字母大写,将日期格式化为指定的格式等等
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<input type="text" v-model="msg" />
<div >{{msg | upper}}</div>
<div >{{msg | upper | toLower}}</div> <!-- 多级过滤-->
<!-- 还能在绑定属性中使用 -->
<div v-bind:id="msg | toUpper" >测试</div> <!-- 发现id = 'Hello'-->
</div>
<script type="text/javascript">
/**
* 过滤器,全局定义
*/
Vue.filter('toUpper',function(val){
//将首字母大写
return val.charAt(0).toUpperCase() + val.slice(1)
})
//过滤器也支持级联操作,将前一个过滤器的结果再进行一次过滤
Vue.filter('toLower',function(val){
//将首字母大写
return val.charAt(0).toLowerCase()+val.slice(1)
})
var vm = new Vue({
el: '#app',
data:{
msg:'hello'
},
//过滤器也支持局部定义
filters:{
upper:function(val){
return val.charAt(0).toUpperCase()+val.slice(1);
}
}
});
</script>
</body>
</html>
带参数的过滤器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<div>{{date}}</div>
<div>{{date | format('yyyy-MM-dd')}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue',
date: new Date()
},
filters:{
//使用过滤器格式化时间,从第二个参数开始接收 yyyy-MM-dd
format:function(val,arg){
if(arg == 'yyyy-MM-dd'){
var ret = '';
ret += val.getFullYear()+"-"+(val.getMonth()+1)+"-"+val.getDate();
return ret;
}
}
}
});
</script>
</body>
</html>
五、生命周期
详细见官网
- 主要阶段
- 挂载(初始化相关属性)
-
- beforeCreate
- created 在实例创建完之后被立即调用
- beforeMount
- mounted el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子,用的最多
- 更新(元素或组件变更操作)
-
- beforeUpdate
- updated
- 销毁(销毁相关属性)
-
- beforeDestroy
- destroyed
六、综合案例
补充知识(数组相关API)
1、变异方法(修改原有数据)响应式
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
2、替换数组(生成新的数组) 需要重新赋值给data中元素
- filter()
- concat()
- slice()
3、修改响应式数据
- Vue.set(属性名,索引,新值)
- vm.$set(属性名,索引,新值)
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
</head>
<body>
<div id="app">
<li v-for="item in list">{{item}}</li>
<hr >
<div>{{info.name}}</div>
<div>{{info.age}}</div>
<div>{{info.gender}}</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
msg:'Hello Vue',
list:['apple','orange','strobery'],
info:{
name:'zhangsan',
age:24
}
}
});
/**
* 修改值操作
*/
// vm.list[1]='change'; 该种操作不会立即渲染到页面上
// Vue.set(vm.list,1,'change');
// vm.$set(vm.list,0,'hello');
//为info增加一个gender属性
// vm.info.gender='male'; //不会立即渲染到页面上
// Vue.set(vm.info,'gender','male');
vm.$set(vm.info,'gender','male')
</script>
</body>
</html>
图书管理综合案例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<style type="text/css">
.grid{
margin: auto;
width: 500px;
text-align: center;
}
.grid table{
width: 100%;
border-collapse: collapse;
}
.grid th,td{
padding: 10;
border: 1px dashed orange;
height: 35px;
line-height: 35px;
}
.grid th{
background-color: orange;
}
.grid .book{
padding-bottom: 10px;
padding-top: 5px;
background-color: #F3DCAB;
}
.grid .total{
height: 30px;
line-height: 30px;
background-color: hotpink;
}
</style>
</head>
<body>
<div id="app">
<div class="grid">
<div>
<h1>图书管理</h1>
<div class="book">
<div>
<label for="id">
编号:
</label>
<input type="text" id="id" v-model="id" style="width: 30%" :disabled="flag" v-focus/>
<label for="name">
名称:
</label>
<input type="text" id="name" v-model="name" style="width: 30%"/>
<!-- 这里的禁用是为了输入相同的书名的时候,不允许添加 -->
<button type="button" @click="handel" :disabled="btnFlag">提交</button>
</div>
</div>
</div>
<div class="total">
<span>总数:{{sum}}</span>
</div>
<table >
<thead>
<tr>
<th>编号</th>
<th>名称</th>
<th>时间</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr :key='item.id' v-for='item in books'>
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date | format('yyyy-MM-dd')}}</td>
<td>
<a href="#" @click.prevent="toEdit(item.id)">修改</a>
<span>|</span>
<a href="#" @click.prevent="deleteBook(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#app',
data:{
id:'',
name:'',
flag:false,
btnFlag:false,
books:[]
},
computed:{
sum:function(){
//计算图书的总数
return this.books.length;
}
},
methods:{
handel:function(){
//该方法其实可以与编辑图书重用
if(this.flag){
//编辑图书
//根据当前的id去更新数组中的数据,这里的箭头函数中的this就是vue实例的this
this.books.some((item) => {
if(item.id == this.id){
item.name = this.name;
//完成更新操作之后需要终止循环
return true;
}
});
this.flag = false;
}else{
//添加图书
var book = {};
book.id = this.id;
book.name = this.name;
book.date = new Date();
this.books.push(book)
//最后再清空表单
this.id = '';
this.name = '';
}
this.id = '';
this.name = '';
},
toEdit:function(id){
//根据id查询要编辑的数据,可以使用过滤器(这里的book获取到的是一个数组)
var book = this.books.filter(function(item){
return item.id == id
});
console.log(book);
//把获取到的信息填充到表单
this.id = book[0].id;
//禁止修改id
this.flag = true;
this.name = book[0].name
},
deleteBook:function(id){
//删除图书
//先根据id找到索引
// var index = this.books.findIndex(function(item){
// return item.id == id;
// })
//根据索引删除图书
// this.books.splice(index,1);
//-----------------方法2--filter-----------
this.books = this.books.filter(function(item){
return item.id != id;
})
}
},
filters:{
format:function(val,pattern){
if(pattern == 'yyyy-MM-dd'){
return val.getFullYear()+"-"+(val.getMonth()+1)+"-"+val.getDate();
}
}
},
directives:{
focus:{
inserted:function(el){
el.focus()
}
}
},
watch:{
name:function(val){
//验证图书名称是否已经存在
var flag = this.books.some(function(item){
return item.name == val;
})
if(flag){
//图书名称已经存在
if(!flag){
this.btnFlag = true;
}
}
}
},
mounted:function(){
//该生命周期钩子函数被触发的时候,模板已经可以使用了
//一般此时用于调用接口获取后台数据,然后把数据填充到模板
var data = [{
id:1,
name:'三国演义',
date:new Date()
},
{
id:2,
name:'西游记',
date:new Date()
},
{
id:3,
name:'红楼梦',
date:new Date()
}];
this.books = data;
}
});
</script>
</body>
</html>