动力节点Vue笔记第二章 Vue核心技术
20/100
发布文章
assdfgdfgjhtdo
未选择任何文件
new
.stop - 调用 event.stopPropagation()。
*<div** @click="san"**>**
3. **<div** @click.stop="er"**>**
4. **<button** @click="yi"**>**{{name}}**</button>**
5. **</div>**
6. **</div>**
.prevent - 调用 event.preventDefault()。
**<a** href="http://www.bjpowernode.com" @click.prevent="yi"**>**
3. {{name}}
4. **</a>**
.capture - 添加事件侦听器时使用 capture 模式。
**<div** @click.capture="san"**>**
3. **<div** @click.capture="er"**>**
4. **<button** @click="yi"**>**{{name}}**</button>**
5. **</div>**
6. **</div>**
注意:只有添加了capture修饰符的元素才会采用捕获模式。(或者说带有capture修饰符的优先触发)
.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。
**<div** @click="san"**>**
1. **<div** @click.self="er"**>**
2. **<button** @click="yi"**>**{{name}}**</button>**
3. **</div>**
4. **</div>**
.once - 只触发一次回调。
5.
**<button** @click.once="yi"**>**
6. {{name}}
7. **</button>**
.passive - (2.3.0) 以 { passive: true } 模式添加侦听器
1.无需等待,直接继续(立即)执行事件默认行为。(对wheel事件有效果)
2. .passive 和 .prevent 修饰符不能共存。
常用的按键修饰符包括:
.enter
.tab (只能配合keydown使用)
.delete (捕获“删除”和“退格”键)
.esc
.space
.up
.down
.left
.right
可以直接将 KeyboardEvent.key 暴露的任意有效按键名转换为 kebab-case 来作为修饰符。
可以通过全局 config.keyCodes 对象自定义按键修饰符别名
Vue.config.keyCodes.huiche = 13
系统修饰键包括4个
.ctrl
.alt
.shift
.meta
系统修饰键在使用时应注意:
只有当系统修饰键和其他键组合使用,并且组合键释放时,才会触发keyup事件。
只要按下系统修饰键,就会触发keydown事件。
小技巧
data中的是属性。用data的属性经过计算得出的全新的属性就是计算属性。
**<div** id="app"**>**
3. **<h1>**{{msg}}**</h1>**
4. 输入的信息:**<input** type="text" v-model="info"**><br>**
5. 反转的信息:{{reversedInfo}} **<br>**
6. 反转的信息:{{reversedInfo}} **<br>**
7. 反转的信息:{{reversedInfo}} **<br>**
8. 反转的信息:{{reversedInfo}} **<br>**
9. **</div>**
10. **<script>**
11. const vm = new Vue({
12. el : '#app',
13. data : {
14. msg : '计算属性-反转字符串案例',
15. info : ''
16. },
17. computed : {
18. reversedInfo:{
19. get(){
20. console.log('getter被调用了');
21. return this.info.split('').reverse().join('')
22. },
23. set(val){
24. //this.reversedInfo = val // 不能这样做,这样会导致无限递归
25. this.info = val.split('').reverse().join('')
26. }
27. }
28. }
29. })
30. **</script>**
只考虑读取,不考虑修改时,可以启用计算属性的简写形式。
computed : {
2. reversedInfo(){
3. console.log('getter被调用了');
4. **return** **this**.info.split('').reverse().join('')
5. }
6. }
使用watch实现:比较数字大小的案例
**<div** id="app"**>**
2. **<h1>**{{msg}}**</h1>**
3. 数值1:**<input** type="text" v-model="number1"**><br>**
4. 数值2:**<input** type="text" v-model="number2"**><br>**
5. 比较大小:{{compareResult}}
6. **</div>**
7. **<script>**
8. const vm = new Vue({
9. el : '#app',
10. data : {
11. msg : '侦听属性的变化',
12. number1 : 1,
13. number2 : 1,
14. compareResult : ''
15. },
16. watch : {
17. number1 : {
18. immediate : true,
19. handler(newVal, oldVal){
20. let result = newVal - this.number2
21. if(result **>** 0){
22. this.compareResult = newVal + '**>**' + this.number2
23. }else if(result **<** **0**){
24. this.compareResult = newVal + '**<**' + this.number2
25. }else{
26. this.compareResult = newVal + '=' + this.number2
27. }
28. }
29. },
30. number2 : {
31. immediate : true,
32. handler(newVal, oldVal){
33. let result = this.number1 - newVal
34. if(result **>** 0){
35. this.compareResult = this.number1 + '**>**' + newVal
36. }else if(result **<** **0**){
37. this.compareResult = this.number1 + '**<**' + newVal
38. }else{
39. this.compareResult = this.number1 + '=' + newVal
40. }
41. }
42. }
43. }
44. })
45. **</script>**
运行效果:
数据绑定的一个常见需求场景是操纵元素的 CSS class 列表和内联样式。因为 class 和 style 都是 attribute,我们可以和其他 attribute 一样使用 v-bind 将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且易出错的。因此,Vue 专门为 class 和 style 的 v-bind 用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组。
适用于样式的名字不确定,需要动态指定。
. <!DOCTYPE html**>**
2. **<html** lang="en"**>**
3. **<head>**
4. **<meta** charset="UTF-8"**>**
5. **<title>**class绑定字符串形式**</title>**
6. **<script** src="../js/vue.js"**></script>**
7. **<style>**
8. .static{
9. border: 1px solid black;
10. background-color: beige;
11. }
12. .big{
13. width: 200px;
14. height: 200px;
15. }
16. .small{
17. width: 100px;
18. height: 100px;
19. }
20. **</style>**
21. **</head>**
22. **<body>**
23. **<div** id="app"**>**
24. **<h1>**{{msg}}**</h1>**
25. **<div** class="static" :class="c1"**></div>**
26. **</div>**
27. **<script>**
28. const vm = new Vue({
29. el : '#app',
30. data : {
31. msg : 'class绑定字符串形式',
32. c1 : 'small'
33. }
34. })
35. **</script>**
36. **</body>**
37. **</html>**
运行效果:
使用vue开发者工具修改c1的small为big:
通过测试可以看到样式完成了动态的切换。
适用于绑定的样式名字不确定,并且个数也不确定。
<!DOCTYPE html**>**
2. **<html** lang="en"**>**
3. **<head>**
4. **<meta** charset="UTF-8"**>**
5. **<title>**class绑定数组形式**</title>**
6. **<script** src="../js/vue.js"**></script>**
7. **<style>**
8. .static{
9. border: 1px solid black;
10. }
11. .active{
12. background-color: green;
13. }
14. .text-danger{
15. color: red;
16. }
17. **</style>**
18. **</head>**
19. **<body>**
20. **<div** id="app"**>**
21. **<h1>**{{msg}}**</h1>**
22. **<div** class="static" :class="['active','text-danger']"**>**数组形式**</div>**
23. **<br><br>**
24. **<div** class="static" :class="[activeClass,errorClass]"**>**数组形式**</div>**
25. **<br><br>**
26. **<div** class="static" :class="classArray"**>**数组形式**</div>**
27. **</div>**
28. **<script>**
29. const vm = new Vue({
30. el : '#app',
31. data : {
32. msg : 'class绑定数组形式',
33. activeClass : 'active',
34. errorClass : 'text-danger',
35. classArray : ['active', 'text-danger']
36. }
37. })
38. **</script>**
39. **</body>**
40. **</html>**
运行效果:
使用vue开发者工具删除数组中的一个样式:
适用于样式名字和个数都确定,但是要动态决定用或者不用。
. <!DOCTYPE html**>**
2. **<html** lang="en"**>**
3. **<head>**
4. **<meta** charset="UTF-8"**>**
5. **<title>**class绑定对象形式**</title>**
6. **<script** src="../js/vue.js"**></script>**
7. **<style>**
8. .static{
9. border: 1px solid black;
10. }
11. .active{
12. background-color: green;
13. }
14. .text-danger{
15. color: red;
16. }
17. **</style>**
18. **</head>**
19. **<body>**
20. **<div** id="app"**>**
21. **<h1>**{{msg}}**</h1>**
22. **<div** class="static" :class="{active : true, 'text-danger' : true}"**>**对象形式**</div>**
23. **<br><br>**
24. **<div** class="static" :class="classObject"**>**对象形式**</div>**
25. **</div>**
26. **<script>**
27. const vm = new Vue({
28. el : '#app',
29. data : {
30. msg : 'class绑定对象形式',
31. classObject : {
32. active : true,
33. 'text-danger' : false
34. }
35. }
36. })
37. **</script>**
38. **</body>**
39. **</html>**
运行效果:
使用vue开发者工具修改text-danger为true:
**<div** id="app"**>**
2. **<h1>**{{msg}}**</h1>**
3. <!-- 静态写法 -->
4. **<div** class="static" style="font-size: 20px;"**>**对象形式**</div><br><br>**
5. <!-- 动态写法1 -->
6. **<div** class="static" :style="{fontSize: 40 + 'px'}"**>**对象形式**</div><br><br>**
7. <!-- 动态写法2 -->
8. **<div** class="static" :style="styleObject"**>**对象形式**</div><br><br>**
9. **</div>**
10. **<script>**
11. const vm = new Vue({
12. el : '#app',
13. data : {
14. msg : 'style绑定对象形式',
15. styleObject : {
16. fontSize : '40px'
17. }
18. }
19. })
20. **</script>**
**<div** id="app"**>**
2. **<h1>**{{msg}}**</h1>**
3. <!-- 静态写法 -->
4. **<div** class="static" style="font-size: 40px; color: red;"**>**数组形式**</div><br><br>**
5. <!-- 动态写法1 -->
6. **<div** class="static" :style="[{fontSize:'40px'},{color:'red'}]"**>**数组形式**</div><br><br>**
7. <!-- 动态写法2 -->
8. **<div** class="static" :style="styleArray"**>**对象形式**</div><br><br>**
9. **</div>**
10. **<script>**
11. const vm = new Vue({
12. el : '#app',
13. data : {
14. msg : 'style绑定对象形式',
15. styleArray : [
16. {fontSize:'40px'},
17. {color:'red'}
18. ]
19. }
20. })
21. **</script>**
指令用于条件性地渲染一块内容。这块内容只会在指令的表达式返回true时才被渲染
**<div** id="app"**>**
2. **<h1>**{{msg}}**</h1>**
3. 温度:**<input** type="number" v-model="temprature"**><br>**
4. 天气:
5. **<span** v-if="temprature <= 10"**>**寒冷**</span>**
6. **<span** v-if="temprature > 10 && temprature <= 25"**>**凉爽**</span>**
7. **<span** v-if="temprature > 25"**>**炎热**</span>**
8. **</div>**
9. **<script>**
10. const vm = new Vue({
11. el : '#app',
12. data : {
13. msg : '条件渲染',
14. temprature : 10
15. }
16. })
17. **</script>**
运行效果:
顾名思义,v-else-if 提供的是相应于 v-if 的“else if 区块”。它可以连续多次重复使用。
一个使用 v-else-if 的元素必须紧跟在一个 v-if 或一个 v-else-if元素后面。
你也可以使用 v-else 为 v-if 添加一个“else 区块”,当然,v-else元素也是必须紧跟在一个 v-if 或一个 v-else-if元素后面。
**<div** id="app"**>**
2. **<h1>**{{msg}}**</h1>**
3. 温度:**<input** type="number" v-model="temprature"**><br>**
4. 天气:
5. **<span** v-if="temprature <= 10"**>**寒冷**</span>**
6. **<span** v-else-if="temprature <= 25"**>**凉爽**</span>**
7. **<span** v-else**>**炎热**</span>**
8. **</div>**
9. **<script>**
10. const vm = new Vue({
11. el : '#app',
12. data : {
13. msg : '条件渲染',
14. temprature : 10
15. }
16. })
17. **</script>**
因为 v-if 是一个指令,他必须依附于某个元素。但如果我们想要切换不止一个元素呢?在这种情况下我们可以在一个 元素上使用 v-if,这只是一个不可见的包装器元素,最后渲染的结果并不会包含个 元素。v-else 和 v-else-if 也可以在 上使用。
**<div** id="app"**>**
2. **<h1>**{{msg}}**</h1>**
3. 温度:**<input** type="number" v-model="temprature"**><br>**
4. 天气:
5. **<template** v-if="temprature <= 10"**>**
6. **<span>**寒冷**</span>**
7. **</template>**
8. **<template** v-else-if="temprature <= 25"**>**
9. **<span>**凉爽**</span>**
10. **</template>**
11. **<template** v-else**>**
12. **<span>**炎热**</span>**
13. **</template>**
14. **</div>**
15. **<script>**
16. const vm = new Vue({
17. el : '#app',
18. data : {
19. msg : '条件渲染',
20. temprature : 10
21. }
22. })
23. **</script>**
另一个可以用来按条件显示一个元素的指令是 v-show。其用法基本一样:
**<div** id="app"**>**
2. **<h1>**{{msg}}**</h1>**
3. 温度:**<input** type="number" v-model="temprature"**><br>**
4. 天气:
5. **<span** v-show="temprature <= 10"**>**寒冷**</span>**
6. **<span** v-show="temprature > 10 && temprature <= 25"**>**凉爽**</span>**
7. **<span** v-show="temprature > 25"**>**炎热**</span>**
8. **</div>**
9. **<script>**
10. const vm = new Vue({
11. el : '#app',
12. data : {
13. msg : '条件渲染',
14. temprature : 10
15. }
16. })
17. **</script>**
不同之处在于 v-show 会在 DOM 渲染中保留该元素;v-show 仅切换了该元素上名为 display 的 CSS 属性。
v-show 不支持在 元素上使用,也不能和 v-else 搭配使用。
v-if 是“真实的”按条件渲染,因为它确保了在切换时,条件区块内的事件监听器和子组件都会被销毁与重建
v-if 也是惰性的:如果在初次渲染时条件值为 false,则不会做任何事。条件区块只有当条件首次变为 true 时才被渲染。
相比之下,v-show 简单许多,元素无论初始条件如何,始终会被渲染,只有 CSS display属性会被切换。
总的来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要频繁切换,则使用 v-show 较好;如果在运行时绑定条件很少改变,则 v-if 会更合适。
语法格式:v-for指令。该指令用在被遍历的标签上。
v-for="(element, index) in elements" :key="element.id"
或者
v-for="(element, index) of elements" :key="element.id"
**遍历数组**
2. **<div** id="app"**>**
3. **<h1>**{{msg}}**</h1>**
4. **<h2>**遍历数组**</h2>**
5. **<ul>**
6. **<li** v-for="(product, index) in products" :key="product.id"**>**
7. 商品名称:{{product.name}},单价:{{product.price}}元/千克,下标:{{index}}
8. **</li>**
9. **</ul>**
10. **</div>**
11. **<script>**
12. const vm = new Vue({
13. el : '#app',
14. data : {
15. msg : '列表渲染',
16. products : [
17. {id:'111',name:'西瓜',price:20},
18. {id:'222',name:'苹果',price:10},
19. {id:'333',name:'香蕉',price:30}
20. ]
21. }
22. })
23. **</script>**
运行效果:
*<div** id="app"**>**
3. **<h1>**{{msg}}**</h1>**
4. **<h2>**遍历对象**</h2>**
5. **<ul>**
6. **<li** v-for="(propertyValue, propertyName) of dog" :key="propertyName"**>**
7. {{propertyName}}:{{propertyValue}}
8. **</li>**
9. **</ul>**
10. **</div>**
11. **<script>**
12. const vm = new Vue({
13. el : '#app',
14. data : {
15. msg : '列表渲染',
16. dog : {
17. name : '拉布拉多',
18. age : 3,
19. gender : '雄性'
20. }
21. }
22. })
23. **</script>**
运行结果:
**<div** id="app"**>**
3. **<h1>**{{msg}}**</h1>**
4. **<h2>**遍历字符串**</h2>**
5. **<ul>**
6. **<li** v-for="char,index of str" :key="index"**>**
7. {{index}}:{{char}}
8. **</li>**
9. **</ul>**
10. **</div>**
11. **<script>**
12. const vm = new Vue({
13. el : '#app',
14. data : {
15. msg : '列表渲染',
16. str : '动力节点'
17. }
18. })
19. **</script>**
运行结果:
**<div** id="app"**>**
3. **<h1>**{{msg}}**</h1>**
4. **<h2>**遍历指定次数**</h2>**
5. **<ul>**
6. **<li** v-for="number,index of 10" :key="index"**>**
7. 下标:{{index}},数字:{{number}}
8. **</li>**
9. **</ul>**
10. **</div>**
11. **<script>**
12. const vm = new Vue({
13. el : '#app',
14. data : {
15. msg : '列表渲染'
16. }
17. })
18. **</script>**
运行结果:
所谓的虚拟dom就是内存当中的dom对象。vue为了提高渲染的效率,只有真正改变的dom元素才会重新渲染。
<!DOCTYPE html**>**
3. **<html** lang="en"**>**
4. **<head>**
5. **<meta** charset="UTF-8"**>**
6. **<title>**key的原理**</title>**
7. **<script** src="../js/vue.js"**></script>**
8. **</head>**
9. **<body>**
10. **<div** id="app"**>**
11. **<h1>**{{msg}}**</h1>**
12. **<button** @click="addFirst"**>**在数组第一个位置添加tom**</button>**
13. **<button** @click="addLast"**>**在数组最后位置添加vue**</button>**
14. **<table>**
15. **<tr>**
16. **<th>**序号**</th>**
17. **<th>**姓名**</th>**
18. **<th>**邮箱**</th>**
19. **<th>**选择**</th>**
20. **</tr>**
21. **<tr** v-for="(vip,index) of vips" :key="index"**>**
22. **<td>**{{index + 1}}**</td>**
23. **<td>**{{vip.name}}**</td>**
24. **<td>**{{vip.email}}**</td>**
25. **<td><input** type="checkbox"**></td>**
26. **</tr>**
27. **</table>**
28. **</div>**
29. **<script>**
30. const vm = new Vue({
31. el : '#app',
32. data : {
33. msg : 'key原理(虚拟dom与diff算法)',
34. vips : [
35. {id:'100',name:'jack',email:'jack@123.com'},
36. {id:'200',name:'lucy',email:'lucy@123.com'},
37. {id:'300',name:'james',email:'james@123.com'}
38. ]
39. },
40. methods : {
41. addFirst(){
42. this.vips.unshift({id:'400',name:'tom',email:'tom@123.com'})
43. },
44. addLast(){
45. this.vips.push({id:'500',name:'vue',email:'vue@123.com'})
46. }
47. }
48. })
49. **</script>**
50. **</body>**
51. **</html>**
运行效果:
全部选中:
添加tom:
可以看到错乱了。思考这是为什么?
运行和测试结果正常,没有出现错乱。为什么?
key存在于虚拟dom元素中,代表该虚拟dom元素的唯一标识(身份证号)。
新的虚拟dom和旧的虚拟dom比较时,先拿key进行比较:
当index作为key时:
当vip.id作为key时:
使用watch和computed分别进行实现:
<!DOCTYPE html**>**
2. **<html** lang="en"**>**
3. **<head>**
4. **<meta** charset="UTF-8"**>**
5. **<title>**列表过滤**</title>**
6. **<script** src="../js/vue.js"**></script>**
7. **<style>**
8. table,tr,th,td{
9. border: 1px solid blue;
10. }
11. **</style>**
12. **</head>**
13. **<body>**
14. **<div** id="app"**>**
15. **<h1>**{{msg}}**</h1>**
16. **<input** type="text" placeholder="请输入搜索关键词" v-model="keyword"**>**
17. **<table>**
18. **<tr>**
19. **<th>**序号**</th>**
20. **<th>**姓名**</th>**
21. **<th>**邮箱**</th>**
22. **</tr>**
23. **<tr** v-for="(vip,index) of filterVips" :key="vip.id"**>**
24. **<td>**{{index+1}}**</td>**
25. **<td>**{{vip.name}}**</td>**
26. **<td>**{{vip.email}}**</td>**
27. **</tr>**
28. **</table>**
29. **</div>**
30. **<script>**
31. const vm = new Vue({
32. el : '#app',
33. data : {
34. keyword : '',
35. msg : '列表过滤',
36. vips : [
37. {id:'100',name:'jack',email:'jack@123.com'},
38. {id:'200',name:'lucy',email:'lucy@123.com'},
39. {id:'300',name:'james',email:'james@123.com'}
40. ],
41. //filterVips : []
42. },
43. /* watch : {
44. keyword : {
45. immediate : true,
46. handler(newValue, oldValue){
47. this.filterVips = this.vips.filter((v) =**>** {
48. return v.name.indexOf(newValue) **>**= 0
49. })
50. }
51. }
52. }, */
53. computed : {
54. filterVips(){
55. return this.vips.filter((v) =**>** {
56. return v.name.indexOf(this.keyword) **>**= 0
57. })
58. }
59. }
60. })
61. **</script>**
62. **</body>**
63. **</html>**
<!DOCTYPE html**>**
2. **<html** lang="en"**>**
3. **<head>**
4. **<meta** charset="UTF-8"**>**
5. **<meta** http-equiv="X-UA-Compatible" content="IE=edge"**>**
6. **<meta** name="viewport" content="width=device-width, initial-scale=1.0"**>**
7. **<title>**列表排序**</title>**
8. **<script** src="../js/vue.js"**></script>**
9. **<style>**
10. table,tr,td,th{
11. border:1px solid black;
12. }
13. **</style>**
14. **</head>**
15. **<body>**
16. **<div** id="app"**>**
17. **<h1>**{{msg}}**</h1>**
18. **<input** type="text" placeholder="输入关键字搜索" v-model="keyword"**><br>**
19. **<button** @click="type = 1"**>**按照名字升序**</button><br>**
20. **<button** @click="type = 2"**>**按照名字降序**</button><br>**
21. **<button** @click="type = 0"**>**按照名字原始顺序**</button><br>**
22. **<table>**
23. **<tr>**
24. **<th>**序号**</th>**
25. **<th>**姓名**</th>**
26. **<th>**邮箱**</th>**
27. **<th>**操作**</th>**
28. **</tr>**
29. **<tr** v-for="(vip, index) in filterVips" :key="vip.id"**>**
30. **<td>**{{index+1}}**</td>**
31. **<td>**{{vip.name}}**</td>**
32. **<td>**{{vip.email}}**</td>**
33. **<td><input** type="checkbox"**></td>**
34. **</tr>**
35. **</table>**
36. **</div>**
37. **<script>**
38. const vm = new Vue({
39. el : '#app',
40. data : {
41. msg : '列表排序',
42. vips : [
43. {id:'100',name:'jack',email:'jack@123.com'},
44. {id:'200',name:'lucy',email:'lucy@123.com'},
45. {id:'300',name:'james',email:'james@123.com'},
46. {id:'400',name:'lilei',email:'lilei@123.com'},
47. ],
48. keyword : '',
49. type : 0
50. },
51. computed : {
52. filterVips(){
53. // 筛选
54. let arr = this.vips.filter((vip) =**>** {
55. return vip.name.indexOf(this.keyword) **>**= 0
56. })
57. // 根据排序类型进行排序
58. if(this.type){
59. arr.sort((v1, v2) =**>** {
60. console.log('@')
61. return this.type == 1 ? v1.name.localeCompare(v2.name) : v2.name.localeCompare(v1.name)
62. })
63. }
64. // 返回
65. return arr
66. }
67. }
68. })
69. **</script>**
70. **</body>**
71. </html>
<!DOCTYPE html**>**
2. **<html** lang="en"**>**
3. **<head>**
4. **<meta** charset="UTF-8"**>**
5. **<title>**收集表单数据**</title>**
6. **<script** src="../js/vue.js"**></script>**
7. **</head>**
8. **<body>**
9. **<div** id="app"**>**
10. **<h1>**{{msg}}**</h1>**
11. **<form** @submit.prevent="send"**>**
12. **<label** for="username"**>**用户名:**</label>**
13. **<input** id="username" type="text" v-model.trim="user.username"**><br><br>**
14. 密码:**<input** type="password" v-model="user.password"**><br><br>**
15. 年龄:**<input** type="number" v-model.number="user.age"**><br><br>**
16. 性别:
17. 男**<input** type="radio" name="gender" v-model="user.gender" value="1"**>**
18. 女**<input** type="radio" name="gender" v-model="user.gender" value="0"**><br><br>**
19. 爱好:
20. 运动**<input** type="checkbox" name="interest" value="sport" v-model="user.interest"**>**
21. 旅游**<input** type="checkbox" name="interest" value="travel" v-model="user.interest"**>**
22. 唱歌**<input** type="checkbox" name="interest" value="sing" v-model="user.interest"**><br><br>**
23. 学历:
24. **<select** v-model="user.grade"**>**
25. **<option** value=""**>**请选择学历**</option>**
26. **<option** value="zk"**>**专科**</option>**
27. **<option** value="bk"**>**本科**</option>**
28. **<option** value="ss"**>**硕士**</option>**
29. **</select><br><br>**
30. 简介:**<textarea** cols="30" rows="10" v-model.lazy="user.introduce"**></textarea><br><br>**
31. **<input** type="checkbox" v-model="user.isAgree"**>**阅读并接受协议**<br><br>**
32. **<button>**注册**</button>**
33. **</form>**
34. **</div>**
35. **<script>**
36. const vm = new Vue({
37. el : '#app',
38. data : {
39. msg : '收集表单数据',
40. user : {
41. username : '',
42. password : '',
43. age : '',
44. gender : '0',
45. interest : ['sport'],
46. grade : 'ss',
47. introduce : '',
48. isAgree : ''
49. }
50. },
51. methods : {
52. send(){
53. console.log(JSON.stringify(this.user))
54. }
55. }
56. })
57. **</script>**
58. **</body>**
59. **</html>**
页面展示效果:
运行结果:
过滤器filters适用于简单的逻辑处理,例如:对一些数据进行格式化显示。他的功能完全可以使用methods,computed来实现。过滤器可以进行全局配置,也可以进行局部配置:
过滤器可以用在两个地方:插值语法和v-bind指令中。
多个过滤器可以串联:{{msg | filterA | filterB | filterC}}
过滤器也可以接收额外的参数,但过滤器的第一个参数永远接收的都是前一个过滤器的返回值。
将内容填充到标签体当中,并且是以覆盖的形式填充,而且填充的内容中即使存在HTML标签也只是会当做一个普通的字符串处理,不会解析。功能等同于原生JS中的innerText。
将内容填充到标签体当中,并且是以覆盖的形式填充,而且将填充的内容当做HTML代码解析。功能等同于原生JS中的innerHTML。
v-html不要用到用户提交的内容上。可能会导致XSS攻击。XSS攻击通常指的是通过利用网页开发时留下的漏洞,通过巧妙的方法注入恶意指令代码到网页,使用户加载并执行攻击者恶意制造的网页程序。这些恶意网页程序通常是JavaScript。
例如:用户在留言中恶意植入以下信息:
其他用户上当了:如果点击了以上的留言,就会将cookie发送给恶意的服务器。
v-cloak配置css样式来解决胡子的闪现问题。
v-cloak指令使用在标签当中,当Vue实例接管之后会删除这个指令。
这是一段CSS样式:当前页面中所有带有v-cloak属性的标签都隐藏起来。
[v-cloak] {
display : none;
}
初次接触指令的时候已经学过了。只渲染一次。之后将被视为静态内容。
使用该指令可以提高编译速度。带有该指令的标签将不会被编译。可以在没有Vue语法规则的标签中使用可以提高效率。不要将它用在带有指令语法以及插值语法的标签中。
函数式:
directives : {
‘text-reverse’ : function(element, binding){
// element 是真实dom对象(可以通过 element instanceof HTMLElement 判断)
// binding 是绑定的对象
element.innerText = binding.value.split(‘’).reverse().join(‘’)
}
}
函数调用时机:
第一时机:模板初次解析时(元素与指令初次绑定)。
第二时机:模板重新解析时。
对象式:可以使用对象式完成更加细致的功能。
directives : {
‘bind-parent’ : {
// 元素与指令初次绑定时自动调用。
bind(element, binding){},
// 元素已经被插入页面后自动调用。
inserted(element, binding){},
// 模板重新解析时被自动调用。
update(element, binding){}
}
}
自定义指令的函数中的this是window。
以上是局部指令,全局指令怎么定义:
对象式:
Vue.directive(‘bind-parent’, {
bind(element, binding){},
inserted(element, binding){},
update(element, binding){}
})
函数式:
Vue.directive(‘text-reverse’, function(element, binding){})
修改data后,页面自动改变/刷新。这就是响应式。就像我们在使用excel的时候,修改一个单元格中的数据,其它单元格的数据会联动更新,这也是响应式。
数据劫持:Vue底层使用了Object.defineProperty,配置了setter方法,当去修改属性值时setter方法则被自动调用,setter方法中不仅修改了属性值,而且还做了其他的事情,例如:重新渲染页面。setter方法就像半路劫持一样,所以称为数据劫持。
push()
pop()
reverse()
splice()
shift()
unshift()
sort()
或者使用:
Vue.set(数组对象, ‘index’, 值)
vm.$set(数组对象, ‘index’, 值)
所谓的生命周期是指:一个事物从出生到最终的死亡,整个经历的过程叫做生命周期。
例如人的生命周期:
可以看到,在这个生命线上有很多不同的时间节点,在不同的时间节点上去做不同的事儿。
Vue的生命周期指的是:vm对象从创建到最终销毁的整个过程。
在生命线上的函数叫做钩子函数,这些函数是不需要程序员手动调用的,由Vue自动调用,程序员只需要按照自己的需求写上,到了那个时间点自动就会执行。
研究Vue的生命周期主要是研究:在不同的时刻Vue做了哪些不同的事儿。
例如:在vm被销毁之前,我需要将绑定到元素上的自定义事件全部解绑,那么这个解绑的代码就需要找一个地方写一下,写到哪里呢?你可以写到beforeDestroy()这个函数中,这个函数会被Vue自动调用,而且是在vm对象销毁前被自动调用。像这种在不同时刻被自动调用的函数称为钩子函数。每一个钩子函数都有对应的调用时间节点。
换句话说,研究Vue的生命周期主要研究的核心是:在哪个时刻调用了哪个钩子函数。
Vue的生命周期可以被划分为4个阶段:初始阶段、挂载阶段、更新阶段、销毁阶段。
每个阶段会调用两个钩子函数。两个钩子函数名的特点:beforeXxx()、xxxed()。
8个生命周期钩子函数分别是:
8个钩子函数写在哪里?直接写在Vue构造函数的options对象当中。
Vue官方的生命周期图:
翻译后的生命周期图:
做了这么几件事:
该阶段适合做什么?
beforeCreate:可以在此时加一些loading效果。
created:结束loading效果。也可以在此时发送一些网络请求,获取数据。也可以在这里添加定时器。
做了这么几件事:
该阶段适合做什么?
mounted:可以操作页面的DOM元素了。
做了这么几件事:
该阶段适合做什么?
beforeUpdate:适合在更新之前访问现有的 DOM,比如手动移除已添加的事件监听器。
updated:页面更新后,如果想对数据做统一处理,可以在这里完成。
做了这么几件事:
该阶段适合做什么?
beforeDestroy:适合做销毁前的准备工作,和人临终前写遗嘱类似。例如:可以在这里清除定时器。