Vue常用特性
一.表单基本操作
1. 单选框操作
<head>
<meta charset="utf-8" />
<title>vue特性</title>
</head>
<body>
<!-- 测试 vue input 单选框选中 -->
<div id="app">
<!-- 在vue根据后台数据来选中男女以前基本使用if判断 -->
<div v-if="gender===1">
<!-- 如果为1让男选中 -->
<input type="radio" name="" id="man" value="1" checked="checked" />
<label for="man">男</label>
</div>
<div v-else>
<!-- 如果为1让男选中 -->
<input type="radio" name="" id="man" value="1" />
<label for="man">男</label>
</div>
<div v-if="gender===2">
<!-- 如果为2让女选中 -->
<input type="radio" name="" id="woman" value="2" checked="checked" />
<label for="woman">女</label>
</div>
<div v-else>
<!--如果不为2让女不选中 -->
<input type="radio" name="" id="man" value="1" />
<label for="man">女</label>
</div>
<br>
<!-- 使用if判断会显得格外的繁琐 -->
<hr>
<!-- vue通过v-model的双向绑定的来监控 若 gender的值与该单选框的value的值想等则该
单选框选中,可以试着把value都改为2试试
-->
<input type="radio" name="" id="man" value="1" v-model="gender" />
<label for="man">男</label>
<input type="radio" name="" id="woman" value="2" v-model="gender" />
<label for="woman">女</label>
</div>
<!-- 测试时将gender值切换 -->
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
// 假设 存储的性别为 2 即为女
gender: 2,
}
})
</script>
</body>
2.复选框操作
我们如法炮制写一下复选框
<body>
<div id="app">
<!-- 定义三组爱好 -->
<input type="checkbox" name="" id="daqiu" value="打球" v-model="hobby" />
<label for="daqiu">打球</label>
<input type="checkbox" name="" id="qiaodaima" value="敲代码" v-model="hobby" />
<label for="qiaodaima">敲代码</label>
<input type="checkbox" name="" id="xuexi" value="学习" v-model="hobby" />
<label for="xuexi">学习</label>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
/* 定义复选框 数据时使用数组,与单选框同样的性质 ,若 hobby
的值有单选框中的value值则选中
*/
hobby: ['打球', '敲代码']
},
})
</script>
</body>
3.表单修饰符
<body>
<div id="app">
<!--
number 修饰符 type="number" 是html 表单自带的属性
在表面上一看其实加不加number都无所谓,其实在获取表单value
时我们获取的都是字符串类型,加上了.number会自动转换为整型(或浮点型)
-->
<input type="number" v-model.number="number" />
<!-- v-model.trim的作用是清除用户输入的两端空格 -->
<input v-model.trim="msg" v-on:focusout="print" />
<br>
<hr />
<p style="color: red;">
.lazy 在更新页面数据时不会实时更新而是当input失去焦点,回车这些事件时二发生改变下面两个 表单一个加了.lazy一个没有加
</p>
<input v-model.lazy="msg">
<input v-model="msg">
<span v-text="msg"></span>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
number: 121 + "212.2",
msg: "定义一个有空格的字符串",
},
methods: {
/* 失去焦点时将msg打印一下
会发现v-model.trim会清空 两端空格
而普通的v-model 不会
*/
print: function() {
console.log(this.msg);
}
}
})
</script>
</body>
4.自定义指令
Vue.directive自定义全局指令
<body>
<div id="app">
<input type="text" v-focus />
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 全局指令在定义时 定义在其他vue实例之外
/*
自定义指令在定义时 如果采用驼峰命名法,例如
定义为 focusF 则在视图使用时应该 用v-focus-f 这样使用
如果只是单纯的focusf 则用 v-focusf 这样使用
*/
// 自定义一个全局指令 自动聚焦
Vue.directive('focus', {
inserted: function(el) {
el.focus();
el.placeholder = "自定义自动聚焦指令"
}
});
new Vue({
el: "#app",
})
</script>
</body>
- Vue.directive 注册全局指令带参数
<body>
<div id="app">
<div v-color="msg">
</div>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 定义全局带参指令 v-color
/* 全局变量将 用户传入 的数据解析 并赋值给该实例 */
Vue.directive('color', {
//bind - 只调用一次,在指令第一次绑定到元素上时候调用
// binding 为自定义的函数形参 通过自定义属性传递过来的值 存在 binding.value 里面
bind: function(el, binding) {
// 根据指令的参数设置背景色 宽 高
el.style.backgroundColor = binding.value.color;
el.style.width = binding.value.width;
el.style.height = binding.value.height;
}
})
new Vue({
el: "#app",
data: {
// 定义一组样式数据
msg: {
color: "red",
width: "200px",
height: "200px"
},
}
})
</script>
</body>
- 自定义局部指令
- 局部指令,需要定义在 directives 的选项 用法和全局用法一样
- 局部指令只能在当前组件里面使用
- 当全局指令和局部指令同名时以局部指令为准
<body>
<div id="app" v-color="msg">
<input type="text" v-focus/>
</div>
<br><br>
<p>
在第二个app1实例中我们同样使用了v-color指令,当有与v-color是app
中的局部指令所以无法生效,当v-focus却可以生效
</p>
<div id="app1" v-color="msg">
<input type="text" v-focus/>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 在这里我们定义一个全局组件 它可以在 全局使用
Vue.directive('focus', {
inserted: function(el) {
el.focus();
el.placeholder = "我使用了自定义自动聚焦指令"
}
});
// 创建 第#app 实例
var vm = new Vue({
el: "#app",
data: {
msg: {
color: 'red',
width: "200px",
height: "200px"
},
},
// 在这里我们定义一个 局部指令 它只能在#app组件上使用
directives: {
color: {
bind: function(el, binding) {
// 根据指令的参数设置背景色 宽 高
el.style.backgroundColor = binding.value.color;
el.style.width = binding.value.width;
el.style.height = binding.value.height;
}
}
}
});
new Vue({
el:"#app1",
})
</script>
</body>
二.监听器和过滤器
1.计算属性
<body>
<div id="app">
<!--
当多次调用 reverseString 的时候
只要里面的 num 值不改变 他会把第一次计算的结果直接返回
直到data 中的num值改变 计算属性才会重新发生计算
-->
<div>{{reverseString}}</div>
<div>{{reverseString}}</div>
<!-- 调用methods中的方法的时候 他每次会重新调用 -->
<div>{{reverseMessage()}}</div>
<div>{{reverseMessage()}}</div>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
/*
计算属性与方法的区别:计算属性是基于依赖进行缓存的,而方法不缓存
*/
var vm = new Vue({
el: '#app',
data: {
msg: 'Nihao',
num: 10
},
methods: {
reverseMessage: function() {
console.log('methods')
return this.msg.split('').reverse().join('');
}
},
//computed 属性 定义 和 data 已经 methods 平级
computed: {
// reverseString 这个是我们自己定义的名字
reverseString: function() {
console.log('computed')
var total = 0;
// 当data 中的 num 的值改变的时候 reverseString 会自动发生计算
for (var i = 0; i <= this.num; i++) {
total += i;
}
// 这里一定要有return 否则 调用 reverseString 的 时候无法拿到结果
return total;
}
}
});
</script>
</body>
2.侦听器 watch
- 使用watch来响应数据的变化
- 一般用于异步或者开销较大的操作
- watch 中的属性 一定是data 中 已经存在的数据
- 当需要监听一个对象的改变时,普通的watch方法无法监听到对象内部属性的改变,只有data中的数据才能够监听到变化,此时就需要deep属性对对象进行深度监听
<body>
<div id="app">
<p>当 input值发生改变时触发监听器 求和</p>
<!-- 定义 两个 数使用监听器来 求和 -->
<label for="fristNumber">第一个数</label>
<input type="number" name="" id="fristNumber" v-model.number="fristNumber" />
<label for="lastNumber">第二个数</label>
<input type="number" name="" id="lastNumber" v-model.number="lastNumber" />
<br>两者之和:{{sum}}
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
fristNumber: 21,
lastNumber: 12,
sum: ''
},
// mounted 钩子函数 在初始化页面 后执行
mounted: function() {
this.sum = this.fristNumber+this.lastNumber
},
// 监听器
watch: {
// 第一个数的监听器 当第一个数改变时,执行方法求和
fristNumber: function(val) {
this.sum = val + this.lastNumber;
},
// 第二个数的监听器 当第一个数改变时,执行方法求和
lastNumber: function(val) {
this.sum = val + this.fristNumber;
}
}
})
</script>
</body>
3.过滤器
- vue.js允许自定义过滤器
- 过滤器不该变真正的data数据,改变的是渲染页面的结果
- 全局过滤器使用filter定义,局部使用filters定义,一个不加s一个加s
- 支持级联
1.全局过滤器
<body>
<div id="app">
<!-- <p>修改input值</p>
<input type="text" name="" id="" v-model="msg"/> -->
<!-- 在msg 渲染页面时 ,先走了一遍msgFormat这个过滤器以过滤器反复的数据为准 -->
<p>{{msg | msgFormat}}</p>
// 全局 带参
<p>{{msg | msgFormat2(1,3,5)}}</p>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
// 定义全局 过滤器
Vue.filter('msgFormat', function(msg) {
//
if (1 === msg) {
return "msg等于1";
} else {
return "msg不等于1";
}
});
<!-- 定义全局带参过滤器 msg是实例中的msg,...arg是可变参数 -->
Vue.filter("msgFormat2", function(msg, ...arg) {
// 将过滤器传入的值进行遍历求和并返回渲染
var sun = 0;
for (var i = 0; i < arg.length; i++) {
sun = sun + arg[i]
}
sun = sun+msg;
return arg.length+"数之和加上msg等于"+sun
});
new Vue({
el: "#app",
data: {
// 设置msg等于1
msg: 1,
}
});
</script>
</body>
2.局部过滤器
<body>
<!--
局部过滤器和全局过滤器很相似 就像局部监听器监听器一样只能
在当前实例中使用,在其他实例中使用不起效果
-->
<div id="app">
<p>{{msg | msgFormat}}</p>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
msg: 1,
},
// 局部过滤器
filters: {
// msgFormat过滤器
msgFormat: function(msg) {
if (msg === 1) {
return "msg的值等于1";
} else {
return "msg的值不等于1";
}
}
}
})
</script>
</body>
三.生命周期和钩子函数
1.生命周期
- 事物从出生到死亡的过程
- Vue实例从创建 到销毁的过程 ,这些过程中会伴随着一些函数的自调用。我们称这些函数为钩子函数
2.常用的钩子函数
beforeCreate | 在实例初始化之后,数据观测和事件配置之前被调用 此时data 和 methods 以及页面的DOM结构都没有初始化 什么都做不了 |
---|---|
created | 在实例创建完成后被立即调用此时data 和 methods已经可以使用 但是页面还没有渲染出来 |
beforeMount | 在挂载开始之前被调用 此时页面上还看不到真实数据 只是一个模板页面而已 |
mounted | el被新创建的vm.$el替换,并挂载到实例上去之后调用该钩子。 数据已经真实渲染到页面上 在这个钩子函数里面我们可以使用一些第三方的插件 |
beforeUpdate | 数据更新时调用,发生在虚拟DOM打补丁之前。 页面上数据还是旧的 |
updated | 由于数据更改导致的虚拟DOM重新渲染和打补丁,在这之后会调用该钩子。 页面上数据已经替换成最新的 |
beforeDestroy | 实例销毁之前调用 |
destroyed | 实例销毁后调用 |
3.钩子函数使用演示
<body>
<div id="app">
<input v-model="msg" />
<p v-text="msg"></p>
<button type="button" v-on:click="destroyVm">点击销毁实例</button>
</div>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
var vm = new Vue({
el: "#app",
data: {
msg: "钩子函数演示"
},
beforeCreate: function() {
console.log("beforeCreate实例初始化之后调用");
},
created: function() {
console.log("实例创建完成后created被调用");
},
beforeDestroy:function(){
console.log("销毁之前调用");
},
destroyed:function(){
console.log("销毁之后调用");
},
methods: {
destroyVm: function() {
alert("实例被销毁");
// $destroy 销毁 vm实例销毁后vm实例将不存在
vm.$destroy();
}
}
});
</script>
</body>
四.vue数组拓展方法
- 在 Vue 中,直接修改对象属性的值无法触发响应式。当你直接修改了对象属性的值,你会发现,只有数据改了,但是页面内容并没有改变
- 变异数组方法即保持数组方法原有功能不变的前提下对其进行功能拓展
push() |
往数组最后面添加一个元素,成功返回当前数组的长度 |
---|---|
pop() |
删除数组的最后一个元素,成功返回删除元素的值 |
shift() |
删除数组的第一个元素,成功返回删除元素的值 |
unshift() |
往数组最前面添加一个元素,成功返回当前数组的长度 |
splice() |
有三个参数,第一个是想要删除的元素的下标(必选),第二个是想要删除的个数(必选),第三个是删除 后想要在原位置替换的值 |
sort() |
sort() 使数组按照字符编码默认从小到大排序,成功返回排序后的数组 |
reverse() |
reverse() 将数组倒序,成功返回倒序后的数组 |
替换数组
- 不会改变原始数组,但总是返回一个新数组
filter | filter() 方法创建一个新的数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。 |
---|---|
concat | concat() 方法用于连接两个或多个数组。该方法不会改变现有的数组 |
slice | slice() 方法可从已有的数组中返回选定的元素。该方法并不会修改数组,而是返回一个子数组 |
动态数组响应式数据
- Vue.set(a,b,c) 让 触发视图重新更新一遍,数据动态起来
- a是要更改的数据 、 b是数据的第几项、 c是更改后的数据
五.章节小题
- 使用vue完成页面crud操作
<body>
<!-- 我们定义一个页面级的增删查改案例来练习数组的操作 -->
<div id="app" class="tableCard">
<input type="text" v-model="id" disabled="disabled" />
<span>{{name}}</span><input type="text" name="" id="name" value="" v-model="name" />
<button type="button" v-on:click="addList">提交</button>
<table class="tableBody">
<!-- 表头 -->
<tr>
<th v-for="t in title">
{{t}}
</th>
</tr>
<!-- 主体 -->
<tr v-for="(list,index) in dataList">
<td>{{list.id}}</td>
<td>{{list.name}}</td>
<td>
<a href="#" v-on:click="update(list.id)">修改</a>
<a href="#" v-on:click="deleteData(list.id)">删除<a>
</td>
</tr>
</table>
<div id="" style="text-align: center;">
总数据量:<span>{{total}}</span>
</div>
</div>
<script src="js/jquery-3.4.1.js" type="text/javascript" charset="utf-8"></script>
<script src="js/vue.js" type="text/javascript" charset="utf-8"></script>
<script type="text/javascript">
new Vue({
el: "#app",
data: {
flag: false,
name: '',
id: '',
title: ["id", "姓名", "操作"],
dataList: [{
id: 1,
name: "李四"
},
{
id: 2,
name: "王五"
},
{
id: 3,
name: "张飞"
},
{
id: 4,
name: "小乔"
},
]
},
methods: {
// 定义添加 方法
addList: function() {
// 添加
if (this.flag === false) {
var data = {};
// 获取 addName
data.name = this.name;
// console.log(addName);
// 求添加前数据长度
data.id = this.dataList.length + 1;
// console.log(dataSzie)
// push 操作 往数组最后一个添加数据
this.dataList.push(data);
} else {
// 修改
var list = this.dataList;
for (var i = 0; i <= list.length; i++) {
if (this.id == list[i].id) {
// 遍历 数据集合 将 对应id的值改为修改后的值
list[i].name = this.name;
break;
}
}
this.flag = false;
/* this.name = '';
this.id = ''; */
}
// 添加 过后清空
this.name = '';
this.id = '';
},
update: function(dataId) {
var list = this.dataList;
for (var i = 0; i <= list.length; i++) {
if (list[i].id == dataId) {
this.id = list[i].id;
this.name = list[i].name;
this.flag = true;
}
}
},
deleteData: function(dataId) {
// 使用过滤器 将 删除 的数据过滤出去
this.dataList = this.dataList.filter(function(item) {
return item.id != dataId;
});
}
},
computed: {
total: function() {
// 3.1 计算图书的总数
return this.dataList.length;
}
}
})
</script>
</body>
dmoe下载:https://gitee.com/li_shang_shan/vue-feature-demo
个人学习,内容简略