Vue常用特性
表单操作
1. 基于Vue的表单操作
- input单行文本
- textarea 多行文本
- select 下拉框
- redio 单选框
- checkbox 多选框
html代码如下:
<div id="app">
<form action="">
<div>
<span>名字:</span>
<span>
<input type="text" v-model="uname">
</span>
</div>
<div>
<span>性别:</span>
<span>
<input type="radio" id="male" v-model="gender" value="1">
<label for="male">男</label>
<input type="radio" id="female" v-model="gender" value="2">
<label for="female">女</label>
</span>
</div>
<div>
<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>
</div>
<div>
<span>职业:</span>
<select v-model="occupation" name="" id="">
<option value="0">请选择职业</option>
<option value="1">教师</option>
<option value="2">软件工程</option>
<option value="3">律师</option>
</select>
</div>
<div>
<span>个人简历:</span>
<textarea v-model="desc"></textarea>
</div>
<div>
<input type="submit" value="提交" @click.prevent="handle">
</div>
</form>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
uname: '神里の凌华',
gender: '2',
hobby: ['2'],
occupation: '0',
desc: '神里凌华大小姐!'
},
methods: {
handle: function () {
console.log(this.uname);
console.log(this.gender);
console.log(this.hobby);
console.log(this.occupation);
console.log(this.desc);
}
}
});
2. 表单域修饰符
- number: 转化为数值
- trim: 去掉开始和结尾的空格
- lazy: 将input事件切换为change事件
html代码如下:
<div id="app">
测试number:<input type="text" v-model.number="age"><br>
测试trim:<input type="text" v-model.trim="info"><br>
测试lazy:<input type="text" v-model.lazy="msg">{{msg}}<br>
<button @click="handle">点击</button>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
age: '',
info: '',
msg: ''
},
methods: {
handle: function () {
console.log(this.age + 2);
console.log(this.info);
console.log(this.msg);
}
}
});
自定义指令
1. 自定义指令的语法规则(获取元素焦点)
js代码如下:
Vue.directive('focus', {
inserted: function (el) {
el.focus();
}
})
const vm = new Vue({
el: '#app',
data: {
name: ''
},
methods: {
handle: function () {
}
}
})
2. 自定义指令用法
html代码如下:
<div id="app">
<input type="text" v-focus>
</div>
3. 带参数的自定义指令(改变元素背景色)
js代码如下:
Vue.directive('color', {
inserted: function (el, binding) {
el.style.backgroundColor = binding.value.color;
}
})
const vm = new Vue({
el: '#app',
data: {
name: ''
},
methods: {
handle: function () {
}
}
})
html代码如下:
<div id="app">
<input type="text" v-color="{color: 'orange'}">
</div>
4. 局部指令
js代码如下:
const vm = new Vue({
el: '#app',
data: {
name: ''
},
methods: {
handle: function () {
}
},
directives: {
focus: {
inserted: function focus(el) {
el.focus();
}
}
}
})
html代码如下:
<div id="app">
<input type="text" v-focus>
</div>
计算属性
1. 为什么需要计算属性
表达式的计算逻辑可能会比较复杂,使用计算属性可以使模板内容更加简洁
html代码如下:
<div id="app">
<div>{{msg}}</div>
<div>{{msg.split('').reverse().join('')}}</div>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
msg: 'Hello'
}
})
2. 计算属性的用法
html代码如下:
<div id="app">
<div>{{msg}}</div>
<div>{{reverseMessage}}</div>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
msg: 'Hello'
},
computed: {
reverseMessage: function () {
return this.msg.split('').reverse().join('');
}
}
})
3. 计算属性与方法的区别
- 计算属性是基于它们的依赖(计算的是已有的数据属性)进行缓存的
- 方法不存在缓存
html代码如下:
<div id="app">
<div>{{msg}}</div>
<div>{{msg}}</div>
<div>{{reverseMessage}}</div>
<div>{{reverseMessage}}</div>
<div>{{reverseString()}}</div>
<div>{{reverseString()}}</div>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
msg: 'Hello'
},
computed: {
reverseMessage: function () {
return this.msg.split('').reverse().join('');
}
},
methods: {
reverseString: function () {
console.log('methods');
return this.msg.split('').reverse().join('');
}
}
})
执行的控制台结果如下:
计算属性调用了两次,如果依赖的数据属性没有变化,只会执行一次,因为有缓存
方法调用了两次,即使依赖的数据属性不变化也会执行了两次,因为没有缓存
侦听器
1. 侦听器的应用场景
数据变化时执行异步或开销较大的操作
2. 侦听器的用法
html代码如下:
<div id="app">
名:<input type="text" v-model="firstName"><br>
姓:<input type="text" v-model="lastName"><br>
全名:<span>{{fullName}}</span>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
firstName: 'Jim',
lastName: 'Green',
fullName: 'Jim Green'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName;
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val;
}
}
})
3. 侦听器案例:验证用户名是否可用
需求:输入框中输入姓名,失去焦点时验证是否存在,如果已存在,提示重新输入,如果不存在,提示可以使用。
实现步骤:
① 通过v-model实现数据绑定
② 需要提供提示信息
③ 需要侦听器监听输入信息的变化
④ 需要修改触发的事件
html代码如下:
<div id="app">
用户名:<input type="text" v-model.lazy="uname">
<span>{{tip}}</span>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
uname: '',
tip: ''
},
methods: {
checkName: function (uname) {
let that = this;
setTimeout(function () {
if (uname == 'admin') {
that.tip = '用户已存在,请更换一个';
} else {
that.tip = '可以使用';
}
}, 2000);
}
},
watch: {
uname: function (val) {
this.checkName(val);
this.tip = '正在校验...';
}
}
})
计算属性与侦听器的区别
计算属性:是computed中定义的属性,这个属性的值 随着依赖的数据属性的变化而调用getter方法返回的,计算属性的方法中,因为使用return立即返回结果,计算属性的结束就是返回的结果,即使计算属性的方法中有异步操作,修改了数据属性也不会影响计算属性的结果,因为结果已经返回了。
侦听器: 是watch中当监听的数据属性发生变化时,会调用相应的方法处理监听器的方法是一直监听者数据属性的变化,并没有计算属性方法结果的这种返回值,不无论是同步或异步,只要修改了数据属性的值,侦听器都会侦听到并调用对应的方法。
过滤器
1. 过滤器的作用是什么?
格式化数据,比如将字符串格式化为首字母大写,将日期格式化为指定的格式等…
2. 自定义过滤器
js代码如下:
Vue.filter('my-filter', function (value) {
//过滤器业务逻辑
return value.toUpperCase();
})
Vue.filter('upper', function (value) {
//过滤器业务逻辑
return value.toUpperCase();
})
Vue.filter('lower', function (value) {
//过滤器业务逻辑
return value.toLowerCase();
})
Vue.filter('formatId', function (value) {
//过滤器业务逻辑
return '00' + value;
})
const vm = new Vue({
el: '#app',
data: {
id: 1,
msg: 'hello W'
}
})
3. 过滤器的使用
html代码如下:
<div id="app">
<div>{{msg}}</div>
<div>{{msg | my-filter}}</div>
<div>{{msg | upper}}</div>
<div>{{msg | upper | lower}}</div>
<div v-bind:id="id | formatId"></div>
</div>
4. 局部过滤器
html代码如下:
<div id="app">
<div>{{msg | upper}}</div>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
id: 1,
msg: 'hello W'
},
filters: {
upper: function (val) {
return val.charAt(0).toUpperCase() + val.slice(1);
}
}
})
5. 带参数的过滤器
html代码如下:
<div id="app">
<div>{{date | format('yyyy-MM-dd')}}</div>
</div>
6. 过滤器的使用
js代码如下:
Vue.filter('format', function (value, arg1) {
//过滤器业务逻辑
let arr = arg1.split('-');
// console.log(arr);
let str = '';
for (let i = 0; i < arr.length; i++) {
let temp = arr[i];
switch (temp) {
case 'yyyy':
str += value.getFullYear() + '年';
break;
case 'MM':
str += value.getMonth() + 1 + '月';
break;
case 'dd':
str += value.getDate() + '日';
break;
}
}
return str;
})
生命周期
1. 主要阶段
-
挂载(初始化相关属性)
① beforeCreate
② created
③ beforeMount
④ mounted
-
更新(元素或组件的变更操作)
① beforeUpate
② updated
-
销毁(销毁相关属性)
① beforeDestroy
② destroy
html代码如下:
<div id="app">
<div>{{msg}}</div>
<button @click="update">更新</button>
<button @click="destroy">销毁</button>
</div>
js代码如下:
const vm = new Vue({
el: '#app',
data: {
msg: '生命周期'
},
methods: {
update: function () {
this.msg = 'hello';
},
destroy: function () {
this.$destroy();
}
},
beforeCreate: function () {
console.log("beforeCreate");
},
created: function () {
console.log("created");
},
beforeMount: function () {
console.log("beforeMount");
},
mounted: function () {
console.log("mounted");
},
beforeUpdate: function () {
console.log("beforeUpdate");
},
updated: function () {
console.log("updated");
},
beforeDestroy: function () {
console.log("beforeDestroy");
},
destroyed: function () {
console.log("destroyed");
}
})
综合案例
图书管理
补充知识(数组相关API)
css代码如下:
table {
text-align: center;
border: 1px dashed #F4DBA7;
}
tr, th, td {
border: 1px dashed #F4DBA7;
}
.active {
background-color: #F4DBA7;
}
tr.active td {
border-bottom: 1px solid greenyellow;
}
html代码如下:
<div id="app">
<h2 style="text-align: center;">图书管理</h2>
<table id="booklist" cellpadding="5" cellspacing="0" width="40%" align="center">
<tbody>
<tr :class="{active : isActive}">
<td colspan="4">
编号:<input type="text" v-model="id">
名称:<input type="text" v-model="name">
<input type="button" value="提交" @click="add">
</td>
</tr>
<tr :class="{active : isActive}">
<th>编号</th>
<th>名称</th>
<th>时间</th>
<th>操作</th>
</tr>
<tr v-for="item in list" :key="item.id">
<td>{{item.id}}</td>
<td>{{item.name}}</td>
<td>{{item.date | format('yyyy-MM-dd-hh-mm-ss')}}</td>
<td><a href="#" @click="modify(item)">修改</a> | <a href="#" @click="del(item.id)">删除</a></td>
</tr>
</tbody>
</table>
</div>
js代码如下:
//处理日期的过滤器
Vue.filter('format', function (value, arg1) {
//过滤器业务逻辑
let arr = arg1.split('-');
let str = '';
for (let i = 0; i < arr.length; i++) {
let temp = arr[i];
switch (temp) {
case 'yyyy':
str += value.getFullYear() + '-';
break;
case 'MM':
str += value.getMonth() + 1 + '-';
break;
case 'dd':
str += value.getDate() + ' ';
break;
case 'hh':
str += value.getHours() + ":";
break;
case 'mm':
str += value.getMinutes() + ":";
break;
case 'ss':
str += value.getSeconds();
break;
}
}
return str;
})
const vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
flag: false, //编辑的状态
isActive: true,
list: [{
id: 1,
name: '三国演义',
date: new Date()
}, {
id: 2,
name: '西游记',
date: new Date()
}, {
id: 3,
name: '红楼梦',
date: new Date()
}, {
id: 4,
name: '水浒传',
date: new Date()
}]
},
methods: {
add: function () {
// 判断是否点击了编辑按钮
if (this.flag) {
//先删除数据
this.del(this.id);
//插入数据
this.list.splice(this.id - 1, 0, { id: this.id, name: this.name, date: new Date()});
this.flag = false;
} else {
//添加记录到list中
this.list.push({
id: this.id,
name: this.name,
date: new Date()
});
}
//将输入框的内容清空
this.id = this.name = '';
},
modify: function (obj) {
this.flag = true;
this.id = obj.id;
this.name = obj.name;
},
del: function (id) {
// some方法循环数组,返回true可以终止循环
// this.list.some((item, i) => {
// if (item.id == id) {
// // i是需要删除元素的数组下标 移除1条记录
// this.list.splice(i, 1);
// // 返回true 终止循环
// return true;
// }
// });
// 通过findIndex方法获取需要删除记录的数组下标
let index = this.list.findIndex(item => {
if (item.id == id) {
return true;
}
});
// 通过splice方法来移除记录
this.list.splice(index, 1);
}
}
})