# 监听属性

计算属性会产生一个新的属性。监听属性只是监听已有的属性。

watch 监听可以用来监听某一个属性的值的变化,当变化时,可以通过该属性下的对应的函数进行监听并执行该函数。其作用与写法类似于计算属性,但两者之间还是有较大的区别,watch 只是监听派发过来的属性,不用产生一个新的属性并返回出去。

可以把 watch 看做是 js 中的 onchange 事件,只要该属性的值发生变化了就会触发该函数。

官网 API:https://cn.vuejs.org/v2/api/#watch

监听属性分为深监听与浅监听,比如要监听某个属性的值为数组,数组元素是对象的情况,默认是浅监听,只有该数组元素的数量进行了变更才会触发函数,如果要让该数组元素中对象的属性变化时也能监听,则需要使用深监听。

所以深监听主要是用于数组和对象的监听。

总之:监听属性(侦听器)使用频率不及计算属性。

# 事件传参的 3 种情况

  1. 事件调用没有参数,但是事件函数有参数的情况

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //调用时没传参
    <div @click="fun"></div>
    //JS
    new Vue({
    ...
    methods:{
    //定义时传参的第一个参数就是事件对象
    fun(a){
    //a是事件对象
    }
    }
    });
  2. 事件调用有参数,事件函数也有参数的情况(都是参数)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    //调用时没传参
    <div @click="fun(a,12)"></div>
    //JS
    new Vue({
    ...
    data:{
    a:123
    }
    methods:{
    //定义时传参了,调用时也传参了,则第一个参数就是调用时的值
    fun(a,b){
    //a代表的就是某一个值
    console.log(a+b);//
    }
    }
    });
  3. 把 1、2 两种情况结合起来,即既想要保留事件对象,又需要传递参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    //调用时没传参
    <div @click="fun($event,a,12)"></div>
    //JS
    new Vue({
    ...
    data:{
    a:123
    }
    methods:{
    //调用时的第一个参数如果是$event,则表示事件对象,后面的参数才是参数
    //定义时的第一个参数就是事件对象,后面的是普通参数与上面的一一对应
    fun(e,a,b){
    //a代表的就是某一个值
    console.log(e);//$event就是事件对象,其他的参数就是形参
    console.log(a+b);//
    }
    }
    });

# 监听属性实例

# 实例 1

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
115
116
117

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style type="text/css">
*{ margin:0;padding:0; }
div{ margin-bottom: 5px; }
body{ padding: 10px; }
fieldset{ padding: 15px; }
#tableBox { margin-top: 20px; }
#tableBox thead{ background-color: #1F9A00;color: #fff; }
table,td,th{ border:1px solid #999; text-align: center; }
td,th{ padding: 5px; }
</style>
<script src="../vue.v2.6.12.js"></script>
</head>
<body>
<div id="app">
<fieldset>
<legend>请输入学生信息</legend>
<form action="#" method="get">
<div>
<label>姓名:</label>
<input type="text" name="" v-model="uname" @keyup.enter="add()" @keyup.ctrl.enter="add()">
</div>
<div>
<label>年龄:</label>
<input type="number" name="" v-model="uage" @keyup.enter="add()" @keyup.ctrl.enter="add()">
</div>
<div>
<label>性别:</label>
<select v-model="usex">
<option disabled="disabled">请选择</option>
<option>男</option>
<option>女</option>
</select>
</div>
<div>
<input type="button" value="创建" name="" @click="add()" @keyup.enter="add()" @keyup.ctrl.enter="add()">
</div>
</form>
</fieldset>

<div id="tableBox">
<table width="100%" cellpadding="5" cellspacing="0">
<thead>
<tr>
<th>姓名</th>
<th>年龄</th>
<th>性别</th>
<th>操作</th>
</tr>
</thead>
<tbody>
<tr v-for="item,index in list">
<td>{{item.name}}</td>
<td>{{item.age}}</td>
<td>{{item.sex}}</td>
<td><input type="button" value="删 除" name="" @click="del(index)"></td>
</tr>
<tr>
<td colspan="4" v-show="this.list.length==0">您还没有添加任何数据哦</td>
<!-- <td colspan="4">您还没有添加任何数据哦</td> -->
</tr>
</tbody>
</table>
</div>
</div>
<script>
let dataHandler={
get(){
return JSON.parse(localStorage.getItem("my"))|| [];
},
set(d){
localStorage.setItem("my",JSON.stringify(d));
}
};
var vm=new Vue({
el:"#app",
data:{
uname:"",
uage:"",
usex:"男",
list:dataHandler.get()
},
methods:{
add(){
if(!this.uname || !this.uage){
alert("请将学生信息补充完整!")
return
}
this.list.unshift({name:this.uname,age:this.uage,sex:this.usex});
//初始化输入框
this.uname="";
this.uage="";
this.usex="男";
},
del(index){
// 删除单条数据
this.list.splice(index,1)
}
},
watch:{
list:{
handler(){
dataHandler.set(this.list);
},
deep:true
}
}
});
</script>
</body>
</html>

# 实例 2

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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

<!DOCTYPE html>
<html lang="zh-CN">

<head>
<meta charset="UTF-8">
<title>todolist</title>
<style type="text/css">
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}

body {
background-color: #f5f5f5;
color: #444
}

a {
text-decoration: none;
color: #333;
}

#app {
width: 640px;
margin: 0 auto
}

#app h1 {
text-align: center;
font-size: 5em;
color: rgba(175, 47, 47, 0.15);
}

.todoapp {
min-height: 200px;
background: #fff;
margin: 30px 0 40px 0;
position: relative;
box-shadow: 0 2px 4px 0 rgba(0, 0, 0, 0.2),
0 25px 50px 0 rgba(0, 0, 0, 0.1);
padding-bottom: 40px;
}

/*.todoapp:before{content: '';}*/
.header {
position: relative;
}

.new-todo {
padding: 16px 16px 16px 60px;
border: none;
background: rgba(0, 0, 0, 0.003);
box-shadow: inset 0 -2px 1px rgba(0, 0, 0, 0.03);
width: 100%;
font-size: 24px;
}

:focus {
outline: 0;
}

.toggle-all {
background: none;
position: absolute;
top: 19px;
left: -6px;
width: 60px;
height: 34px;
text-align: center;
border: none;
-webkit-appearance: none;
cursor: pointer;
}

.toggle-all:before {
content: '﹀';
font-size: 22px;
color: #333;
padding: 10px 27px 10px 27px;
}

.todolist li {
padding: 10px;
border-bottom: 1px solid #e6e6e6;
list-style: none;
}

.todolist li input,
.todolist li a {
display: inline-block;
width: 45px;
}

.todolist li input {
height: 25px;
vertical-align: -5px;
}

.todolist li a {
float: right;
display: none;
font-size: 20px
}

.todolist li:hover a {
color: #af5b5e;
display: block;
}

.todolist li span {
font-size: 1.5em;
}

.todolist li:last-child {
border-bottom: none;
}

.footer {
color: #777;
padding: 10px 15px;
height: 40px;
position: absolute;
width: 100%;
bottom: 0;
border-top: 1px solid #e6e6e6;
}

.footer:before {
content: '';
position: absolute;
right: 0;
bottom: 0;
left: 0;
height: 50px;
overflow: hidden;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2), 0 8px 0 -3px #f6f6f6, 0 9px 1px -3px rgba(0, 0, 0, 0.2), 0 16px 0 -6px #f6f6f6, 0 17px 2px -6px rgba(0, 0, 0, 0.2);
}

.clear-completed {
float: right;
position: absolute;
right: 20px;
}

/*事项完成时*/
.completed {
color: #d9d9d9;
text-decoration: line-through;
}
.red{
color: #f00;
}
</style>
<script src="vue.v2.6.12.js"></script>
</head>

<body>
<!-- 外观参考了:http://todomvc.com/examples/vue/
代码By 罗永超 -->
<div id="app">
<h1>todolist</h1>
<section class="todoapp">
<header class="header">
<input autofocus="autofocus" autocomplete="off" placeholder="请在这里输入您的待办事项" v-model="text"
class="new-todo" @keyup.enter="add">
<input type="checkbox" class="toggle-all" v-model="checkall">
</header>
<ul class="todolist">
<li v-for="item,index in list">
<input type="checkbox" v-model="item.check">
<span :class="{completed:item.check==true}">{{item.content}}</span>
<a href="#" @click="del(index)">x</a>
</li>
</ul>
<footer class="footer">
<span class="todo-count"><strong :class="{red:todo>0}">{{todo}}</strong> 个未完成
</span>
<a class="clear-completed" href="#" @click="clear">
清除已完成
</a>
</footer>
</section>
</div>
<script>
let dataHandler={
get(){
return JSON.parse(localStorage.getItem("mymy"))|| [];
},
set(d){
localStorage.setItem("mymy",JSON.stringify(d));
}
};
let vm = new Vue({
el: "#app",
data: {
list: dataHandler.get(),
text: ""//输入框文本
},
methods: {
add() {//回车新增待办
if(!this.text){return};//判断非空
this.list.unshift({check:false,content:this.text});//数组中添加对象
this.text = "";//输入框文本清空
},
del(index){//删除单个
this.list.splice(index,1);
},
clear(){//删除全部
this.list=this.list.filter(item=>item.check==false);
}
},
computed: {
checkall: {
get() {
return this.list.every(item=>item.isChecked);
},
set(value) {
this.list.forEach(item=>{item.check=value});//全选绑定
}
},
todo(){
return this.list.filter(item=>item.check==false).length;//未完成计数
}
},
watch:{
list:{
handler(){
dataHandler.set(this.list);
},
deep:true
}
}
})
</script>
</body>

</html>

更新于 阅读次数

请我喝[茶]~( ̄▽ ̄)~*

tz 微信支付

微信支付

tz 支付宝

支付宝