📖 earlier posts 📖
在vue当中,还提供了一个v-on
指令来监听DOM事件,并使用一些鼠标、键盘方法来运行一些js code
,其中我们在上面几章已经讲述了v-on
指令的缩写为@
,本文我们将不会重复上述关于v-on
指令的信息。
鼠标左击处理 (@click \ v-on:click)
1 2 3 4 5 6 7 8 9 10 11 12 <div id="app"> <button @click="click += 1">增加</button> <p>当前增加次数为 {{click}} 次</p> </div> <script> var app = new Vue({ el: '#app', data: { click: 0 } }) </script>
方法调用 在上述的code中,如果用于复杂逻辑处理那么会直接写上 js code 是不可行的,所以vue自然而然的为我们提供了调用方法的方式:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <div id="app"> <button v-on:click="add">Add</button> </div> <script> var app = new Vue({ el: '#app', data: { counter: 0 }, methods: { add: function(event) { alert("当前数据默认被点击次数" + this.counter) if (event) { alert("被触发元素为:" + event.target.tagName) } } } }) </script>
内链调用处理 在上述我们演示到了方法调用以及鼠标动作处理等操作,其中鼠标左击处理也是通过内链
直接调用的,所谓内链就是与html 标签元素写在一起 即大多数都被称之为内链
。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <div id="app"> <button @click="echo('Hello,vue!')">Vue!</button> <button @click="echo('Hello,hello!')">Hello!</button> </div> <script> var app = new Vue({ el: '#app', data: { echo: function(message) { alert(message) } } }) </script>
修饰符 在之前我们讲到了vue的基本事件修饰符,本文我们紧接着上述内容进行详细讲解,首先:
v-on 鼠标修饰符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ```vue <div id="app"> </div> <form v-on:submit.prevent="onSubmit"> <a v-bind:href="url">Go blog</a> </form> <script> var app = new Vue({ el: '#app', data: { url: 'http://sif_one.gitee.io/' } }) </script>
那么其最后在 v-on
指令的笼罩下范围内的<a>
标签将会失去原本的作用:
ID
DA
FA
.stop
调用 event.stopPropagation()
停止传播
.prevent
调用 event.preventDefault()
防止默认
.capture
添加事件侦听器时使用capture(捕获) 模式
.self
只当事件从侦听器绑定元素本身触发时才进行回调
```.{keyCode
keyAlias} ```
只当事件从特定键触发时才进行回调
.native
监听组件根本元素的原生事件
.once
只触发一次回调
.left
只当点击鼠标左键时触发
.right
只当鼠标点击右键时触发
.middle
当鼠标中键时触发
.passive
以 { passive: true } 模式添加侦听器
在上述的修饰符中,在事件处理中经常会调用到event.stopPropagation
以及event.stopPropagation
等方法,但由于其主要处理纯粹的数据逻辑,并不处理BOM事件的写接 。
于是,vue为了解决这个问题,官方为其提供了事件的修饰符:
stop
prevent
capture
salf
once
passive
当然vue官方文档还提供了几个修饰符的组合例子:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 <!-- 阻止单击事件继续传播 --> <a v-on:click.stop="doThis"></a> <!-- 提交事件不再重载页面 --> <form v-on:submit.prevent="onSubmit"></form> <!-- 修饰符可以串联 --> <a v-on:click.stop.prevent="doThat"></a> <!-- 只有修饰符 --> <form v-on:submit.prevent></form> <!-- 添加事件监听器时使用事件捕获模式 --> <!-- 即内部元素触发的事件先在此处理,然后才交由内部元素进行处理 --> <div v-on:click.capture="doThis">...</div> <!-- 只当在 event.target 是当前元素自身时触发处理函数 --> <!-- 即事件不是从内部元素触发的 --> <div v-on:click.self="doThat">...</div>
在以上的修饰符进行组合的时候,请需要注意顺序,顺序不同可能最后表达的效果可能不一。。
不仅仅这样
众所周知,jq很多方法都需要使用鼠标事件,如鼠标单击事件,而vue 在2.2.0版本中,也增加了一个鼠标按钮修饰符:
ID
DA
.left
.right
.middle
键盘修饰符
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 ```vue <div id="app"> <input v-on:keyup.tab="echo"> </div> <script> var app = new Vue({ el: '#app', data: { echo: function(message) { alert("监听到了 tab 的键盘事件") } } }) </script>
在上述的code案例中,我们主要使用tab
案件码来配合键盘修饰符来监听tab
的键盘事件,vue一共所支持的按键修饰符共有9个,分别为:
ID
DA
.enter
.tab
.delete
.esc
.space
.up
.down
.left
.right
系统修饰符 当然,vue的v-on
指令还不仅仅以上这些,自然而然的还支持了系统修饰符,我们可以通过按下响应的按键触发监听器:
ID
DA
.ctrl
.alt
.shift
.meta
同样的,系统修饰符也可以进行组合,如官方文档中所提供的例子:
1 2 3 4 5 <!-- Alt + C --> <input v-on:keyup.alt.67="clear"> <!-- Ctrl + Click --> <div v-on:click.ctrl="doSomething">Do something</div>
需要注意的是,修饰符键于常规的不同,当keyup
事件一起使用的时候,修饰符键必须处于按下的状态 ,只有当按住tab
的情况下释放其他案件,才能被触发,所以如果需要实现那种行为,可以改为键代码为keyup.17
即可。
.exact 2.5.0中所新增的修饰符,可以**精确的控制系统修饰符组合并触发事件**,这里我们提供了vue的官方文档中所写的例子: 1 2 3 4 5 6 7 8 9 ```vue <!-- 即使 Alt 或 Shift 被一同按下时也会触发 --> <button v-on:click.ctrl="onClick">A</button> <!-- 有且只有 Ctrl 被按下的时候才触发 --> <button v-on:click.ctrl.exact="onCtrlClick">A</button> <!-- 没有任何系统修饰符被按下的时候才触发 --> <button v-on:click.exact="onClick">A</button>
从例子中可以看到使用.exact
修饰符进行系统修饰符的多种组合变得更加方便(且不用写键代码如keyup.17
)
除了vue所提供的v-if
指令之外,还提供了另一用于多次渲染元素的模块指令v-for
,首先需要提供遍历的元素
别名格式为:
当然我们也可以使用v-for
指令并基于数组来渲染列表,通常items
是源数据数组,而item
则是被迭代的数组元素别名。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <div id="app"> <p v-for="item in items" :key="item.message"> {{ item.message }} </p> </div> <script> var app = new Vue({ el: '#app', data: { items: [ {message: 'Vue'}, {message: 'Ajax'}, {message: 'Ejs'}, ] } }) </script>
父作用域属性(第二参数) 在v-for
块中还支持访问所有父作用域的属性,v-for
并支持第二参数:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div id="app"> <p v-for="(item, index) in items"> {{title}} - {{index}} - {{ item.message }} </p> </div> <script> var app = new Vue({ el: '#app', data: { title: 'Hello', items: [ {message: 'Vue'}, {message: 'Ajax'}, {message: 'Ejs'}, ] } }) </script>
其中index
属性对应的则是输出次数,为v-for
所支持的第二参数,其格式为:
遍历对象 除了遍历元素之外 ,for还可以遍历对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div id="app"> <p v-for="item in items"> {{item}} </p> </div> <script> var app = new Vue({ el: '#app', data: { items: { name: 'kun', age: '10' } } }) </script>
键名:元素 我们可以通过使用vue所提供的另一种方式即键名:元素
来循环遍历对象:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div id="app"> <p v-for="(value ,name) in items"> {{name}}:{{value}} </p> </div> <script> var app = new Vue({ el: '#app', data: { items: { name: 'kun', age: '10' } } }) </script>
维护状态 当v-for
渲染元素列表的时候,他会默认使用就地更新
的策略,如果数据被改变,vue将不会移动dom元素来匹配数据项的顺序。为了确保他们的每个索引位置正确的渲染 。
这个时候我们需要为每个节点写入一个唯一的key属性即:
1 2 3 <div v-for="item in items" v-bind:key="item.id"> <!-- 内容 --> </div>
在官方稳定那个中建议尽可能使用 v-for 时所提供的 key属性,除非遍历输出的DOM内容非常简单,或是希望性能上的提升
数组更新检测 变更方法
ID
DA
FA
push()
增加一个方法
pop()
从下往上突然的删除一个方法
shift()
从上往下删除一个方法
unshift()
从上方新加入一个方法
splice()
splice()
方法可用于添加、删除、替换 数组内的值
sort()
用于排序方法
reverse()
主要用于排序倒序
sort 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 <div id="app"> <p v-for="item in sortItems"> {{ item }} </p> </div> <script> var app = new Vue({ el: '#app', data: { items: [1,20,2,3,4,100], }, computed: { sortItems:function() { return this.items.sort(sortNumber) } }, }); function sortNumber(a,b) { return a-b } </script>
reverse() 1 2 3 4 5 6 7 8 9 10 11 12 13 <div id="app"> <p v-for="item in items.slice().reverse()"> {{ item }} </p> </div> <script> var app = new Vue({ el: '#app', data: { items: [1,2,3,4,5,6], } }) </script>
v-if …… v-if-else …… v-else
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div id="app"> <h1 v-if="message === 'Vue'">Vue</h1> <h1 v-else-if="message === 'Laravel'">Laravel</h1> <h1 v-else> 不是 Vue 也不是 Laravel </h1> </div> <script> var app = new Vue({ el: '#app', data: { faq: ' ', message: 'Vue' } }) </script>
当地一个条件满足Vue
的时候,则自然而然的显示Vue
,但如果第一条件不满足但满足了第二条件Laravel
,则自然而然的显示Laravel
,如果都不满足则输出v-else
指令内的信息。
v-if vue中我们可以通过使用v-if
有条件的渲染一块内容,就比如下述code中的message
值如果是true
则会显示:
1 2 3 4 5 6 7 8 9 10 11 12 <div id="app"> <h1 v-if="message">Vue is awesome!</h1> </div> <script> var app = new Vue({ el: '#app', data: { faq: ' ', message: false } }) </script>
v-else
1 2 3 4 5 6 7 8 9 10 11 12 13 <div id="app"> <h1 v-if="message">Vue is awesome!</h1> <h1 v-else="message">Hello,world</h1> </div> <script> var app = new Vue({ el: '#app', data: { faq: ' ', message: false } }) </script>
如果将message
的值为false
,那么则显示v-else
内的数据,当v-if
符合条件则显示其v-if
块的信息。
key 复用 key 通过使用key
我们可以管理可复用的元素,且vue也会尽可能的提高渲染的效率,使用可服用的元素的好处就是元素不会从头开始进行渲染 ,这也使得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 <div id="app"> <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address"> </template> <button @click="toggleLoginType">Toggle login type</button> </div> <script> var app = new Vue({ el: '#app', data: { loginType: 'username' }, methods: { toggleLoginType: function () { return this.loginType = this.loginType === 'username' ? 'email' : 'username' } } }) </script>
在上述code中,我们主要切换了loginType
的值,也就是当不满足username
条件的时候切换为else
块的placeholder
,而使得切换效果的功能主要通过v-on
进行实现。
唯一 key 复用key的缺点是表单内的信息也会被同步,而如果设置一个唯一的key,则每个数据都是独立的,服用的只是房子本身而并非里面的装饰物:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 <div id="app"> <template v-if="loginType === 'username'"> <label>Username</label> <input placeholder="Enter your username" key="username"> </template> <template v-else> <label>Email</label> <input placeholder="Enter your email address" key="email"> </template> <button @click="leghtLoginType">Toggle login type</button> </div> <script> var app = new Vue({ el: '#app', data: { loginType: 'username' }, methods: { leghtLoginType: function () { return this.loginType = this.loginType === 'username' ? 'email' : 'username' } } }) </script>
v-show 在前端的开发当中我们经常会使用一个非常棒的方法即display
,通常当display
的值如果为none
则不会进行显示。在vue中,v-show
主要用于切换display
的CSS 属性:
1 2 3 4 5 6 7 8 9 10 11 <div id="app"> <h1 v-show="show">Hello,Vue</h1> </div> <script> var app = new Vue({ el: '#app', data: { show: true } }) </script>
当在控制端中执行app.show=false
的时候,则此时<h1>
标签的css属性将会更改为display: none
,则不可见,v-if
与v-show
的区别可以是:
ID
DA
v-if
通过vue进行条件渲染,确保在切换的过程中被销毁和重建
v-show
不管条件如何,元素依然会被显然,只是根据 CSS display 属性进行切换
v-if
拥有更高的切换开销,v-show
则有更高的初始渲染 的开销
计算属性 尽管vue内的表达式非常便利,但设计他们的初衷依然是用于进行简单的运算,如下方的code主要用于翻转字符串:
1 2 3 4 5 6 7 8 9 10 11 <div id="app"> {{message.split('').reverse().join('')}} </div> <script> var app = new Vue({ el: '#app', data: { message: 'hello,world' } }) </script>
但是如果我们想要在模板中多处 翻转字符串的时候就会变得非常繁琐,所以对于复杂的处理我们一般使用computed
属性,即```所有getter和setter上的this上下文都会被绑定在Vue的实例中:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div id="app"> {{ reversedMessage }} </div> <script> var app = new Vue({ el: '#app', data: { message: 'hello,world' }, computed: { reversedMessage: function() { return this.message.split('').reverse('').join('') } } }) </script>
在此时,我们首先声明了一个计算属性为reversedMessage
,并提供了函数将作特征为 app.reversedMessage
的getter
函数,同样的我们也可以在控制台中通过使用app.message="vue"
来进行修改。
通过计算属性,vue知道app.reversedMessage
依赖或引用于app.message
所以当app.message
发生改变的时候,依赖他的数据自然会被更新。
计算属性和方法 在官方文档中该标题为 计算属性 vs 方法
很显然虽然两者最后都会达到同样的效果:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 <div id="app"> {{ reversedMessage() }} </div> <script> var app = new Vue({ el: '#app', data: { message: 'hello,world' }, methods: { reversedMessage: function() { return this.message.split('').reverse().join('') } } }) </script>
但是不同的是计算属性
是基于他的响应式依赖进行缓存的,当相关响应式以来发生改变的时候才会重新渲染,所以这就意味着只要````app.message没事不进行该ian,多次访问
reversedMessage```并不会立即返回计算之前的效果或再次执行 。
相比之下与每次访问都要重新进行寻安然,调用方法然后在再次执行函数的操作很明显前者较为优秀。
计算属性和侦听属性 vue为我们提供了一种更加通用的方式来观察响应vue实例上的数据变动即watch
的侦听属性,当有一些数据需要随着其他数据进行变动的时候,可以使用watch属性 :
watch 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <script> var app = new Vue({ el: '#app', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, watch: { firstName: function(val) { this.fullName = val + '' + this.lastName }, lastName: function(val) { this.fullName = this.firstName + '' + val } } }) </script>
computed 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <script> var app = new Vue({ el: '#app', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, computed: { fullName: function () { return this.firstName + '' + this.lastName } } }) </script>
ID
DA
watch
computed
通过上述的演示我们就可以非常轻松的了解到watch的作用,当很多数据需要随着其他数据改变而改变的时候,这个时候使用watch
就非常的适当,而computed
对于单个的数据较为有优势。
getter 与 setter 1 2 getter 与 setter getter 主要用于检索变量,而setter则用于更新变量的值
computed默认用于检索变量,如果想实现于watch
差不多的作用那么我们可以增加一下setter
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 <div id="app"> {{ fullName }} </div> <script> var app = new Vue({ el: '#app', data: { firstName: 'Foo', lastName: 'Bar', fullName: 'Foo Bar' }, computed: { fullName: { // getter get: function () { return this.firstName + ' ' + this.lastName }, // setter set: function (newValue) { var names = newValue.split(' ') this.firstName = names[0] this.lastName = names[names.length - 1] } } } }) </script>
侦听器 vue为开发者所提供了一种更加丝滑的API为watch
,vue在实例化的同时调用watch
,来遍历 watch对象内的所有属性。
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 <div id="app"> <input v-model="faq"> <p>{{answer}}</p> </div> <script src="https://cdn.jsdelivr.net/npm/axios@0.12.0/dist/axios.min.js"></script> <script src="https://cdn.jsdelivr.net/npm/lodash@4.13.1/lodash.min.js"></script> <script> var app = new Vue({ el: '#app', data: { faq: ' ', answer: '请输入信息' }, watch: { faq: function(newQuestion, oldQuestion) { this.answer = '正在输入……' this.debouncedGetAnswer() } }, created: function() { this.debouncedGetAnswer = _.debounce(this.getAnswer,500) }, methods: { getAnswer: function() { if(this.faq.indexOf('?') === -1) { this.answer = '输入的时候请加上一个问号' return } this.answer = '正在检索' var vm = this axios.get('https://yesno.wtf/api') .then(function(response) { vm.answer = _.capitalize(response.data.answer) }) .catch(function(error) { vm.answer = 'API内并没有此数据' + error }) } } }) </script>
Vue.js主要使用了基于HTML
的模板语法,允许开发者声明式的将DOM绑定至底层的Vue实例数据,由于Vue.js基于HTML模板语法,所以所编写的自然而然能被浏览器所解析(除了远古浏览器)。
插值 插值主要包含了文本、原始HTML、属性、原始表达式
等四类,其中我们会在本章一一进行介绍:
文本 Mustache 在Vue.js中,常见的数据绑定形式就使用Mustache
语法来进行插值,即<p>{{message}}</p>
,这里的Mustache是一款经典的前端模板引擎,而Mustache的价值在其稳定以及经典,其中在Vui内的{{……}}
写法就类似与Mustache模板引擎的语法:
v-once Vue.js为我们提供了一个类似与Object.freeze()
阻止修改的方法,而vue又为我们提供了另一种方法即v-once
指令,通过v-once
指令我们可以进行一次性插值,当数据改变的时候,内容将不会被更新 .
1 2 3 4 5 6 7 8 9 10 11 <div id="app"> <span v-once>{{ message }}</span> </div> <script> var vm = new Vue({ el: "#app", data: { message: 'Hello,world' } }) </script>
原始 HTML 通常在为我们提供指令的时候一般都会提供一个输出原始HTML
的指令。Vue并不例外,Vue所提供的指令是v-html
,即:
1 <div v-html="html"></div>
建议 v-html指令预期是字符串类型
,内容按照HTML
进行插入,不会被当作vue
模板进行编译。使用v-html
指令可能会出现一些安全问题,所以我们尽量在一些不容易发生问题的地方使用。
v-bind v-bind:id 在默认的情况下Mustache语法并不能
使用在HTML 属性中(在vue编译的范围内),当遇到这种情况的时候我们可以使用v-bind
指令:
1 2 3 4 5 6 7 8 9 <div v-bind:id="app">{{Hello}}</div> <script> var vm = new Vue({ el: "#app", data: { message: 'Hello,world' } }) </script>
如果你还不能理解上面的Code以及v-bind
指令,我们可以通过下方code来进行理解:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 <div v-bind:id="app">{{Hello}}</div> <div id="app"> <p>{{hello}}</p> </div> <script> var vm = new Vue({ el: "#app", data: { message: 'Hello,world' } }) </script>
在上述的code中,使用v-bind
指令的html属性将会在vue编译的范围内进行输出,而未使用b-bind
指令的html属性将不会进行输出。
v-bind:src 通过使用v-bind:src
指令,我们可以绑定一个src属性的比如img
元素:
1 2 3 4 5 6 7 8 9 10 11 <div id="app"> <img v-bind:src="img" alt=""> </div> <script> var vm = new Vue({ el: "#app", data: { img: 'https://img-home.csdnimg.cn/images/20201124032511.png' } }) </script>
当然v-bind
指令还可以支持缩写为:
,及上述img
元素重构为:
v-pind:class 除了id~src
之外,还支持class
等方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 <style> .red { color: red; } </style> <body> <div id="app"> <p v-bind:class="colorRed">Hello,world</p> </div> <script> var vm = new Vue({ el: "#app", data: { colorRed: 'red' } }) </script>
1 2 3 4 ```vue <div id="app"> <p v-bind:class="[one, two]">Hello,world</p> </div>
Vue 通过class red
添加到vue的渲染队列中,最后使用v-pind:class
来引入colorRed
。
v-pind:style
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 <style> .red { color: red; } </style> <body> <div id="app"> <p v-bind:style="colorRed">Hello,world</p> </div> <script> var vm = new Vue({ el: "#app", data: { colorRed: { color: 'red', fontSize: "20px" } } }) </script>
1 2 3 4 ```vue <div id="app"> <p v-bind:style="[one, two]">Hello,world</p> </div>
v-pind:href 除了以上的几种v-pind
参数之外,自然还支持了href
参数
1 2 3 4 5 6 7 8 9 10 11 <div id="app"> <a v-bind:href="url">Go blog</a> </div> <script> var app = new Vue({ el: '#app', data: { url: 'http://sif_one.gitee.io/' } }) </script>
JavaScript 表达式 vue对javascript表达式有良好的支持,且并不限于表达式,甚至包括语句:
1 2 3 4 5 6 7 8 9 10 11 <div id="app"> {{message + ',vue!'}} </div> <script> var app =new Vue({ el: '#app', data: { message: 'hello' } }) </script>
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 <div id="app"> {{ ok ? 'YES!' : 'NO!' }}<br> </div> <script> var app = new Vue({ el: '#app', data: { ok: false, } }) </script> ``` ## 指令  指令即(Directives)则在vue中则是代表有```v-```前缀的特殊属性,当表达式改变的时候也会将行为应用到DOM内: ```vue <div id="app"> <p v-if="seen">Hello,world!</p> </div> <script> var app = new Vue({ el: '#app', data: { seen: true, } }) </script>
由于将属性加入到了DOM对象内,所以我们可以通过控制台来进行操作对象,就如本文中我们将此来实现显示以及隐藏等。
参数 当介绍完指令之后,自然而然的就是轮到了参数,就以上述的code为例子,v-if
为属性,而seen
为参数,如果要写我们可以这样:
1 2 3 4 5 6 7 8 9 10 11 <div id="app"> <a v-bind:href="url">Go blog</a> </div> <script> var app = new Vue({ el: '#app', data: { url: 'http://sif_one.gitee.io/' } }) </script>
修饰符 v-on
1 2 3 4 5 6 7 8 9 10 11 12 13 14 ```vue <div id="app"> </div> <form v-on:submit.prevent="onSubmit"> <a v-bind:href="url">Go blog</a> </form> <script> var app = new Vue({ el: '#app', data: { url: 'http://sif_one.gitee.io/' } }) </script>
那么其最后在 v-on
指令的笼罩下范围内的<a>
标签将会失去原本的作用:
ID
DA
FA
.stop
调用 event.stopPropagation()
停止传播
.prevent
调用 event.preventDefault()
防止默认
.capture
添加事件侦听器时使用capture(捕获) 模式
.self
只当事件从侦听器绑定元素本身触发时才进行回调
```.{keyCode
keyAlias} ```
只当事件从特定键触发时才进行回调
.native
监听组件根本元素的原生事件
.once
只触发一次回调
.left
只当点击鼠标左键时触发
.right
只当鼠标点击右键时触发
.middle
当鼠标中键时触发
.passive
以 { passive: true } 模式添加侦听器
缩写 虽然已经在上述说明中标注了其指令的缩写,但为了视觉效果和让读者感觉非常重要,还是要单独列一个标题来着重标注 。
Vue.js最为不同且便捷的方式就是,基本上每个指令都会有一个缩写,其中v-
前缀作为一种视觉提示,可用来辨别vue特定的属性,就如本文我们所出现的 v-bind
、v-on
缩写分别为:
以及@
。
MVVM MVVM是Model-View-ViewModel
的缩写,即模型-视图-视图模型
,MVVM最早是由微软所提出,主要借鉴了MVC的思想,前端页面中,将模型用Javascript对象表示 ,View负责显示,而将模型与视图关联起来的叫 ViewModel ,ViewModel负责将模型
数据同步到视图
显示。
如果说到Vue前面为什么要举那么多修改DOM的例子,那无非就是之为读者学习 Vue 实例所铺路,虽然Vue并没有完全的遵守 MVVM模型
但是Vue受到了启发。
如果你说jquery与vue来修改DOM节点的区别那么我们可以使用以下例子来进行分别,你会发现vue的确是受到了 MVVM 的启发:
jquery 1 2 var name = 'jquery'; $('#name').text(name);
MVVM 1 2 3 4 5 6 7 8 9 10 11 12 var person = { name: 'Bart', }; ``` 当改变 JavaScript对象的时候,也将会导致DOM结构或数据作出相应的变化,MVVM的出现让我们的从如何操作DOM变成了**如何改变JavaScript**对象数据或状态,这也是MVVM的设计思想之一。 ## 创建一个 Vue 实例 Vue的应用创建可以通过 Vueh函数来创建一个新的实例开始,如: ```vue var vm = new Vue({ // code })
虽然 Vue并没有完全遵循 MVVM模型,但是其设计也收到了启发,所以在其官方文档中依然会使用vm
即(ViewModel)缩写来作为 Vue 的实例。
数据与方法 在Vue实例被创建的时候,他会将 data
对象中的所有属性加入到 vue内,当这些属性的值发生改变的时候,试图将会产生一个响应
,来匹配更新为新的值:
1 2 3 4 5 6 var vm = new Vue({ el: "#app", data: { message: 'Hello,world' } })
当这些数据被改变的时候,视图会进行重新渲染
只有当实例被创建的时候就已经存在data
中的属性才是响应式的 ,如果你在控制台内想新添加一个属性,且一开始他为空且不存在,那么将不会触发任何的视图更新,此时需要设置初始值,详情可以查看官方文档内的 : https://vuejs.bootcss.com/guide/instance.html 章节。
当然有了初始值,以及修改的,自然会出现一个组织修改现有属性的方法即Object.freeze()
,即:
1 2 3 4 5 6 7 var vm = new Vue({ el: "#app", data: { message: 'Hello,world' } }) Object.freeze(vm)
在接触 Vue 自定义指令的之前,我们需要了解到 钩子函数
,在 Windows 中,钩子函数实在 Windows 消息处理机制中的一部分,可以通过设置钩子来实现自己想要的需要效果。在 Vue 中每个被创建的实例都需要经过一系列初始化的过程,如果需要设置数据监听、编译或挂载DOM时,会调用一个生命周期
的钩子,而此时我们可以在此加入一些code来实现自己想要的效果。
钩子函数 钩子函数即在Vue实例中插入一段code来满足自己下需求,截至vue 2.x 版本内,共支持的钩子函数共有:
ID
DA
bind
只调用一次,指令第一次绑定到元素的时候调用,一般进行一次性的初始化设置
inserted
被绑定元素插入父节点时调用
update
被绑定元素的模板被更新时进行调用,无论绑定值是否变化。通过比较更新前和更新后的值,可以忽略不必要的模板进行更新
componentUpdate
被绑定的元素所在模板完成一次新的周期时被调用
unbind
指令与元素解绑时进行调用一次
钩子参数
ID
DA
el
指令绑定的元素
binding
一个对象且包含以下属性
name 指令名(不需要包括 v- 前缀)
value 指令的绑定值
oldValue
expression 字符串形式的表达式指令
arg 传给指令的参数,如 v-directive:foo
其中参数为 foo
modifiers
vnode
Vue 编译生成的虚拟节点
oldVnode
上一个虚拟节点,仅在 update 、 componentUpdated 钩子中使用```
自定义指令 全局指令 我们以一个非常经典的案例作为一个例子,当页面加载的时候,该选素将会获得焦点:
1 2 3 4 5 6 7 8 9 10 11 12 13 <div id="app"> <input v-focus> </div> <script> Vue.directive('focus', { inserted: function(el) { el.focus() } }) new Vue({ el: '#app' }) </script>
通过 directive
我们注册了一个名为focus
的全局组件,其主要作用就是:“当该页面加载的时候”,他会自动获取焦点仅此而已,并且我们还使用了inserted
钩子函数,以用于绑定父节点中欧调用focus
。
局部指令 通常而言,全局自定义指令与局部自定义指令之间的区别可以从code看出,全局注册指令是单独来写的即:
1 2 3 4 5 Vue.directive('focus', { inserted: function(el) { el.focus() } })
而局部自定义指令是在初始化vue
时写的,即之可以在本身的Vue实例中进行使用,除此之外他们之间的区别还可以是一个是通过directive
来定义,另一个则是通过使用directives
来实现的。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <div id="app"> <input v-focus> </div> <script> new Vue({ el: '#app', directives: { focus: { inserted: function(el) { el.focus() } } } }) </script>
初始化 在通常情况下,不同组件之间的动态切换可以让页面变得更加的拥有趣味,且可以减少一些不必要的从页面占用。动态组建可以用于构建一些非动态的填写,而如果需要满足一些OAuth
等切换或登录的场景,则需要使用 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 40 41 42 43 <div id="example"> <button @click="methodsAll">Go</button> <component v-bind:is="componentView"></component> </div> <script> var one = { template: ` <div>one Template</div> ` }; var two = { template: ` <div>two Template</div> ` }; var three = { template: ` <div>three Template</div> ` }; new Vue({ el: '#example', components: { one, two, three, }, data:{ index:0, list:['one','two','three'], }, computed:{ componentView(){ return this.list[this.index]; } }, methods:{ methodsAll(){ this.index = (++this.index)%3; } } }) </script>
keep-alive Vue创建一个新的 ```componentView``` 实例,也就是说只要通过使用```keep-alive```方法进行包裹,即可让他们在```第一次```创建时会被进行**缓存**,即保存刚刚切换后的数据,为了更加的体现```keep-alive```效果,我们可以使用表单来进行验证: 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 | ID | DA | | --- | --- | | 使用 keep-alive |  | | 不使用 keep-alive |  | ```vue <div id="example"> <button @click="methodsAll">Go</button> <keep-alive> <component v-bind:is="componentView"></component> </keep-alive> </div> <script> var one = { template: ` <input type="text"> ` }; var two = { template: ` <div>two Template</div> ` }; var three = { template: ` <div>three Template</div> ` }; new Vue({ el: '#example', components: { one, two, three, }, data:{ index:0, list:['one','two','three'], }, computed:{ componentView(){ return this.list[this.index]; } }, methods:{ methodsAll(){ this.index = (++this.index)%3; } } }) </script>
插槽在Vue组件中,是一个极为不可缺少的一个部分,对于插槽,我们可以理解为我们首先定义了一个 Error
,之后通过使用<slot>
元素让其输出关于Error
后相关的内容,这在 Vue中通常被称之为后备内容
。
默认插槽 1 2 3 4 5 6 7 8 9 10 11 12 13 <div id="app"> <solt-name></solt-name> </div> <script> Vue.component('soltName', { template: ` <div>Hello</div> ` }) var vm = new Vue({ el: '#app', }) </script>
后备内容 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 <div id="app"> <solt-name>world!</solt-name> </div> <script> Vue.component('soltName', { template: ` <div>Hello, <slot></slot> </div> ` }) var vm = new Vue({ el: '#app', }) </script>
具名插槽 有时候我们如果需要多个插槽,那么通俗的来讲就是为分配一个名字
,在一般的情况下没有名字的插槽将会被认定为是一个默认插槽
,在上图中,我们主要定义了导航、正文、结尾
等三个插槽,其中默认插槽 被应用在导航中,而正文、结尾
主要被具名插槽 中的two
以及three
进行填写:
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 <style> .orset { margin-top: 10%; } </style> <div id="app"> <solt-name> <div class="orset" slot="two">正文</div> <div class="orset" slot="three">结尾</div> </solt-name> </div> <script> Vue.component('soltName', { template: ` <div> <solt>默认插槽</solt> <slot name="two"></slot> <slot name="three"></slot> </div> ` }) var vm = new Vue({ el: '#app', }) </script>
作用域插槽 作用域插槽作为 vue 插槽中最为详细的一部分不仅仅是适用范围广,通常还可以搭配着 vue 指令来进行输出,本次案例我们主要会通过使用for
来循环以及使用if
来分别针对且有条件的对数据进行输出与使用:
输出 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 <div id="app"> <slot-name :lists="Teamname"> <template slot-scope="slotvm"> {{slotvm}} </template> </slot-name> </div> <script> Vue.component('slotName', { props: ['lists'], template: ` <div> <p v-for="list in lists"> <slot v-bind="list"></slot> </p> </div> ` }) var vm = new Vue({ el: '#app', data: { Teamname: [ { id:1, name: 'Jiangxue' }, { id:2, name: 'Sif one' }, { id:3, name: 'ZhongShan' } ] } }) </script>
条件输出
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 <div id="app"> <slot-name :lists="Teamname"> <template v-if="slotvm.id==1" slot-scope="slotvm"> {{slotvm.name}} </template> </slot-name> </div> <script> Vue.component('slotName', { props: ['lists'], template: ` <div> <p v-for="list in lists"> <slot v-bind="list"></slot> </p> </div> ` }) var vm = new Vue({ el: '#app', data: { Teamname: [ { id:1, name: 'Jiangxue' }, { id:2, name: 'Sif one' }, { id:3, name: 'ZhongShan' } ] } }) </script>
在上述code中,我们首先将数据使用v-for
来进行循环输出,之后在通过使用v-if
以及使用v-bind
来进行绑定属性,最终通过满足条件即 Teamname
中,id 为1的键值名称
得到且输出。
va: http://jsrun.net/v2NKp/edit
事件在vue中主要被定义为当你点击
他的时候,他会作出什么反映,这就比如我们前几章所介绍的当按下鼠标时,则值每次分别增加1
,则这种被称之为“事件”。
事件命名 Vue的事件命名不同于 prop,即事件名不存在任何的自动化大小写转换
,即触发、监听的事件必须完全匹配这个事件所用的名称,如:
事件定义 在Vue 中我们可以通过使用v-on
指令或者@
来简写作为 DOM 元素的事件绑定,而除此之外我们还可以使用 Vue 事件接口(Eventd interface)
中的
$on (eventName)
$emit(eventName)
通过上述 Vue 接口事件,可分别使用$on
来进行监听事件 以及将$emit
用于触发事件 。
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 <div id="app"> <div id="event-example"> <button-event v-on:event="eventGo"></button-event> <button-event v-on:event="eventGo"></button-event> </div> </div> <script> Vue.component('button-event', { template: '<button v-on:click="increaseUp">{{ echo }}</button>', data: function() { return { echo: 0 } }, methods: { increaseUp: function() { this.echo +=1 this.$emit('event') } }, }) new Vue({ el: '#event-example', data: { total: 0 }, methods: { eventGo: function() { this.total += 1 } } }) </script>
v-model 自定义组件 表单 Vue 中v-model
指令可以用于在表单或组件上自动创建一个双向的绑定,就为明显的例子无非就是获取表单输入,通过表单输入
以及获取表单
输入即可是一个双向绑定 ,如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 <div id="app"> <model-input v-model="number"></model-input> <p>{{number}}</p> </div> <script> Vue.component('model-input', { template: ` <input ref="input" :value="value" @input="$emit('input',$event.target.value)"> `, props: ['value'], }) new Vue({ el: '#app', data: { number: null, } }) </script>
多选 在上述的流程图中,我们合租要通过使用v-on
以及v-show
来分别判断鼠标事件以及真假值
的判断,当check
被点击的时候,则默认将v-show
改变为 true
状态使得其变得可见,默认为false
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 <div id="app"> <show-checkbox v-model="check"></show-checkbox> <div v-show="check"> 以同意相关注册协议 </div> </div> <script> Vue.component('show-checkbox', { model: { prop: 'checked', event: 'change' }, props: { checked: Boolean }, template: ` <input type="checkbox" v-bind:checked="checked" v-on:change="$emit('change', $event.target.checked)" > ` }) new Vue({ el: '#app', data: { check: false } }) </script>
📖 more posts 📖