过滤器[v3已废弃]

过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中

定义过滤器的两种方式

使用Vue.filter()进行全局定义

1
2
3
4
5
6
Vue.filter('RMB1',function(v){
if(v===0){
return v
}
return v+'元'
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="../js/vue.2.7.10.js"></script>
<script src="./filter_price.js"></script>
</head>
<body>
<div id="app">
<p>价格:{{ price |RMB }}</p><!--和Django中类似-->
</div>
<script>
//全局过滤器
// Vue.filter("RMB", (data) => {
// return data.toFixed(2)+'¥';
// });
var vm = new Vue({
el: "#app",
data: {
price: 3.99999
}
})
</script>
</body>
</html>
1
2
3
Vue.filter("RMB", (data) => {
return data.toFixed(2)+'¥';
});

在vue对象通过filter属性定义(局部过滤器)

1
2
3
4
5
6
7
8
9
10
11
12
var vm = new Vue({
el: "#app",
data: {
price: 3.99999
},
//局部变量
filters: {
RMB(data) {
return data.toFixed(2) + '¥';
}
}
})

计算和侦听属性

计算属性

我们之前学习过字符串反转,如果直接把反转的代码写在元素中,则会使得其他同事在开发时不易发现数据被调整了,所以vue提供了一个计算属性(computed),可以让我们把调整data数据代码存在该属性中。

#实例货币汇率转换

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.3.3.4.js"></script>
<style>
input[type=text] { /*input和[]需要紧挨着*/
width: 60px;
}
</style>
</head>
<body>
<div id="box">
<!-- {{a_money}}美元={{ (a_money * rate).toFixed(5) }}人民币--><!--一般写法-->
{{a_money}}美元={{ p_money }}人民币
<input type="text" v-model="a_money">美元
</div>
<script>
vm = Vue.createApp({
data() {
return {
a_money: 0,
rate: 6.4701
}
},
//计算属性,实际上而言,这里的每一个方法最终对html都是一个变量,这个变量在已有的基础上通过计算得到的
computed: {
p_money() {
return (this.a_money * this.rate).toFixed(5)
}
},

}).mount("#box");
</script>
</body>
</html>

可写计算属性//对象写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.3.3.4.js"></script>
<style>
input[type=text] { /*input和[]需要紧挨着*/
width: 60px;
}
</style>
</head>
<body>
<div id="box">
<input type="password" v-model="password">
<p>{{password}}</p>
<p>{{topassword}}</p>
</div>
<script>
vm = Vue.createApp({
data() {
return {
topassword: ''//这里的命名方式不能使用_password,_password可能是私有属性
}
},
//对象写法 --计算属性--存储器
computed: {
password: {
//读取器
get() {
//base64加密
return atob(this.topassword)
},
//存储器
set(data) {
this.topassword = btoa(data)
}
}
},
methods() {
},
mounted() {
},
}).mount("#box");
</script>
</body>
</html>

监听属性

侦听属性,可以帮助我们侦听data某个数据的变化,从而做出相应的自定义操作。

侦听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数,当侦听的data数据发生变化时,会自定执行的对应函数,这个函数在被调用时,vue会传入两个形参,第一个是变化前的数据值,第二个是变化后的数据值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.3.3.4.js"></script>
</head>
<body>
<div id="box">
<button @click="number--">-</button>
<input type="text" v-model="number">
<button @click="number++">+</button>
</div>
<script>
vm = Vue.createApp({
data() {
return {
number: 0,
max_num: 10
}
},
//watch中的所有方法名,就是data或者computer中的变量
watch: {
number() {//此处表示number的变化,当number一旦改变,此处自动调用
if (this.number < 0) {
this.number = 0
} else if (this.number > this.max_num) {
this.number = this.max_num
}
},
},
methods() {
},
mounted() {
},
}).mount("#box")
</script>
</body>
</html>

可以用在用户设置某一个数据置顶的情况(比如购物车默认地址)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
watch:{
'default_address_id': function () {
for (let default_address of this.addresses) {
if (this.default_address_id === default_address.id) {
// console.log(default_address)
let index = this.addresses.indexOf(default_address)
if (index !== 0) {
this.addresses.splice(index)
this.addresses.splice(0, 0, default_address)
}
}
}
}
}

小案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.3.3.4.js"></script>
<style>
select, option {
width: 120px;
}
</style>
</head>
<body>
<div id="box">
省份:<select v-model="province">
<option :value="province.name" v-for="province in province_list">{{province.name}}</option>
</select>
城市:<select v-model="city">
<option :value="city.name" v-for="city in citys">{{city.name}}</option>
</select> 地区:<select v-model="dist">
<option :value="dist.name" v-for="dist in dists">{{dist.name}}</option>
</select>
</div>
<script>
vm = Vue.createApp({
data() {
return {
dists: [],
provinces: [],
citys: [],
dist: '',
province: '',
city: '',
province_list: [
{'id': 1, 'name': '江西省'},
{'id': 2, 'name': '浙江省'},
{'id': 3, 'name': '湖南省'},
{'id': 4, 'name': '广东省'},
],
city_list: [
{'id': 5, 'name': '抚州市', "pid": 1},
{'id': 6, 'name': '九江市', "pid": 1},
{'id': 7, 'name': '鹰潭市', "pid": 1},
{'id': 8, 'name': '上饶市', "pid": 1},
{'id': 9, 'name': '南昌市', "pid": 1},
{'id': 10, 'name': '杭州市', "pid": 2},
{'id': 11, 'name': '温州市', "pid": 2},
{'id': 12, 'name': '宁波市', "pid": 2},
{'id': 13, 'name': '金华市', "pid": 2},
{'id': 14, 'name': '台州市', "pid": 2},
{'id': 15, 'name': '长沙市', "pid": 3},
{'id': 16, 'name': '湘潭市', "pid": 3},
{'id': 17, 'name': '广州市', "pid": 3},
{'id': 18, 'name': '深圳市', "pid": 4},
{'id': 19, 'name': '汕头市', "pid": 4},
],
dist_list: [
{"id": 20, "name": '芙蓉区', "pid": 15},
{"id": 21, "name": '天心区', "pid": 15},
{"id": 22, "name": '临川区', "pid": 5},
{"id": 23, "name": '金溪县', "pid": 5},
{"id": 24, "name": '龙湾区', "pid": 11},
{"id": 25, "name": '瓯海区', "pid": 11},
{"id": 25, "name": '越秀区', "pid": 17},
]
}
},
//bug当province变更新值的时候,如果之前已经选择了地区,那么地区的数组不会为空--已解决
//当选择江西抚州金溪县后更改为浙江温州瓯海区后再更换为江西抚州金溪县会自动填值--莫名其妙没了
//watch中的所有方法名,就是data或者computer中的变量
watch: {
province() {//此处表示number的变化,当number一旦改变,此处自动调用
// this.citys=[];
this.city=''//解决方法
let province_id = -1;//初始化,首个省份id为-1
for (let provice of this.province_list) { //of左边 返回的是循环中的成员 in左边 返回的是循环中的下标
if (provice.name === this.province) {
// console.log(key)
province_id = provice.id;
break;//退出循环
}
}
this.citys = []
for (let key of this.city_list) {
if (key.pid === parseInt(province_id)) {
this.citys.push(key);//给数组追加成员;
}
}
},
city() {
let city_id = -1;//初始化,首个省份id为-1
for (let city of this.city_list) { //of左边 返回的是循环中的成员 in左边 返回的是循环中的下标
if (city.name === this.city) {
city_id = city.id;
break;//退出循环
}
}
this.dists = []
let count = false
for (let key of this.dist_list) {
if (key.pid === parseInt(city_id)) {
this.dists.push(key);//给数组追加成员;
count = true
}
}

}
},
}).mount("#box")
</script>
</body>
</html>

vue2.7版本简便写法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.2.7.10.js"></script>
<style>
select, option {
width: 120px;
}
</style>
</head>
<body>
<div id="box">
<!-- 此处优化只是减少代码量,但是存在地区选择后重新选择身份地区不清空的bug-->
省份:<select v-model="province_id">
<option :value="province.id" v-for="province in province_list">{{province.name}}</option>
</select>
城市:<select v-model="city_id">
<option :value="city.id" v-if="city.pid===province_id" v-for="city in city_list">{{city.name}}</option>
</select>
地区:<select v-model="dist_id">
<option :value="dist.id" v-if="dist.pid===city_id" v-for="dist in dist_list">{{dist.name}}</option>
</select>
</div>
<script>
var vm = new Vue({
el: "#box",
data() {
return {
dist_id: '',
province_id: '',
city_id: '',
province_list: [
{'id': 1, 'name': '江西省'},
{'id': 2, 'name': '浙江省'},
{'id': 3, 'name': '湖南省'},
{'id': 4, 'name': '广东省'},
],
city_list: [
{'id': 5, 'name': '抚州市', "pid": 1},
{'id': 6, 'name': '九江市', "pid": 1},
{'id': 7, 'name': '鹰潭市', "pid": 1},
{'id': 8, 'name': '上饶市', "pid": 1},
{'id': 9, 'name': '南昌市', "pid": 1},
{'id': 10, 'name': '杭州市', "pid": 2},
{'id': 11, 'name': '温州市', "pid": 2},
{'id': 12, 'name': '宁波市', "pid": 2},
{'id': 13, 'name': '金华市', "pid": 2},
{'id': 14, 'name': '台州市', "pid": 2},
{'id': 15, 'name': '长沙市', "pid": 3},
{'id': 16, 'name': '湘潭市', "pid": 3},
{'id': 17, 'name': '广州市', "pid": 3},
{'id': 18, 'name': '深圳市', "pid": 4},
{'id': 19, 'name': '汕头市', "pid": 4},
],
dist_list: [
{"id": 20, "name": '芙蓉区', "pid": 15},
{"id": 21, "name": '天心区', "pid": 15},
{"id": 22, "name": '临川区', "pid": 5},
{"id": 23, "name": '金溪县', "pid": 5},
{"id": 24, "name": '龙湾区', "pid": 11},
{"id": 25, "name": '瓯海区', "pid": 11},
{"id": 25, "name": '越秀区', "pid": 17},
]
}
},
});
</script>
</body>
</html>

修饰符

也叫指令修饰符,它的作用就是为了增加或者限制指令本身的工作作用

1
2
3
4
5
6
7
8
.stop		#阻止事件冒泡,是当前标签事件无效
.once #限制触发事件为一次性绑定,一次性后不在生效
.prevent #阻止标签的默认跳转行为

.number #把表单输入的内容转换为数值类型
.13
.trim #把表单输入的内容左右两边的空格删除
.lazy #表单数据同步事件设置为每次更新数据

阻止事件冒泡和刷新页面

事件冒泡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.3.3.4.js"></script>
</head>
<body>
<div id="box">
<div id="father">
<p @click="show2">一段话
<a href="" @click.prevent.stop="show1">阻止事件冒泡和刷新页面</a></p>
</div>
</div>
<div id="box2">
<div id="father2">
<p onclick="show('p')">一段话
<a href="" onclick="show('a')">链接</a></p>
</div>
</div>
<div id="box3">
<div id="father3">
<p id="p">一段话
<a href="" id="a">链接</a></p>
</div>
</div>
<script>
//在js中,针对事件冒泡阶段,如果父元素和子元素,绑定了同类事件,子元素触发了以后,父元素也跟着触发,这就是事件冒泡
//事件冒泡有好有坏,看开发者如何使用
//事件冒泡说的明白一点就是子元素和父元素都有点击事件,触发子元素的点击事件,父元素也跟着触发。但是触发父元素的点击事件,子元素并不会被触发
//好处:方便的实现事件委托,优化js代码
//坏处会造成不必要的事件触发。此时需要我们阻止冒泡事件
vm = Vue.createApp({
data() {
return {
message: "hello"
}
},
methods: {
show1() {
console.log('a标签被点击了')
},
show2() {
console.log('p标签被点击了')
}
},
}).mount("#box")

function show(el) {
console.log(el + '被点击了')
}

var box2 = document.getElementById("box2");
box2.onclick = function (ev) {
var e = ev || window.event;
preventDef(e);
alert("后续操作");
}

function preventDef(e) {
//e.preventDefault() : 非 IE 使用
// e.returnValue = false :IE 使用
//兼容写法
if (e.preventDefault) {
e.preventDefault();
} else {
window.event.returnValue = false;
}
}

//分隔符
var div = document.querySelector("#father3")
var a = document.querySelector("#a")
var p = document.querySelector("#p")
div.onclick = () => {
show('div标签')
};
a.onclick = (e) => {
console.log(e)
//阻止事件冒泡
e.preventDefault()
show('a')
};
p.onclick = () => {
show('p')
}
</script>
</body>
</html>

使用.stop和.prevent

事件委托:优化代码,提高性能,避免卡顿

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<div id="app">
<ul class="father">
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
</ul>
</div>
<script>
//批量绑定事件
// var li_list = document.querySelectorAll('li')
// for (li of li_list) {
// // console.log(li)
// // li.onclick = () => {
// li.onclick = function(){
// console.log(this.innerHTML);//显示当前元素内部的HTML
// }
// }

//事件委托:优化代码,提高性能,避免卡顿
var ul = document.querySelector('ul')
ul.onclick = (e) => {
console.log(e.target);//本质//获取触发事件的目标元素
console.log(e.target.innerHTML);//本质//获取触发事件的目标元素
}
</script>
</body>
</html>

综合案例-todolist

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="./js/vue.3.3.4.js"></script>
<style>
.list_con {
width: 600px;
margin: 50px auto 0;
}

.inputtxt {
width: 550px;
height: 30px;
border: 1px solid #ccc;
padding: 0px;
text-indent: 10px;
}

.inputbtn {
width: 40px;
height: 30px;
border: 1px solid #ccc;
padding: 0px;
}

.list {
margin: 0;
padding: 0;
list-style: none;
margin-top: 20px;
}

.list li {
height: 40px;
line-height: 40px;
}

.list li span {
float: left;
}

.list li a {
float: right;
text-decoration: none;
margin: 0 10px;
}
</style>
</head>
<body>
<div id="box" class="list_con">
<h2>To do list</h2>
<input type="text" name="" id="txt1" class="inputtxt" v-model="addtxt">
<input type="button" value="增加" id="btn1" class="inputbtn" @click="addTask">
<ul id="list" class="list">
<!--javascritp:; #阻止a标签跳转-->
<li v-for="(task,index) in task_lsit">
<span>{{task}}</span>
<a href="javascript:;" class="up" @click="upTask(index)"></a>
<a href="javascript:;" class="down" @click="downTask(index)"></a>
<a href="javascript:;" class="del" @click="removeTask(index)"> 删除 </a><!--通过下标删除数组中对应的成员-->
</li>
</ul>
</div>
<script>
vm = Vue.createApp({
data() {
return {
addtxt: '',
task_lsit: [
'学习html',
'学习css',
'学习javascript',
]
}
},
methods: {
addTask() {
// this.task_lsit.unshift(this.addtxt);
this.task_lsit.push(this.addtxt);
//unshift是数组首位添加一个成员
//push是数组末尾添加一个成员
//shift是删除数组首位成员
this.addtxt = ''//添加成功后刷新输入框内容
},
removeTask(index) {
// delete this.task_lsit[index]//这样只是将数组内容删除了并且补充为empty,对应li标签并未被删除,
// 并不是真的删除相当于this.task_lsit[index] = ''
//使用.splice(起始下标,成员个数,...插入成员1,插入成员2,插入成员3)//也可以用来插入成员
this.task_lsit.splice(index, 1)//处理数组的高阶函数
},
//==表示判断两边数据的值是否相等,===表示判读左右两边数据的值和数据类型是否一致
upTask(index) {
if ((index - 1) >= 0) {
let task = this.task_lsit.splice(index, 1)[0]//['学习css'][0]
// console.log(task)
this.task_lsit.splice(index - 1, 0, task)
}
},
downTask(index) {
if ((index + 1) <= this.task_lsit.length) {
let task = this.task_lsit.splice(index, 1)[0]//['学习css'][0]
// console.log(task)
this.task_lsit.splice(index + 1, 0, task)
}
}
},
mounted() {
},
}).mount("#box")
</script>
</body>
</html>

本破站由 @BXZDYG 使用 Stellar 主题创建。
本博客部分素材来源于网络,如有侵权请联系1476341845@qq.com删除
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。

本"页面"访问 次 | 👀总访问 次 | 总访客
全部都是博主用心学编写的啊!不是ai啊 只要保留原作者姓名并在基于原作创作的新作品适用同类型的许可协议,即可基于非商业目的对原作重新编排、改编或者再创作。