Vue 简介
Vue 是一个用于"构建用户界面(基于数据渲染出用户看到的画面)" 的渐进式框架
基本使用
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title>
</head><body><div class="box"><h1>{{ msg }}</h1><p>{{ num }}</p></div><!-- 引入的是开发版本的包 - 它包含完整的注释和警告 --><script src="./js/vue.js"></script><script>// 创建实例const boxObj = new Vue({el: '.box',data: {msg: 'Hello World',num: 520}})// data中的内容绑定到了 boxObj 中,我们可以使用 boxObj.msg 和 boxObj.num 获得数据console.log(boxObj.msg)console.log(boxObj.num)</script>
</body></html>
Vue 指令
v-html
作用:设置元素的 innerHTML
<body><div class="box"><div v-html="msg"></div></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {msg: '<a href="https://www.baidu.com">百度</a>'}})</script>
</body>
v-show
作用:控制元素显示隐藏
使用场景:频繁切换显示隐藏的场景
v-if
作用:控制元素显示隐藏(条件渲染)
使用场景:不频繁切换显示隐藏的场景
<body><!-- 两者的区别:v-show 底层原理:切换 css 的 display:none 来控制显示隐藏v-if 底层原理:根据"判断条件"控制"元素节点"是否"创建"或"移除"--><div class="box"><div v-show="flag">我是v-show控制的盒子</div><div v-if="flag">我是v-if控制的盒子</div></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {flag: false // false 让元素隐藏,true 让元素显示}})</script>
</body>
v-else
v-else-if
<body><div class="box"><p v-if="gender === 1">性别:男</p><p v-else>性别:女</p><hr><p v-if="score >= 90">成绩为 A</p><p v-else-if="score >= 75">成绩为 B</p><p v-else-if="score >= 60">成绩为 C</p><p v-else>成绩为D</p></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {gender: 1,score: 80}})</script>
</body>
v-on
作用:注册事件(即:添加监听 + 逻辑处理)
<body><div class="box"><button v-on:click="count--">-</button><span>{{ count }}</span><button @click="count++">+</button> <!-- v-on:click 可以简写为 @click --></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {count: 100}})</script>
</body>
<body><div class="box"><button @click="showChange">显示或隐藏</button><h1 v-show="isShow">Hello World</h1></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {isShow: true},// 这里提供函数,处理复杂的业务逻辑methods: {showChange() { this.isShow = !this.isShow } // 这里的this指的是boxObj// ...}})</script>
</body>
<body><div class="box"><h1>账户余额: {{ money }}元</h1><button @click="buy(8)">冰淇淋8元</button><button @click="buy(15)">奶茶15元</button></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {money: 100},methods: {buy(price) {this.money -= price}}})</script>
</body>
v-bind
作用:动态的设置标签属性
<body><div class="box"><img v-bind:src="imgURL" v-bind:alt="msg"><!-- 如果觉得上面的写法太复杂,可以简写成下面的形式 --><img :src="imgURL" :alt="msg"></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {imgURL: './images/img0.png',msg: 'Jack'}})</script>
</body>
<body><div class="box"><!-- 要求实现:除了top之外,为这个div继续添加类名 className1、className3 --><!-- 方法一 --><div class="top" :class="{ className1: true, className2: false, className3: true }"></div><!-- 方法二 --><div class="top" :class="['className1, className3']"></div></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {}})</script>
</body>
<body><div class="box"><span>当前盒子宽度: {{ wd }}</span><br><span>当前盒子高度: {{ ht }}</span><br><button @click="wd++">横向拉长</button><button @click="ht++">纵向拉长</button><hr><div class="inner" :style="{ 'width': wd + 'px', 'height': ht + 'px', 'background-color': bgc }"></div></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {wd: 100,ht: 50,bgc: 'pink'}})</script>
</body>
v-for
- 基本使用
<body><div class="box"><h3>城市列表</h1><ul><li v-for="(item, index) in list">{{ item }} || {{ index }}</li><!-- 上面的index如果不需要的话,可以写成下面的形式 --><li v-for="item in list">{{ item }}</li></ul></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {list: ['北京', '上海', '广州', '深圳']}})</script>
</body>
- key 作用:给元素添加唯一的标识,便于 Vue 进行列表项的正确排序复用
- 注意:key 的值只能是"字符串"或数字类型,且必须具有唯一性
<body><div class="box"><h3>我的收藏</h1><ul><li v-for="item in list" v-bind:key="item.id"><span>{{ item.name }}</span><span>{{ item.time }}</span><button @click="move(item.id)">取消收藏</button></li></ul></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {list: [{ id: 1, name: '水杯', time: '中午' },{ id: 2, name: '茶壶', time: '傍晚' },{ id: 3, name: '电脑', time: '清晨' },{ id: 4, name: '毛巾', time: '下午' }]},methods: {move(id) {this.list = this.list.filter(item => item.id !== id)}}})</script>
</body>
v-model
作用:给 表单元素
使用,双向数据绑定,可以快速获取或设置表单元素内容
<body><!-- v-model 可以让数据和视图,形成双向数据绑定(1)数据变化,视图自动更新(2)视图变化,数据自动更新--><div class="box">账户:<input type="text" v-model="username"> <br>密码:<input type="password" v-model="password"> <br><button @click="reset">重置</button></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {username: '',password: ''},methods: {reset() {this.username = ''this.password = ''}}})</script>
</body>
<body><div class="box"><form action="http://127.0.0.1/">姓名: <input type="text" name="username" v-model="usernameYX"><br><br>是否成年: <input type="checkbox" name="isAdult" v-model="isAdultYX"><br><br>性别:<input type="radio" name="gender" value="1" v-model="genderYX">男<input type="radio" name="gender" value="0" v-model="genderYX">女<br><br>所在城市:<select name="city" v-model="cityYX"><option value="北京">北京</option><option value="上海">上海</option><option value="广州">广州</option><option value="深圳">深圳</option></select><br><br>自我描述:<textarea name="selfDescribe" v-model="descYX"></textarea><button type="submit">点击提交</button></form></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {usernameYX: '',isAdultYX: true,genderYX: '1',cityYX: '深圳',descYX: "请在这里输入..."}})</script>
</body>
指令修饰符
@keyup.enter | 键盘回车监听 |
---|---|
v-model.trim | 去除首尾空格 |
v-model.number | 转为数字类型 |
@事件名.stop | 阻止冒泡 |
@事件名.prevent | 阻止默认行为 |
<body><div class="box"><input @keyup.enter="warn" v-model="username" type="text"></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {username: ''},methods: {warn() {this.username = '输入错误,请重试'}}})</script>
</body>
计算属性(简写)
概念:
基于现有的数据,计算出来的新属性。依赖的数据变化,自动重新计算
注意:
计算属性,是有缓存功能的,一旦计算出来结果,就会立即缓存,如果依赖项没有变化,则当我们再次调用时,是会直接读取缓存的结果,而不是像methods 那样调用一次执行一次代码
对比:
computed 计算属性 VS methods 方法:1. computed 偏向计算,偏向对数据的处理,通过它的缓存的特性,可以将非常复杂的计算的结果缓存下来,只要依赖项没有发生变化,它的结果就一定没有变化,直接从缓存中读取上一次保留的结果即可2. methods 偏向处理业务逻辑
语法:(演示如下)
<body><div class="box"><h3>购物车清单</h3><table style="border: 1px solid #000;"><tr><th>名字</th><th>数量</th></tr><tr v-for="item in list" :key="item.id"><td>{{ item.name }}</td><td>{{ item.num }}</td></tr></table><p>物品总数:{{ totalCount }}个</p></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {list: [{ id: 1, name: '卫衣', num: 3 },{ id: 2, name: '帽子', num: 7 },{ id: 3, name: '墨镜', num: 2 }]},computed: {totalCount() {// 使用 reduce 求和const total = this.list.reduce((sum, item) => sum + item.num, 0)// 一定要记得返回结果return total}}})</script>
</body>
计算属性(完整写法)
- 计算属性默认的简写,只能读取访问,不能"修改"
- 如果要"修改",需要写计算属性的完整写法
<body><div class="box">姓: <input type="text" v-model="firstName">+名: <input type="text" v-model="lastName">=<span>{{ fullName }}</span><br><br>改名为: <input type="text" v-model="nameIs"><button @click="changeName">确认改名</button></div><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {firstName: '',lastName: '',nameIs: ''},methods: {changeName() {this.fullName = this.nameIs}},computed: {// 下面是简写形式(这样写只能读,不能改)// fullName() {// return this.firstName + this.lastName// }// 完整的写法 -> 获取 + 设置fullName: {// 当fullName计算属性被"获取求值"时,执行get(如果有缓存,优先读取缓存)get() { return this.firstName + this.lastName },// 当fullName计算属性被"修改赋值"时,执行set(修改的值,转递给set方法的形参)set(value) {this.firstName = value.slice(0, 1) // 截取字符串的第一个字符this.lastName = value.slice(1) // 截取字符串剩下的字符}}}})</script>
</body>
监视器(简写)
作用:监视数据变化,执行一些业务逻辑或异步操作
<body><div class="box">请输入简体中文: <input type="text" v-model="words"><br>对应的外星语言: <input type="text" v-model="translation"></div><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {words: '',translation: '',obj: {picture: ''}},watch: {// 监视obj.picture,该方法会在数据变化时执行,形参里的oldValue可以省略// 'obj.picture'(newValue, oldValue) {// console.log('变化了', newValue)// }// 监视words,该方法会在数据变化时执行words(newValue, oldValue) {// 防抖: 为了解决访问过快对服务器造成太大压力的问题,我们可以设置一些延迟,本例中延时400msclearTimeout(this.timer)this.timer = setTimeout(async () => { // 直接给boxObj这个实例挂载timer属性const res = await axios({url: 'https://applet-base-api-t.itheima.net/api/translate/',params: {words: newValue}})this.translation = res.data.data}, 400)}}})</script>
</body>
监视器(完整写法)
<body><div class="box">翻译成:<select name="language" v-model="obj.lang"><option value="001">简体中文</option><option value="002">英文</option><option value="003">意大利语</option></select><br>要翻译的语言: <input type="text" v-model="obj.words"><br>翻译内容结果: <input type="text" v-model="translation"></div><script src="https://unpkg.com/axios/dist/axios.min.js"></script><script src="./js/vue.js"></script><script>const boxObj = new Vue({el: '.box',data: {// 要监视的对象obj: {lang: '002',words: '',},// 翻译结果translation: ''},watch: {obj: {deep: true, // 深度监视// immediate: true, // 初始化立即执行一次handler方法handler(newValueObj) {// 实现防抖功能,人为制造延迟(400ms),减轻服务器压力clearTimeout(this.timer) // 让boxObj挂载timer属性this.timer = setTimeout(async () => {const res = await axios({url: 'https://applet-base-api-t.itheima.net/api/translate/',params: newValueObj})console.log(res)this.translation = res.data.data}, 400)}}}})</script>
</body>