Vue 的安装
在 vue 的官网中下载 vue.js
vue.js 一般使用在开发环境中, vue.min.js 一般使用在生产环境中
然后创建一个.html 文件, 在页面上运行
1 2 3 4 5 6 7 8 9 10 11
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>初始Vue</title> <script src="../js/vue.js"></script> </head> <body></body> </html>
|
在页面上打开 F12, 发现有两条提示
第一个提示, 需要我们下载一个 Vue 的拓展来开发
https://devtools.vuejs.org/guide/installation.html下载地址
下载完成之后会在右上角显示
第二个提示, 则是我们需要在生产环境中使用 vue.min.js
这代码编写的过程中, 我们可以关闭这个提示
Vue.config.productionTip=false
1 2 3 4
| <script src="../js/vue.js"></script> <script> Vue.config.productionTip = false; </script>
|
再回过头看控制台, 警告就消失了
初识 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 44 45 46 47 48 49 50
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>初始Vue</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h1>Hello, {{name}}, {{address}}</h1> </div> <script> Vue.config.productionTip = false; const x = new Vue({ el: "#root", data: { name: "尚硅谷", address: "北京", }, }); </script> </body> </html>
|
v-bind 可以简写 :
模板语法
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
|
<div id="root"> <a v-bind:href="school.url" x="hello">去尚硅谷</a> <a :href="school.url.toUpperCase()" x="hello">去尚硅谷</a> </div> <script> new Vue({ el: "#root", data: { name: "jack", school: { name: "尚硅谷", url: "http://www.atguigu.com", }, }, }); </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
|
<div id="root">
单向数据绑定: <input type="text" :value="name" /><br /> 双向数据绑定: <input type="text" v-model="name" />
</div> <script> new Vue({ el: "#root", data: { name: "尚硅谷", }, }); </script>
|
el 与 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
|
<div id="root"> <h1>你好, {{name}}</h1> </div> <script> const v = new Vue({ data: { name: "尚硅谷", }, }); console.log(v); v.$mount("#root"); </script>
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <script>
new Vue({ el: "#root", data: function () { return { name: "尚硅谷", }; }, }); </script>
|
理解 MVVM
编写代码片段
复制如下代码保存
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| { "Print to console": { "scope": "html, javascript, typescript", "prefix": "v1", "body": [ "new Vue({", " el: '#root',", " data: {", " $1", " }", "})" ], "description": "生成一个Vue实例" } }
|
在页面中只需要输入 v1, 就可以快速创建一个 Vue 实例, 非常的方便
MVVM 模型
- M:模型(Model) :对应 data 中的数据
- V:视图(View) :模板
- VM:视图模型(ViewModel) : Vue 实例对象
MVVM 模型就是把一些乱七八糟的数据和一堆乱七八糟的 DOM 结构在中间使用 VM 连接
回顾 Object.defineProperty 方法
enumerable
此时这种写法是可以遍历 person 的属性的
从上可以观察到 Object.defineProperty 定义的属性, 默认是不能被遍历的
只有设置了 enumerable: true 才能被遍历
writable
从上面可以观察到 Object.defineProperty 定义的属性, 默认是不能修改的
只有设置了 writable: true, 才能被修改
从上面可以观察到 Object.defineProperty 定义的属性, 默认是不能删除的
只有设置了 configurable: true 才能被删除
数据代理
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
<script> let obj = { x: 100 }; let obj2 = { y: 200 }; Object.defineProperty(obj2, "x", { get() { return obj.x; }, set(value) { obj.x = value; }, }); </script>
|
修改了 obj2.x 的值, obj.x 值也随之发生了变化
vm 中使用了 Object.defineProperty 代理了_data 的属性
_data.name 中有 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
|
<div id="root"> <h2>欢迎来到{{name}}学习</h2> <button v-on:click="showInfo1">点我提示信息</button> <button @click="showInfo2(66, $event)">点我提示信息</button> </div> <script> const vm = new Vue({ el: "#root", data: { name: "尚硅谷", }, methods: { showInfo1(event) { console.log(event.target.innerText); console.log(this); }, showInfo2(number, a) { console.log(a); console.log(number); alert("同学您好!!"); }, }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>事件修饰符</title> <script src="../js/vue.js"></script> <style> * { margin-top: 20px; }
.demo1 { height: 50px; background-color: skyblue; }
.box1 { padding: 5px; background-color: skyblue; }
.box2 { padding: 5px; background-color: orange; }
.list { width: 200px; height: 200px; background-color: peru; overflow: auto; }
li { height: 100px; } </style> </head>
<body>
<div id="root"> <h2>欢迎来到{{name}}学习</h2> <a href="http://www.atguigu.com" @click.prevent="showInfo" >点我提示信息</a >
<div class="demo1" @click="showInfo"> <button @click.stop="showInfo">点我提示信息</button> <a href="http://www.atguigu.com" @click.prevent.stop="showInfo" >点我提示信息</a > </div>
<button @click.once="showInfo">点我提示信息</button>
<div class="box1" @click.capture="showMsg(1)"> div1 <div class="box2" @click="showMsg(2)"> div2 </div> </div>
<div class="demo1" @click.self="showInfo"> <button @click="showInfo">点我提示信息</button> </div>
<ul @wheel.passive="demo" class="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul> <ul @scroll="demo" class="list"> <li>1</li> <li>2</li> <li>3</li> <li>4</li> </ul>
</div> <script> new Vue({ el: "#root", data: { name: "尚硅谷", }, methods: { showInfo(event) { alert("同学你好! "); }, showMsg(msg) { console.log(msg); }, demo() { for (let i = 0; i < 100000; i++) { console.log("#"); } }, }, }); </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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>键盘事件</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>欢迎来到{{name}}学习</h2>
<input type="text" placeholder="按下回车提示输入" @keydown.ctrl.y="showInfo"> </div> <script> Vue.config.productionTip = false Vue.config.keyCodes.huiche = 13 new Vue({ el: '#root', data: { name: '尚硅谷' }, methods: { showInfo(e) { console.log(e.key, e.keyCode); } } }) </script>
</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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>姓名案例_插值语法实现</title> <script src="../js/vue.js"></script> </head> <body> <div id="root"> 姓: <input type="text" v-model="firstName" /> <br /><br /> 名: <input type="text" v-model="lastName" /> <br /><br /> 全名: <span>{{firstName}}-{{lastName}}</span> 全名: <span>{{firstName.slice(0, 3)}}-{{lastName}}</span> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { firstName: "张", lastName: "三", }, methods: {}, }); </script> </body> </html>
|
姓名案例_methods 实现
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>姓名案例_methods实现</title> <script src="../js/vue.js"></script> </head> <body> <div id="root"> 姓: <input type="text" v-model="firstName" /> <br /><br /> 名: <input type="text" v-model="lastName" /> <br /><br /> 全名: <span>{{fullName()}}</span> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { firstName: "张", lastName: "三", }, methods: { fullName() { return this.firstName + "-" + this.lastName; }, }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>姓名案例_计算属性</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> 姓: <input type="text" v-model="firstName" /> <br /><br /> 名: <input type="text" v-model="lastName" /> <br /><br /> 全名: <span>{{fullName}}</span> <br /><br /> 全名: <span>{{fullName}}</span> <br /><br /> 全名: <span>{{fullName}}</span> <br /><br /> 全名: <span>{{fullName}}</span> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { firstName: "张", lastName: "三", }, methods: {}, computed: { fullName: { get() { console.log("get被调用了"); return this.firstName + "-" + this.lastName; }, set(value) { console.log("set", value); const arr = value.split("-"); console.log(arr[0]); console.log(arr[1]); this.firstName = arr[0]; this.lastName = arr[1]; }, }, }, }); </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 48 49 50 51 52 53 54 55 56 57 58 59 60
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>姓名案例_计算属性简写</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> 姓: <input type="text" v-model="firstName" /> <br /><br /> 名: <input type="text" v-model="lastName" /> <br /><br /> 全名: <span>{{fullName}}</span> <br /><br /> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { firstName: "张", lastName: "三", }, methods: {}, computed: {
fullName() { console.log("get被调用了"); return this.firstName + "-" + this.lastName; }, }, }); </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 48
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>天气案例</title> <script src="../js/vue.js"></script> </head> <body> <div id="root"> <h2>今天天气很{{info}}</h2> <button @click="isHot = !isHot">切换天气</button> </div> <script> Vue.config.productionTip = false;
new Vue({ el: "#root", data: { isHot: true, }, methods: { changeWeather() { this.isHot = !this.isHot; }, }, computed: { info() { return this.isHot ? "炎热" : "凉爽"; }, }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>天气案例_监视属性</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> </div> <script> Vue.config.productionTip = false;
const vm = new Vue({ el: "#root", data: { isHot: true, }, methods: { changeWeather() { this.isHot = !this.isHot; }, }, computed: { info() { return this.isHot ? "炎热" : "凉爽"; }, }
});
vm.$watch("isHot", { immediate: true, handler(newValue, oldValue) { console.log("isHot被修改了", newValue, oldValue); }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>天气案例_深度监视</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> <hr /> <h3>a的值是: {{numbers.a}}</h3> <button @click="numbers.a++">点我a++</button> <h3>b的值是: {{numbers.b}}</h3> <button @click="numbers.b++">点我b++</button>
<button @click="numbers = {a:666,b:999}">点我替换numbers</button> </div> <script> Vue.config.productionTip = false;
const vm = new Vue({ el: "#root", data: { isHot: true, numbers: { a: 1, b: 1, }, }, methods: { changeWeather() { this.isHot = !this.isHot; }, }, computed: { info() { return this.isHot ? "炎热" : "凉爽"; }, }, watch: { isHot: { handler(newValue, oldValue) { console.log("isHot被修改了", newValue, oldValue); }, },
numbers: { deep: true, handler() { console.log("numbers被修改了"); }, }, }, }); </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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>天气案例_监视属性_简写</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h2>今天天气很{{info}}</h2> <button @click="changeWeather">切换天气</button> </div> <script> Vue.config.productionTip = false;
const vm = new Vue({ el: "#root", data: { isHot: true, }, methods: { changeWeather() { this.isHot = !this.isHot; }, }, computed: { info() { return this.isHot ? "炎热" : "凉爽"; }, }, watch: {
}, });
vm.$watch("isHot", function (newValue, oldValue) { console.log("isHot被修改了", newValue, oldValue); }); </script> </body> </html>
|
两个重要的小原则: 1.所被 Vue 管理的函数,最好写成普通函数,这样 this 的指向才是 vm 或 组件实例对象。 2.所有不被 Vue 所管理的函数(定时器的回调函数、ajax 的回调函数等、Promise 的回调函数),最好写成箭头函数,这样 this 的指向才是 vm 或 组件实例对象。
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>姓名案例_watch实现</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> 姓: <input type="text" v-model="firstName" /> <br /><br /> 名: <input type="text" v-model="lastName" /> <br /><br /> 全名: <span>{{fullName}}</span> <br /><br /> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { firstName: "张", lastName: "三", fullName: "张-三", }, methods: {}, watch: { firstName(val) { setTimeout(() => { this.fullName = val + "-" + this.lastName; }, 1000); }, lastName(val) { this.fullName = this.firstName + "-" + val; }, }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>绑定样式</title> <style> .basic { width: 400px; height: 100px; border: 1px solid black; }
.happy { border: 4px solid red; ; background-color: rgba(255, 255, 0, 0.644); background: linear-gradient(30deg, yellow, pink, orange, yellow); }
.sad { border: 4px dashed rgb(2, 197, 2); background-color: gray; }
.normal { background-color: skyblue; }
.atguigu1 { background-color: yellowgreen; }
.atguigu2 { font-size: 30px; text-shadow: 2px 2px 10px red; }
.atguigu3 { border-radius: 20px; } </style> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <div class="basic" :class="mood" @click="changeMood">{{name}}</div> <br /><br />
<div class="basic" :class="classArr">{{name}}</div> <br /><br />
<div class="basic" :class="classObj">{{name}}</div> <br /><br /> <div class="basic" :class="{atguigu1: true, atguigu2: true}"> {{name}} </div> <br /><br />
<div class="basic" :style="{fontSize: fsize+'px'}">{{name}}</div> <br /><br />
<div class="basic" :style="styleObj">{{name}}</div> <br /><br />
<div class="basic" :style="[styleObj, styleObj2]">{{name}}</div> <br /><br /> <div class="basic" :style="styleArr">{{name}}</div> <br /><br /> </div>
<script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { name: "尚硅谷", mood: "normal", classArr: ["atguigu1", "atguigu2", "atguigu3"], classObj: { atguigu1: true, atguigu2: true, }, fsize: 40, styleObj: { fontSize: "40px", color: "red", }, styleObj2: { backgroundColor: "orange", }, styleArr: [ { fontSize: "40px", color: "blue", }, { backgroundColor: "gray", }, ], }, methods: { changeMood() {
const arr = ["happy", "sad", "normal"]; const index = Math.floor(Math.random() * 3); this.mood = arr[index]; }, }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>条件渲染</title> <script src="../js/vue.js"></script> </head> <body>
<div id="root"> <h2>当前的n值是:{{n}}</h2> <button @click="n++">点我n+1</button>
<template v-if="n === 1"> <h2>你好</h2> <h2>尚硅谷</h2> <h2>北京</h2> </template>
</div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { name: "尚硅谷", a: false, n: 0, }, methods: {}, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>基本列表</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>人员列表(遍历数组)</h2> <ul> <li v-for="(person,index) in persons" :key="index"> {{index}} - {{person.name}} - {{person.id}} </li> </ul>
<h2>汽车信息(遍历对象)</h2> <ul> <li v-for="(value,key) in car" ::key="key"> {{key}} -- {{value}} </li> </ul> <h2>遍历字符串(用得少)</h2> <ul> <li v-for="(char,index) in str" ::key="index"> {{index}} -- {{char}} </li> </ul> <h2>遍历指定次数(用得少)</h2> <ul> <li v-for="(number,index) in 5" ::key="index"> {{number}} -- {{index}} </li> </ul> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { persons: [ { id: "001", name: "张三", age: 18 }, { id: "002", name: "李四", age: 19 }, { id: "003", name: "王五", age: 20 }, ], car: { name: "奥迪A8", price: "70万", color: "黑色", }, str: "hello", }, methods: {}, }); </script> </body> </html>
|
key 的原理
开发中如何选择 key?: 1.最好使用每条数据的唯一标识作为 key, 比如 id、手机号、身份证号、学号等唯一值。 2.如果不存在对数据的逆序添加、逆序删除等破坏顺序操作,仅用于渲染列表用于展示,使用 index 作为 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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>key的原理</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>人员列表(遍历数组)</h2> <button @click="add">添加一个老刘</button> <ul> <li v-for="(person,index) in persons" :key="person.id"> {{person.name}} - {{person.id}} <input type="text" /> </li> </ul> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { persons: [ { id: "001", name: "张三", age: 18 }, { id: "002", name: "李四", age: 19 }, { id: "003", name: "王五", age: 20 }, ], }, methods: { add() { this.persons.unshift({ id: "004", name: "老刘", age: 40 }); }, }, }); </script> </body> </html>
|
监视数据的原理
监测数据的原理就是监测 set 被调用监测的, 一旦 set 被调用, 就会被监测到
因为 vm.student === vm._data.student , 所以上面的代码可以简写
注意, 这种方式只能给 vm 中的某一个对象追加属性, 不能给 data 追加一个属性
只用着了这七个方法, vue 会发现修改了数组
下面这种方法, 修改数组, vue 也会发现, 然后渲染页面
数组里面不能够使用 getset 来监视, 尽管修改了数组索引的值, 但是页面并没有发生改变
使用了 push 的方式修改了数组, 但是页面发生了变化
使用了这七个方法中的修改了数组, 都是响应式的, 页面都会有反应的
列表渲染
基本列表
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>基本列表</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>人员列表(遍历数组)</h2> <ul> <li v-for="(person,index) in persons" :key="index"> {{index}} - {{person.name}} - {{person.id}} </li> </ul>
<h2>汽车信息(遍历对象)</h2> <ul> <li v-for="(value,key) in car" ::key="key"> {{key}} -- {{value}} </li> </ul> <h2>遍历字符串(用得少)</h2> <ul> <li v-for="(char,index) in str" ::key="index"> {{index}} -- {{char}} </li> </ul> <h2>遍历指定次数(用得少)</h2> <ul> <li v-for="(number,index) in 5" ::key="index"> {{number}} -- {{index}} </li> </ul> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { persons: [ { id: "001", name: "张三", age: 18 }, { id: "002", name: "李四", age: 19 }, { id: "003", name: "王五", age: 20 }, ], car: { name: "奥迪A8", price: "70万", color: "黑色", }, str: "hello", }, methods: {}, }); </script> </body> </html>
|
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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>key的原理</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>人员列表(遍历数组)</h2> <button @click="add">添加一个老刘</button> <ul> <li v-for="(person,index) in persons" :key="person.id"> {{person.name}} - {{person.id}} <input type="text" /> </li> </ul> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { persons: [ { id: "001", name: "张三", age: 18 }, { id: "002", name: "李四", age: 19 }, { id: "003", name: "王五", age: 20 }, ], }, methods: { add() { this.persons.unshift({ id: "004", name: "老刘", age: 40 }); }, }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>列表过滤</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h2>人员列表</h2> <input type="text" placeholder="请输入名字" v-model="keyWord" /> <ul> <li v-for="(person,index) in filPersons" :key="index"> {{person.name}} - {{person.id}} - {{person.sex}} </li> </ul> </div> <script> Vue.config.productionTip = false;
const vm = new Vue({ el: "#root", data: { keyWord: "", persons: [ { id: "001", name: "马冬梅", age: 18, sex: "女" }, { id: "002", name: "周冬雨", age: 19, sex: "女" }, { id: "003", name: "周杰伦", age: 20, sex: "男" }, { id: "004", name: "温兆伦", age: 20, sex: "男" }, ], }, computed: { filPersons() { return this.persons.filter((p) => { return p.name.indexOf(this.keyWord) !== -1; }); }, }, }); </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 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>列表排序</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h2>人员列表</h2> <input type="text" placeholder="请输入名字" v-model="keyWord" /> <button @click="sortType = 2">年龄升序</button> <button @click="sortType = 1">年龄降序</button> <button @click="sortType = 0">原顺序</button> <ul> <li v-for="(person,index) in filPersons" :key="person.id"> {{person.name}} - {{person.age}} - {{person.sex}} <input type="text" /> </li> </ul> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { keyWord: "", persons: [ { id: "001", name: "马冬梅", age: 33, sex: "女" }, { id: "002", name: "周冬雨", age: 30, sex: "女" }, { id: "003", name: "周杰伦", age: 18, sex: "男" }, { id: "004", name: "温兆伦", age: 20, sex: "男" }, ], sortType: 0, }, computed: { filPersons() { const arr = this.persons.filter((p) => { return p.name.indexOf(this.keyWord) !== -1; });
if (this.sortType) { arr.sort((p1, p2) => { return this.sortType == 1 ? p2.age - p1.age : p1.age - p2.age; }); }
return arr; }, }, }); </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 48 49 50 51 52 53 54 55 56
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>列表排序</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h2>人员列表</h2> <button @click="updateMei">点我修改马冬梅</button> <ul> <li v-for="(person,index) in persons" :key="person.id"> {{person.name}} - {{person.age}} - {{person.sex}} </li> </ul> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { persons: [ { id: "001", name: "马冬梅", age: 33, sex: "女" }, { id: "002", name: "周冬雨", age: 30, sex: "女" }, { id: "003", name: "周杰伦", age: 18, sex: "男" }, { id: "004", name: "温兆伦", age: 20, sex: "男" }, ], }, methods: { updateMei() { this.persons[0] = { id: "001", name: "马老师", age: 50, sex: "男" }; }, }, }); </script> </body> </html>
|
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vue检测数据改变的原理</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h2>学校名称: {{name}}</h2> <h2>学校地址: {{address}}</h2> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { name: "尚硅谷", address: "北京", }, methods: {}, }); </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" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>模拟一个数据检测</title> </head> <body> <script> let data = { name: "尚硅谷", address: "北京", };
const obs = new Observer(data); console.log(obs);
let vm = {}; vm._data = data = obs;
function Observer(obj) { const keys = Object.keys(obj); console.log(keys); keys.forEach((k) => { Object.defineProperty(this, k, { get() { return obj[k]; }, set(val) { console.log( `${k}被改了被改了, 我要去解析模板, 生成虚拟DOM.....我要开始忙了` ); obj[k] = val; }, }); }); } </script> </body> </html>
|
Vue.set 的使用
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vue检测数据改变的原理</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h2>学校名称: {{school.name}}</h2> <h2>学校地址: {{school.address}}</h2> <h2>校长: {{school.leader}}</h2> <hr /> <button @click="addSex">点我添加一个性别: 性别为男</button> <h2>姓名: {{student.name}}</h2> <h2>年龄: {{student.age.rAge}}, {{student.age.sAge}}</h2> <h2 v-if="student.sex">性别: {{student.sex}}</h2> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { school: { name: "尚硅谷", address: "北京", }, student: { name: "tom", age: { rAge: 40, sAge: 29, }, friends: [ { name: "jerry", age: 35 }, { name: "tony", age: 36 }, ], }, }, methods: { addSex() { this.$set(this.student, "sex", "男"); }, }, }); </script> </body> </html>
|
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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>Vue检测数据改变的原理_数组</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> <h2>学校名称: {{school.name}}</h2> <h2>学校地址: {{school.address}}</h2> <h2>校长: {{school.leader}}</h2> <hr /> <button @click="addSex">点我添加一个性别: 性别为男</button> <h2>姓名: {{student.name}}</h2> <h2>年龄: {{student.age.rAge}}, {{student.age.sAge}}</h2> <h2 v-if="student.sex">性别: {{student.sex}}</h2>
<h2>爱好</h2> <ul> <li v-for="(h,index) in student.hobby" :key="index"> {{h}} </li> </ul> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { school: { name: "尚硅谷", address: "北京", }, student: { name: "tom", age: { rAge: 40, sAge: 29, }, hobby: ["抽烟", "喝酒", "烫头"], friends: [ { name: "jerry", age: 35 }, { name: "tony", age: 36 }, ], }, }, methods: { addSex() { this.$set(this.student, "sex", "男"); }, }, }); </script> </body> </html>
|
总结 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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>总结Vue数据监测</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>学生信息</h2>
<button @click="student.age++">年龄+1岁</button>
<button @click="addSex">添加性别属性,默认值:男</button>
<button @click="updateSex">修改性别</button>
<button @click="addFriends">在列表首位添加一个朋友</button>
<button @click="updateFriends">修改第一个朋友的名字为:张三</button>
<button @click="addHobby">添加一个爱好</button>
<button @click="updateHobby">修改第一个爱好为:开车</button>
<button @click="deleteHobby">过滤掉爱好中的抽烟</button>
<h2>姓名: {{student.name}}</h2> <h2>年龄: {{student.age}}</h2> <h2 v-if="student.sex">性别: {{student.sex}}</h2> <h2>爱好</h2> <ul> <li v-for="(h,index) in student.hobby" :key="index"> {{h}} </li> </ul> <h2>朋友们</h2> <ul> <li v-for="(f,index) in student.friends" :key="index"> {{f.name}} -- {{f.age}} </li> </ul> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { student: { name: "tom", age: 18, hobby: ["抽烟", "喝酒", "烫头"], friends: [ { name: "jerry", age: 35 }, { name: "tony", age: 36 }, ], }, }, methods: { addSex() { this.$set(this.student, "sex", "男"); }, updateSex() { this.student.sex = "未知";
}, addFriends() { this.student.friends.unshift({ name: "肉豆蔻", age: 18 }); }, updateFriends() { this.student.friends[0].name = "张三"; }, addHobby() { this.student.hobby.push("学习"); }, updateHobby() { this.student.hobby.splice(0, 1, "开车"); }, deleteHobby() {
this.student.hobby = this.student.hobby.filter((h) => { return h !== "抽烟"; }); }, }, });
</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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>收集表单数据</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <form @submit.prevent="demo"> 账号: <input type="text" v-model.trim="userInfo.account" autofocus /><br /><br /> 密码: <input type="password" v-model="userInfo.password" /><br /><br /> 年龄: <input type="number" v-model.number="userInfo.age" /><br /><br /> 性别: 男<input type="radio" name="sex" value="male" v-model="userInfo.sex" /> 女<input type="radio" name="sex" value="female" v-model="userInfo.sex" /><br /><br /> 爱好: 抽烟<input type="checkbox" name="hobby" value="抽烟" v-model="userInfo.hobby" /> 喝酒<input type="checkbox" name="hobby" value="喝酒" v-model="userInfo.hobby" /> 烫头<input type="checkbox" name="hobby" value="烫头" v-model="userInfo.hobby" /><br /><br /> 所属校区 <select v-model="userInfo.city"> <option value="">请选择校区</option> <option value="beijing">北京</option> <option value="shanghai">上海</option> <option value="shenzhen">深圳</option> <option value="wuhan">武汉</option> </select> <br /><br /> 其他信息: <textarea v-model.lazy="userInfo.other"></textarea> <br /><br /> <input type="checkbox" v-model="userInfo.agree" /> 阅读并接受<a href="http://www.atguigu.com">《用户协议》</a> <br /><br /> <button>提交</button> </form> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { userInfo: { account: "", password: "", age: 18, sex: "female", hobby: [], city: "beijing", other: "", agree: "", }, }, methods: { demo() { console.log(JSON.stringify(this.userInfo)); }, }, }); </script> </body> </html>
|
过滤器
在https://www.bootcdn.cn/网站中找到 dayjs.min.js 并且引入
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
| <!DOCTYPE html> <html lang="en">
<head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>过滤器</title> <script src="../js/vue.js"></script> <script src="../js/dayjs.min.js"></script> </head>
<body>
<div id="root"> <h2>显示格式化后的时间</h2> <h3>现在是: {{fmtTime}}</h3> <h3>现在是: {{getFmtTime()}}</h3> <h3>现在是: {{time | timeFormater}}</h3> <h3>现在是: {{time | timeFormater('YYYY_MM_DD')}}</h3> <h3>现在是: {{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3> <h3 :x="msg | mySlice">尚硅谷</h3></h3> </div> <div id="root2"> <h2>{{name | mySlice}}</h2> </div> <script> Vue.config.productionTip = false Vue.filter('mySlice', function(value) { return value.slice(0, 4); })
const vm = new Vue({ el: '#root', data: { time: Date.now(), msg: '你好,尚硅谷' }, methods: { getFmtTime() { return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss'); } }, computed: { fmtTime() { return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss'); } }, filters: { timeFormater(value, str='YYYY-MM-DD HH:mm:ss') { return dayjs(value).format(str); }, } })
new Vue({ el: '#root2', data: { name: 'hello, atguigu' }, methods: { } }) </script> </body>
</html>
|
内置指令
v-text
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>v-text指令</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <div>你好, {{name}}</div> <div v-text="name"></div> <div v-text="str"></div> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { name: "尚硅谷", str: "<h2>你好啊!</h2>", }, methods: {}, }); </script> </body> </html>
|
v-html
v-html 有安全性问题!!!!
(1).在网站上动态渲染任意 HTML 是非常危险的,容易导致 XSS 攻击。
(2).一定要在可信的内容上使用 v-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 48 49 50 51
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>v-html指令</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <div>你好, {{name}}</div> <div v-html="str"></div> <div v-html="str2"></div> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { name: "尚硅谷", str: "<h2>你好啊!</h2>", str2: '<a href=javascript:location.href="http://www.baidu.com?"+document.cookie>点我有好看的</a>', }, methods: {}, }); </script> </body> </html>
|
v-cloak
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>v-cloak指令</title> <style> [v-cloak] { display: none; } </style> </head>
<body>
<div id="root"> <h2 v-cloak>{{name}}</h2> </div> <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { name: "尚硅谷", }, methods: {}, }); </script> </body> </html>
|
v-once
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>v-once指令</title> <script src="../js/vue.js"></script> </head> <body>
<div id="root"> <h2 v-once>初始的时候n = {{n}}</h2> <h2>当前的n = {{n}}</h2></h2> <button @click="n++">点我n+1</button> </div> <script> Vue.config.productionTip = false new Vue({ el: '#root', data: { n: 1 }, methods: { } }) </script> </body> </html>
|
v-pre
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>v-pre_指令</title> <script src="../js/vue.js"></script> </head> <body>
<div id="root"> <h2 v-pre>Vue其实很简单</h2> <h2>当前的n = {{n}}</h2></h2> <button @click="n++">点我n+1</button> </div> <script> Vue.config.productionTip = false new Vue({ el: '#root', data: { n: 1 }, methods: { } }) </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>自定义指令</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2>{{name}}</h2> <h2>当前的n值是: <span v-text="n"></span></h2> <h2>放大10倍后的值是: <span v-big="n"></span></h2> <h2>放大10倍后的值是: <span v-big-number="n"></span></h2> <button @click="n++">点我n+1</button> <hr /> <input type="text" v-fbind:value="n" /> </div>
<div id="root2"> <input type="text" v-fbind:value="x" /> </div> <script> Vue.config.productionTip = false; Vue.directive("fbind", { bind(element, binding) { element.value = binding.value; }, inserted(element, binding) { element.focus(); }, update(element, binding) { element.value = binding.value; element.focus(); }, });
const vm = new Vue({ el: "#root", data: { n: 1, name: "尚硅谷", }, methods: {}, directives: { big(element, binding) { console.log("big", this); element.innerText = binding.value * 10; }, "big-number"(element, binding) { element.innerText = binding.value * 10; }, }, });
new Vue({ el: "#root2", data: { x: 1, }, methods: {}, }); </script> </body> </html>
|
回顾一个 DOM 操作
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>回顾一个DOM操作</title> <style> .demo { background-color: orange; } </style> </head> <body> <button id="btn">点我创建一个输入框</button> <script> const btn = document.getElementById("btn"); btn.onclick = () => { const input = document.createElement("input");
input.className = "demo"; input.value = 99; input.onclick = () => { alert(1); }; document.body.appendChild(input);
input.focus();
input.parentElement.style.backgroundColor = "skyblue"; console.log(input.parentElement); }; </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 48 49 50 51 52 53 54 55 56
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>引出生命周期</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2 :style="{opacity: opacity}">欢迎学习Vue</h2> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { opacity: 1, }, methods: {}, mounted() { setInterval(() => { this.opacity -= 0.01; if (this.opacity <= 0) { this.opacity = 1; } }, 16); }, });
</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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>分析生命周期</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root" :x="n"> <h2>当前的n值是: {{n}}</h2> <button @click="add">点我n+1</button> <button @click="bye">点我销毁</button> </div> <script> Vue.config.productionTip = false; new Vue({ el: "#root", data: { n: 1, }, methods: { add() { console.log("add"); this.n++; }, bye() {
console.log("bye"); this.$destroy(); }, }, watch: { n() { console.log("n变了"); }, }, beforeCreate() { console.log("beforeCreate"); }, created() { console.log("created"); }, beforeMount() { console.log("beforeMount"); }, mounted() { console.log("mounted"); }, beforeUpdate() { console.log("beforeUpdate"); },
updated() { console.log("updated"); }, beforeDestroy() { console.log("beforeDestroy"); this.add(); }, destroyed() { console.log("destroyed"); }, }); </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 48 49 50 51 52 53 54
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>总结生命周期</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <h2 :style="{opacity: opacity}">欢迎学习Vue</h2> <button @click="stop">点我停止变化</button> </div> <script> Vue.config.productionTip = false; const vm = new Vue({ el: "#root", data: { opacity: 1, }, methods: { stop() { this.$destroy(); }, }, mounted() { this.timer = setInterval(() => { console.log("setInterval"); this.opacity -= 0.01; if (this.opacity <= 0) { this.opacity = 1; } }, 16); }, beforeDestroy() { console.log("vm即将驾鹤西游了"); clearInterval(this.timer); }, }); </script> </body> </html>
|
组件的概念
组件的定义: 实现应用中局部功能代码和资源的集合
非单文件组件
组件就是一块砖, 哪里需要哪里搬
非单文件组件:
一个文件中包含有 n 个组件
单文件组件的嵌套组件:
一个文件中只包含有 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 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>基本使用</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <hello></hello> <hr /> <h1>{{msg}}</h1> <hr /> <student></student> <hr /> <school></school> </div> <div id="root2"> <hello></hello> </div> <script> Vue.config.productionTip = false;
const student = Vue.extend({ template: ` <div> <h2>学生姓名: {{studentName}}</h2> <h2>学生年龄: {{age}}</h2> </div> `, data() { return { studentName: "张三", age: 18, }; }, });
const school = Vue.extend({ template: ` <div> <h2>学校名称: {{schoolName}}</h2> <h2>学校地址: {{address}}</h2> <button @click="showName">点我提示学校名</button> </div> `,
data() { return { schoolName: "尚硅谷", address: "北京昌平", }; }, methods: { showName() { alert(this.schoolName); }, }, });
const hello = Vue.extend({ template: ` <div> <h2>你好啊! {{name}}</h2> </div> `, data() { return { name: "Tom", }; }, });
Vue.component("hello", hello); new Vue({ el: "#root", data: { msg: "你好啊!", }, methods: {}, components: { school, student, }, });
new Vue({ el: "#root2", }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>几个注意点</title> <script src="../js/vue.js"></script> </head> <body>
<div id="root"> <h1>{{msg}}</h1> <school></school> </div> <script> Vue.config.productionTip = false; const s = Vue.extend({ template: ` <div> <h2>学校名称: {{name}}</h2> <h2>学校地址: {{address}}</h2> </div> `, data() { return { name: "尚硅谷", address: "北京", }; }, }); new Vue({ el: "#root", data: { msg: "欢迎学习Vue!", }, methods: {}, components: { school: s, }, }); </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 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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>组件的嵌套</title> <script src="../js/vue.js"></script> </head>
<body> <div id="root"> </div> <script> Vue.config.productionTip = false; //定义student组件
const student = Vue.extend({ template: ` <div> <h2>学生姓名: {{name}}</h2> <h2>学生年龄: {{age}}</h2> </div> `, name: "student", data() { return { name: "肉豆蔻", age: 18, }; }, }); //定义school组件
const school = Vue.extend({ template: ` <div> <h2>学校名称: {{name}}</h2> <h2>学校地址: {{address}}</h2> <student></student> </div> `, name: "school", data() { return { name: "尚硅谷", address: "北京", }; }, //注册组件(局部) components: { student: student, }, }); //定义hello组件 const hello = Vue.extend({ template: ` <h1>{{msg}}</h1> `, data() { return { msg: "欢迎来到尚硅谷学习!", }; }, }); //定义app组件 const app = Vue.extend({ template: ` <div> <hello></hello> <school></school> </div> `, components: { school, hello, }, }); //创建vm
new Vue({ template: ` <app></app> `, el: "#root", data: {}, methods: {}, //注册组件(局部) components: { app, }, }); </script> </body> </html>
|
VueComponent
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
| <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>VueComponent</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <school></school> <hello></hello> </div> <script> Vue.config.productionTip = false; const school = Vue.extend({ template: ` <div> <h2>学校名称:{{name}}</h2> <h2>学校地址:{{address}}</h2> <button @click="showName">点我提示学校名</button> </div> `, data() { return { name: "尚硅谷", address: "北京", }; }, methods: { showName() { console.log("showName", this); }, }, });
const test = Vue.extend({ template: `<span>atguigu</span>`, });
const hello = Vue.extend({ template: ` <div> <h2>{{msg}}</h2> <test></test> </div> `, data() { return { msg: "你好啊!", }; }, components: { test, }, });
new Vue({ el: "#root", data: {}, methods: {}, components: { school, hello, }, }); </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 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" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1.0" /> <title>一个重要的内置关系</title> <script src="../js/vue.js"></script> </head>
<body>
<div id="root"> <school></school> </div> <script> Vue.config.productionTip = false; Vue.prototype.x = 99;
const school = Vue.extend({ template: ` <div> <h2>学校名称: {{name}}</h2> <h2>学校地址: {{address}}</h2> <button @click="showX">点我输出x</button> </div> `, name: "school", data() { return { name: "尚硅谷", address: "北京", }; }, methods: { showX() { console.log(this.x); }, }, });
const vm = new Vue({ el: "#root", data: { msg: "你好", }, methods: {}, components: { school, }, });
console.log( school.prototype.__proto__ === Vue.prototype );
</script> </body> </html>
|
实例的隐式原型对象永运指向缔造者的原型对象