我们的 Vue 新手学习之旅即将结束,你也快要从 Vue 学徒级别毕业了。但是在这之前,你必须掌握 侦听器。
今天我们将要处理两个非常重要的概念,一个是刚才提到的 侦听器,另一个是 输入绑定。
话不多说,我们先构建一个超级简单的表单样例来展示这两个超赞的功能。
<html>
<head>
<title>Vue 101</title>
</head>
<body>
<div id="app">
<label>What's your favorite game ever?</label>
<input type="text" >
<hr>
<p>{{ response }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data() {
return {
favoriteGame: null,
response: ''
}
}
});
</script>
</body>
</html>
让我们看下这段代码到底做了啥。
在 <div id="app">
内部,我们创建了一个 label 标签以及最基础形式的 <input>
标签。然后,我们在模板中输出了 response
属性的结果。
在 Vue 实例中,我们申明了包含两个属性的本地状态,分别是 favoriteGame
以及 response
。另外请注意,如果我们的 data()
不使用函数的 return
语法来创建,v-model 将不起作用。
这个功能大概是,我们希望用户无论在 <input>
标签输入什么样的内容都能存到变量中,这样的话我们就可以在合适的地方使用它了。
在 vanilla JS 甚至是 JQuery 中,你可能会用 $('input')
或者 document.querySelector
捕捉 input
元素,但是在 Vue 中我们有更简单的方法来完成这项寻常的任务。
接下来介绍下 v-model
。
v-model
如同你之前学习到的那样,所有以 v-
开头的属性都是 Vue 指令。v-model
的含义简单来说就是:
Vue ,我想让你获取标记了 v-model
指令的输入框上的所有输入,然后建立一个双向绑定关系。我将提供一个 属性
,无论何时我的代码修改了这个属性 - 输入框中的值也要同时更新,同样的,无论何时这个输入框内的值变化了 - 这个变化值也要映射到我的属性中。
让我们实际操作下,首先跳到 <input>
声明处,然后给它加上 v-model
指令。
<input type="text" v-model="favoriteGame">
现在去浏览器运行一下这段代码,然后在你奇妙而美丽的输入框中写一点东西。哈哈哈哈哈哈… 嗝?
额,好像什么事情都没发生的样子。继续打开你的 Vue 开发工具然后检查 <Root>
元素的数据。耶,有进展了。
现在进入开发工具然后改变下 favoriteGame
的值(别忘了用引号包起来,这里需要一个字符串)。EZ-BINDS-R-US ?
Vue 非常聪明,它知道如何绑定每种类型的原生 HTML 输入框,因此你只需要添加好 v-model
然后坐收渔利即可,不过得在你开始构建自己的组件并使用时 v-model 的强大才会真正的展现出来。
在幕后 v-model
实际上为每次绑定建立了 v-bind:value
和 v-on:input
两个指令,但在这里对这个问题深入讨论就有点超纲了,所以有兴趣了解更多相关知识的话,看下这个链接: 在组件上使用 v-model
侦听器
现在我们已经了解了超强大的黏在一起的双向绑定 v-model
,接下来结合实际做一些事情吧。
你已了解过如何把 data
状态属性通过 {{ favoriteGame }}
的方式放到模板中,所以这里就不啰嗦了。也已经学过了如何在 method
以及 computed
属性中使用 this.favoriteGame
- 这里也不再啰嗦。但是如果你想 “监听” 或者 “响应” 这个属性变化时候,会发生什么呢?
计算属性非常适合重新计算内容并返回处理后的数据,但如果我们想要在某个值变更的时候更改程序中其他地方的状态,或者触发某些异步请求,应该怎么做呢?在这个小案例中 侦听器
来拯救世界了。
让我们给需要观察的属性创建一个样例。
const app = new Vue({
el: '#app',
data() {
return {
favoriteGame: null,
response: ''
}
},
// 侦听器在这里↓
watch: {
favoriteGame(newValue, oldValue) {
console.log('Favorite game was ' + oldValue + ' and now is ' + newValue)
}
}
});
侦听器被定义在主实例或者组件的 watch
属性中,我们传递了一个对象,这个对象包含了我们想要监听的每个属性及其配置。
简答来说,每个你想要监听或者响应其变化的 data
属性或者 props
属性都需要将其名称放到 watch: {}
中。所以如果你的属性名是 favoriteGame
那么这个函数的名称也是 favoriteGame
。
每个函数触发时都会被传入两个参数,第一个参数是该属性获得的 新值
,第二个参数是该属性改变前的 老值
。
代码里边添加一些 console.log
声明并刷新一下你的浏览器窗口。随后试着在 <input>
标签中输入一些内容然后检查下控制台输出。不论何时何地 favoriteGame
属性只要变了,监听函数就会被触发。
下面我们用这个来实操一点有意思的东西。还记得我们的 response
属性么?让我们根据用户的输入信息生成一些有意思内容并放到 response 属性中去,皮一下就很开心。
watch: {
favoriteGame(newValue, oldValue) {
if (!newValue) return // 如果是空字符串,直接返回
// 如果新值包含关键字 metroid
if (newValue.toLowerCase().indexOf('metroid') !== -1) {
this.response = 'Ceres station is under attack!'
return
}
// 如果新值包含单词 zelda
if (newValue.toLowerCase().indexOf('zelda') !== -1) {
this.response = 'Its dangerous to go alone, take this ?️'
return
}
// 如果老值包含 metroid 并且用户对其进行了修改
if (
oldValue.toLowerCase().indexOf('metroid') !== -1 &&
newValue.toLowerCase().indexOf('metroid') === -1
) {
this.response = 'GET TO DA CHOPPA NAO'
return
}
// 默认响应值
this.response = 'Sure, why not?'
}
}
以防万一你不理解代码,indexOf
会检查传入的字符串是否存在于当前字符串中,并在不存在时返回 -1
,存在时返回字符串所在的位置。
继续用这个做一些有意思的玩意吧,写一些新示例然后在浏览器中把玩把玩。
我期望你现在可以理解监视属性的强大,多思考有助于理解这个功能,比如我的属性发生了改变并且我需要用编程的方式去响应它(通过 ajax 调用,外部函数,更新一个辅助值等等),这些场景通常来讲用监听器是一个好的解决方案。除此之外,还有计算属性可供选择。
<html>
<head>
<title>Vue 101</title>
</head>
<body>
<div id="app">
<label>What's your favorite game ever?</label>
<input type="text" v-model="favoriteGame">
<hr>
<p>{{ response }}</p>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data() {
return {
favoriteGame: null,
response: ''
}
},
watch: {
favoriteGame(newValue, oldValue) {
if (!newValue) return
if (newValue.toLowerCase().indexOf('metroid') !== -1) {
this.response = 'Ceres station is under attack!'
return
}
if (newValue.toLowerCase().indexOf('zelda') !== -1) {
this.response = 'Its dangerous to go alone, take this ?️'
return
}
if (
oldValue.toLowerCase().indexOf('metroid') !== -1 &&
newValue.toLowerCase().indexOf('metroid') === -1
) {
this.response = 'Nothing is true , everything is permitted'
return
}
this.response = 'Sure, why not?'
}
}
});
</script>
</body>
</html>
总结
恭喜你已经在学习 Vue 的道路上走这么远了!
现在,我确信你已经掌握了基础工具的使用,可以在 Vue 中实际构建一个非常溜的有实际功能的应用了。但是学海无涯,还有很多东西需要学习与探索以便你能榨干框架的全部能力。
不过不要担心,我曾提到过 Vue.js 最棒的地方就是它的 文档,并且我现在也还这样认为。
还记得我最开始试着写代码的时候,非常担心看不懂文档,因为技术文档一般都解释得很晦涩,并且还假定我已经对这个语言或者框架有着非常高的了解。
值得庆幸的是,Vue 文档团队对此做了很多出色的工作,为我们需要的所有功能撰写了完整的编程指南和示例代码,在本指南中我们已经详细介绍过了,除此之外你仍需要继续深入理解 Vue 框架。
Vue 实战入门系列到此结束!