一
MVVM 是Model-View-ViewModel 的缩写,是一种基于前端开发的架构模式,是基于一种代码分工思想来的。
Model:指代的就是vue对象的data选项里面的数据。这里的数据要显示到HTML页面中。
View:指代的就是vue中数据要显示的HTML页面,也称之为“视图模板” 。
ViewModel:指代的是vue.js中编写代码时创建vue实例对象vm,它是vue.js的核心,负责连接 View 和 Model,vm对象会时刻的监控View和Model的变化,保证视图的变量值和data选项中变量的值一致性。这个特性也叫双向数据绑定。
二 Vue的常用指令
一 操作数据
1.1 属性操作
属性 | 描述 | 示例 |
vm.$data | createApp中的data选项,传递到vm对象内部时,变成了使用Proxy对象代理的属性 |
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <p >{{num}}</p> <p ref="p3">{{num}}</p> <p>{{num}}</p> </div> <script> var vm = Vue.createApp({ data(){ return { num: 100, msg: "hello" } } }).mount("#app"); console.log(vm) // 传递到vm对象中的data数据 console.log(vm.$data) // 实例化了vm对象以后,调用mount绑定的可控视图范围 console.log(vm.$el) console.log(vm.$el.parentElement); // 获取当前绑定vm对象的HTML标签,<div id="app" data-v-app>100</div> // 在绑定标签范围内,要抓取元素,通过$refs来抓取 console.log(vm.$refs); console.log(vm.$refs.p3); vm.$refs.p3.innerHTML = "hello!!!!"; </script> </body> </html> 总结 1. createApp中的data选项,传递到vm对象内部时,已经变成了使用Proxy对象代理的属性,可以通过`vm.$data`来查询。 2. vm对象在经过调用mount方法绑定HTML标签以后,这个标签代表的就是当前vm对象的可控范围,可以通过`vm.$el`属性来查询, 通过要获取绑定vm的HTML元素,可以通过`vm.$el.parentElement`来获取。 3. vm对象提供$refs可以让我们开发者直接在vm控制的视图范围,使用`ref`属性绑定任意元素,并在`vm.$refs`中获取。 vm.$refs.p3 则表示获取视图代码中的 `ref="p3"`的标签。 |
vm.$el |
vm对象在经过调用mount方法绑定HTML标签以后,这个标签代表的就是当前vm对象的可控范围。 vm.$el.parentElement可以获取绑定vm的HTML元素 |
|
vm.$refs | vm对象提供$refs可以让我们在vm控制的视图范围,使用ref 属性绑定任意元素,并在 |
指令 | 描述 | 示例 |
v-html | 输出html内容到双标签中 |
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> 密码:<input :type="input_type"><button @click="show_password">{{btn_text}}</button> </div> <script> var vm = Vue.createApp({ data(){ return { input_type: "password", btn_text: "显示密码", } }, methods:{ show_password(){ // 显示密码 if(this.input_type === "password"){ this.input_type = "text"; this.btn_text = "隐藏密码"; }else{ this.input_type = "password"; this.btn_text = "显示密码"; } } } }).mount("#app"); </script> </body> </html> |
v-model | 输出data里面的数据,同时还可以修改data里面的数据。实现了双向绑定 | |
{{普通文本}} | 输出纯文本内容到双标签中 | |
:属性名 | 把属性中的内容当成vue变量进行输出 | |
@事件名 | 绑定事件操作 |
1.2 事件绑定
指令 | 描述 | 示例 |
@click | 鼠标点击事件 |
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <button @click="sub">-</button> <input type="text" v-model.number="num" size="2" @change="check_num"> <button @click="num++">+</button> </div> <script> var vm = Vue.createApp({ data(){ return { num: 0, } }, methods: { sub(){ if(this.num<=0){ return false; } this.num--; }, check_num(){ if(this.num<0){ this.num = 0; } } } }).mount("#app"); </script> </body> </html>
![]() [TOC] # 1. vue.js的快速入门使用 ## 1.1 vue.js库的下载 vue.js是目前前端web开发最流行的工具库/框架,由尤雨溪在2014年2月发布的。 另外几个常见的工具库:react.js、vue.js、angular.js、jQuery 官方网站:https://cn.vuejs.org/ 官方文档:https://v3.cn.vuejs.org/guide/introduction.html vuejs目前有1.x、2.x和3.x 版本,我们学习3.x版本的。 jQuery和vue的定位是不一样的。 ``` jQuery的定位是获取元素和完成特效。 vuejs的定位是方便操作和控制数据和完成特效。 ``` ## 1.2 vuejs的使用 vuejs的使用官方提供了2种方式: 1. 基于脚本导入使用,下载vue.js文件 或者网上别人保存在CDN服务器的vue.js文件,通过script标签引入到html网页。 2. 基于项目构建工具来进行使用,需要安装项目构建工具,自动构建成一个独立的项目。 目前官方推荐的项目构建工具:npm、vue-cli、vite。 我们先通过vuejs的第1种方式来完成vue语法和基础内容的学习。这种方式的使用,vue的引入类似于jQuery,开发中可以使用开发版本vue-x.x.x.js,产品上线要换成vue.min.js。 github: https://github.com/vuejs/vue-next/tags 下载地址:https://v3.cn.vuejs.org/guide/introduction.html https://cdn.jsdelivr.net/npm/vue@next/dist/  ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <!-- 1. 引入vue.js文件 --> <script src="./assets/vue.global.3.2.20.js"></script> </head> <body> {{message}} <!-- vue的模板标签,也叫指令,专门可以输出data里面的变量 --> <div id="app"> <!-- 2. 创建或绑定一个vue操作的标签 --> <p>{{message}}</p> <a :href="url">{{title}}</a> </div> <hr> <div id="demo"> {{message}}<br> {{num}} </div> <script> // 3. 基于Vue.createApp实例化一个vue管理对象-vm var vm = Vue.createApp({ data(){ // 4. data是必填参数,表示vue要输出到控制标签中的内容或属性 return { message: "hello", url: "https://www.baidu.com", title: "百度", } } }).mount("#app"); // 5. 通过vm对象的mount把html标签与vm对象进行捆绑 var vm2 = Vue.createApp({ data(){ return { message: "nihao!!", num: 2300, } } }).mount("#demo") </script> </body> </html> ``` 总结: ```javascript //1. vue的使用要从创建Vue管理对象开始,一个html页面中可以创建多个vm对象,每个vm之间互不干扰。 var vm = Vue.createApp({}); //2. 创建vue对象的时候,需要传递选项参数,选项参数就是json对象,json对象必须有data成员 var vm = Vue.createApp({ data(){ return {} }, }).mount("#app"); //mount:设置vue可以操作的html内容范围,值一般就是css的id选择器。 //data: 保存vue.js中要显示到html页面的数据。 //3. vue.js要控制的内容范围,必须先通过id来设置。 <div id="app"> <h1>{{message}}</h1> <p>{{message}}</p> </div> ``` ### 1.2.1 调试工具Vue Devtools的安装 1. 官网地址:https://v3.cn.vuejs.org/guide/installation.html#%E5%8F%91%E5%B8%83%E7%89%88%E6%9C%AC%E8%AF%B4%E6%98%8E  2. 下载回来的压缩包,复制到ubuntu或者开发的系统下用户家目录下进行解压,然后打开谷歌浏览器,在地址栏上输入`chrome://extensions/`,勾选开发者模式。  3. 选择左边的加载已解压的扩展程序,就是刚才复制到ubuntu下的扩展目录,接着点击当前目录右上角的打开。  4. 完成了步骤以后,就可以看到谷歌浏览器已经成功安装了。效果如下:  5. 在使用vue的页面时,vue图标效果如下:  6. 最后要注意!当前vue插件所在的目录绝对不能删除!!删了这个目录,则插件也没有了。所以自己找一个保存文件的目录把插件放进去再安装到谷歌浏览器中。  ## 1.3 vue.js的M-V-VM思想 MVVM 是Model-View-ViewModel 的缩写,它是一种基于前端开发的架构模式,是一种**代码分工**思想来的。 `Model` 指代的就是vue对象的data选项里面的数据。这里的数据要显示到HTML页面中。 `View` 指代的就是vue中数据要显示的HTML页面,也称之为“视图模板” 。 `ViewModel ` 指代的是vue.js中Vue.createApp创建实例对象vm了,它是vue.js的核心,负责连接 View 和 Model,**保证视图的变量值和data选项中变量的值一致性**,所以前面代码中,data选项里面的数据被显示中p标签中就是vm对象自动完成的。vm对象会时刻的监控View和Model的变化,并**保持双方数据的一致性**!!!有时候,这个特性也叫`双向数据绑定`  编写代码,让我们更加清晰的了解MVVM: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <p>{{num}}</p> <input type="text" v-model="num"><button @click="add">+</button> </div> <script> // M-V-VM中的VM就是Vue.createApp的返回值 var vm = Vue.createApp({ data(){ // data里面的返回值对象就是Model数据模型 return { num: 10, } }, methods:{ add(){ this.num++; console.log(this.num); // this代表的vm对象,vm对象在运行时会自动把methods和data的变量与函数作为自己的属性和方法 this.test() }, test(){ console.log("test方法执行了") } } }).mount("#app"); // mount绑定的就是vue的View视图模板 </script> </body> </html> ``` ## 1.4 VM常用属性操作 在浏览器中可以在 console.log通过 vm对象可以直接访问el和data属性,甚至可以访问data里面的数据 ```vue <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <p >{{num}}</p> <p ref="p3">{{num}}</p> <p>{{num}}</p> </div> <script> var vm = Vue.createApp({ data(){ return { num: 100, msg: "hello" } } }).mount("#app"); console.log(vm) // 传递到vm对象中的data数据 console.log(vm.$data) // 实例化了vm对象以后,调用mount绑定的可控视图范围 console.log(vm.$el) console.log(vm.$el.parentElement); // 获取当前绑定vm对象的HTML标签,<div id="app" data-v-app>100</div> // 在绑定标签范围内,要抓取元素,通过$refs来抓取 console.log(vm.$refs); console.log(vm.$refs.p3); vm.$refs.p3.innerHTML = "hello!!!!"; </script> </body> </html> ``` > 总结 > > 1. createApp中的data选项,传递到vm对象内部时,已经变成了使用Proxy对象代理的属性,可以通过`vm.$data`来查询。 > > 2. vm对象在经过调用mount方法绑定HTML标签以后,这个标签代表的就是当前vm对象的可控范围,可以通过`vm.$el`属性来查询, > > 通过要获取绑定vm的HTML元素,可以通过`vm.$el.parentElement`来获取。 > > 3. vm对象提供$refs可以让我们开发者直接在vm控制的视图范围,使用`ref`属性绑定任意元素,并在`vm.$refs`中获取。 > > vm.$refs.p3 则表示获取视图代码中的 `ref="p3"`的标签。 ## 1.5 显示数据 1. 在双标签中显示**纯文本数据**一般通过\{\{ \}\}来完成数据显示,双花括号中还可以支持js表达式和符合js语法的代码,例如函数调用. 2. 如果双标签的内容要显示的**数据包含html代码**,则使用v-html来完成 3. 在**表单输入框**中显示数据要使用v-model来完成数据显示 整个HTML网页组织起来就是DOM树形结构,那么vue在视图模板的时候,采用了虚拟DOM方式来展示数据的。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <p>{{num}}</p> <p>{{num+200}}</p> <p>{{(3.3333333+1).toFixed(2)}}</p> <p>{{parseInt(num+3.3333333)}}</p> <p>{{Math.random()}}</p> <p @click="shownum">{{num}}</p> <hr> <p>{{message}}</p> <p><a href="www.baidu.com">百度</a></p> <p v-html="message"></p> <hr> <input type="text" :value="num"><br> <!-- 只读属性,不能在修改时保证所有的变量值同步 --> <input type="text" v-model="num"> <textarea name="" id="" cols="30" rows="10" v-model="num"></textarea> <select name="" id="" v-model="num"> <option value="200">上海</option> <option value="100">天津</option> <option value="300">北京</option> </select> </div> <script> var vm = Vue.createApp({ data(){ return { num: 100, message: '<a href="http://www.baidu.com">百度</a>', } }, methods:{ shownum(){ alert(this.num); // 把js原生的DOM或者BOM操作,全部写在HTML视图以外。 console.log(this.num); } } }).mount("#app"); </script> </body> </html> ``` 总结: ``` 1. 可以在普通双标签中使用{{ }} 或者 v-html 来输出data里面的数据 <h1>{{message}}</h1> <h1 v-html="message"></h1> 2. 可以在表单标签中使用v-model属性来输出data里面的数据,同时还可以修改data里面的数据 <input type="text" v-model="username"> ``` # 2. vue的常用指令 指令 (Directives) 是带有“v-”前缀的特殊属性,由vue提供的。每一个指令在vue中都有固定的作用。 在vue中提供了很多指令,常用的有:`{{变量名}}`,`v-if`、`v-model`、`v-for`、`v-html`、`@事件名`或`:属性名`等等。 指令会在vm对象的data选项数据发生变化时,会同时改变元素中的其控制的内容或属性。 因为vue的历史版本原因,所以有一部分指令都有两种写法: | vue1.x | vue2.x以后 | 描述 | | ----------------- | ------------ | --------------------------------- | | v-html | v-html | 输出html内容到双标签中 | | v-text="普通文本" | {{普通文本}} | 输出纯文本内容到双标签中 | | v-bind:属性名 | :属性名 | 把属性中的内容当成vue变量进行输出 | | v-on:事件名 | @事件名 | 绑定事件操作 | ## 2.1 属性操作 格式: ```vue <标签名 :标签属性="data变量名"></标签名> ``` ```html <p :title="str1">{{ str1 }}</p> <!-- 也可以使用v-html显示双标签的内容,{{ }} 是简写 --> <a :href="url2">淘宝</a> <a v-bind:href="url1">百度</a> <!-- v-bind是vue1.x版本的写法 --> ``` #### 显示/隐藏密码 代码: ```vue <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> 密码:<input :type="input_type"><button @click="show_password">{{btn_text}}</button> </div> <script> var vm = Vue.createApp({ data(){ return { input_type: "password", btn_text: "显示密码", } }, methods:{ show_password(){ // 显示密码 if(this.input_type === "password"){ this.input_type = "text"; this.btn_text = "隐藏密码"; }else{ this.input_type = "password"; this.btn_text = "显示密码"; } } } }).mount("#app"); </script> </body> </html> ``` ## 2.2 事件绑定 基本写法 ```html <标签名 @click="num+=5">按钮</标签名> <标签名 @click="方法名">按钮</标签名> <标签名 @click="方法名(参数1,参数2,....)">按钮</标签名> ``` vue中常用事件的写法对照: | vue写法 | 原生javascript写法 | 描述 | | --------- | ------------------ | -------------- | | @click | onclick | 鼠标点击事件 | | @dblclick | ondblclick | 鼠标双击事件 | | @submit | onsubmit | 表单提交事件 | | @focus | onfocus | 获取焦点事件 | | @blur | onblur | 失去焦点事件 | | @change | onchange | 值发生改变事件 | | .... | ... | ... | #### 商品增加减少数量 步骤: 1. 给vue对象添加操作数据的方法 2. 在标签中使用指令调用操作数据的方法 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <button @click="sub">-</button> <input type="text" v-model.number="num" size="2" @change="check_num"> <button @click="num++">+</button> </div> <script> var vm = Vue.createApp({ data(){ return { num: 0, } }, methods: { sub(){ if(this.num<=0){ return false; } this.num--; }, check_num(){ if(this.num<0){ this.num = 0; } } } }).mount("#app"); </script> </body> </html> ``` #### 表单的数据校验 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> span.tips{ font-size: 12px; color: red; margin-left: 5px; } </style> </head> <body> <div id="app"> 登录账号:<input type="text" placeholder="请输入账号!" v-model="username" @blur="check_username" @focus="clear_tips('username_tip')"> <span class="tips" ref="username_tip"></span><br> 登录密码:<input type="password" placeholder="请输入密码!" v-model="password" @blur="check_password" @focus="clear_tips('password_tip')"> <span class="tips" ref="password_tip"></span><br> 确认密码:<input type="password" placeholder="请输入确认密码!" v-model="password2" @blur="check_password2" @focus="clear_tips('password2_tip')"> <span class="tips" ref="password2_tip"></span><br> <input type="submit" value="注册" @click="submit_form"> </div> <script> var vm = Vue.createApp({ data(){ return { username: "root", password: "", password2: "", } }, methods: { check_username(){ if(this.username.length < 4 || this.username.length > 12){ this.$refs.username_tip.innerHTML = "请输入4-12个字符长度的登录账号!"; return true; } }, clear_tips(name){ this.$refs[name].innerHTML = "" }, check_password(){ if(this.password.length<6 || this.password.length>16){ this.$refs.password_tip.innerHTML = "请输入6-16个字符长度的登录密码!"; return true; } }, check_password2(){ // 验证密码与确认密码是否一致 if(this.password !== this.password2){ this.$refs.password2_tip.innerHTML = "登录密码与确认密码必须一致!"; return true; } }, submit_form(){ if (this.check_username() || this.check_password() || this.check_password2() ){ console.log("验证失败!无法提交数据"); return false; } } } }).mount("#app"); </script> </body> </html> ``` ## 2.3 操作样式 操作样式,本质就是属性操作,使用冒号: ### 2.3.1 控制标签class类名 ``` 格式: <h1 :class="值">元素</h1> # 值可以是变量名、对象、对象的变量名、数组、数组变量名 ``` ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> .p1{ background-color: yellow; } .p2{ color: red; } </style> </head> <body> <div id="app"> <p>用法1::class属性值是一个class类名的变量</p> <p :class="cls1">一段文本信息</p> <hr> <p>用法2::class属性值是一个json对象</p> <p :class="{p1: b1, p2: b2}">一段文本信息</p> <hr> <p>用法3::class属性值是一个对象变量名</p> <p :class="p_cls1">一段文本信息</p> <hr> <p>用法4::class属性值是一个数组,数组的成员是data中声明的用于控制样式的json对象</p> <p :class="[cls2,cls3]">一段文本信息</p> <hr> <p>用法5: :class属性值时一个数组变量名</p> <p :class="arr">一段文本信息</p> <p>注意::class属性在同一个标签中,只能出现一次,后面出现的:class属性会被vue忽略掉,但是:class可以和class属性组合使用,class也只能在同一个标签中出现一次</p> <p class="p1" :class="cls2" :class="cls3">一段文本信息</p> </div> <script> var vm = Vue.createApp({ data(){ return { cls1: "p1", b1: true, b2: true, p_cls1: { p1: true, p2: false }, cls2: { p2: true, }, cls3: { p1: true, }, arr: [ {p1: true}, {p2: true}, ] } }, methods: { } }).mount("#app"); </script> </body> </html> ``` 代码执行效果:  总结: ```html 1. 给元素绑定class类名,最常用的就是第1,2,3种。 vue对象的data数据: data(){ return { cls1: "p1", b1: true, b2: true, p_cls1: { p1: true, p2: false }, cls2: { p2: true, }, } }, html元素: <div class="p1" :class="cls2">2222</div> 最终浏览器效果: <div class="p1 p2">2222</div> ``` ### 2.3.2 控制标签style样式 工作中基本很少出现style控制样式,一个规范不允许,另一个就是代码不好维护。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <p>用法1::style的值是一个json对象</p> <p :style="{'font-size': size, color: col1}">一段文本信息</p> <hr> <p>用法2::style的值是一个对象变量名</p> <p :style="sty1">一段文本信息</p> <hr> <p>用法3::style的值是一个数组,数组的成员是样式组成的对象</p> <p :style="[sty2, sty3]"></p> <p>用法4::style的值是一个数组变量名</p> <p :style="sty_list"></p> </div> <script> var obj = { backgroundColor: "red", "border-radius": "100%", } var vm = Vue.createApp({ data(){ return { size: '24px', col1: 'red', sty1: { "text-align": "center", "color": "yellow", "background-color": "red", }, sty2: { "width": '150px', "height": '150px', }, sty3: { "background-color": "red", }, sty_list: [ obj, { "width": '150px', "height": '150px', }, ] } }, methods: { } }).mount("#app"); </script> </body> </html> ``` ### 2.3.3 实例-vue版本选项卡 基本样式: ```vue <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> p{ padding: 0; margin: 0; } .title-list span{ display: inline-block; /* 设置元素的显示模式:行级块状元素 */ height: 60px; line-height: 60px; width: 120px; background-color: #bbb; text-align: center; cursor: pointer; } .title-list .activate{ background-color: yellow; } .content-list .content{ background-color: yellow; display: none; width: 370px; height: 280px; } .content-list .current{ display: block; } </style> </head> <body> <div id="optioncard"> <div class="title-list"> <span class="activate">国内新闻</span> <span>国际新闻</span> <span>银河新闻</span> </div> <div class="content-list"> <div class="content current"> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> </div> <div class="content current"> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> </div> <div class="content"> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> </div> </div> </div> <script> </script> </body> </html> ``` 特效实现,代码: ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> p{ padding: 0; margin: 0; } .title-list span{ display: inline-block; /* 设置元素的显示模式:行级块状元素 */ height: 60px; line-height: 60px; width: 120px; background-color: #bbb; text-align: center; cursor: pointer; } .title-list .activate{ background-color: yellow; } .content-list .content{ background-color: yellow; display: none; width: 370px; height: 280px; } .content-list .current{ display: block; } </style> </head> <body> <div id="optioncard"> <div class="title-list"> <span :class="{activate: index === 0}" @click="index=0">国内新闻</span> <span :class="{activate: index === 1}" @click="index=1">国际新闻</span> <span :class="{activate: index === 2}" @click="index=2">银河新闻</span> </div> <div class="content-list"> <div class="content" :class="{current: index === 0}"> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> </div> <div class="content" :class="{current: index === 1}"> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> </div> <div class="content" :class="{current: index === 2}"> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> </div> </div> </div> <script> var vm = Vue.createApp({ data(){ return { index: 0, } }, methods: { } }).mount("#optioncard") </script> </body> </html> ``` 代码运行效果:  ## 2.4 条件渲染指令 vue中提供了两个指令可以用于**判断是否要显示元素**,分别是v-if和v-show。 ### 2.4.1 v-if ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.3.2.20.js"></script> </head> <body> <div id="app"> <!-- vue对象最终会把条件的结果变成布尔值 --> <p v-if="username">欢迎回到xx网站,{{username}}</p> </div> <script> const vm =Vue.createApp({ data(){ return { username: "", } }, }).mount("#app") </script> </body> </html> ``` ### 2.4.2 v-else v-else指令来表示 v-if 的“else 块”,v-else 元素必须紧跟在带 v-if 或者 v-else-if 的元素的后面,否则它将不会被识别。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.3.2.20.js"></script> </head> <body> <div id="app"> <!-- v-else只能作为子语句,跟在上一个v-if后面,而且只能出现一次,否则后面v-else会覆盖前面的v-else --> <p v-if="username">欢迎回到xx网站,尊敬的{{username}}!</p> <p v-else>欢迎访问xx网站,尊敬的游客!</p> <p v-else>欢迎访问xx网站,尊敬的游客!2</p> </div> <script> const vm =Vue.createApp({ data(){ return { username: "", } }, }).mount("#app") </script> </body> </html> ``` ### 2.4.3 v-else-if v-if后面可以出现0个或多个v-else-if语句,而v-else-if后面可以跟着0个或1个v-else子语句。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="js/vue.3.2.20.js"></script> <style> .l0{ color: #000; } .l1{ color: #ffff99; background: black; } .l2{ color: #ffff33; background: black; } .l3{ color: #aaaa00; background: black; } </style> </head> <body> <div id="app"> <p v-if="username">欢迎回到xx网站,尊敬的{{username}}!</p> <p v-else>欢迎访问xx网站,尊敬的游客!</p> <p v-if="level === 0" class="l0">您是vip会员!</p> <p v-else-if="level === 1" class="l1">您是svip会员!</p> <p v-else-if="level === 2" class="l2">您是mvip会员!</p> <p v-else-if="level === 3" class="l3">您是msvip会员!</p> <p v-else>您是签到会员!</p> </div> <script> const vm =Vue.createApp({ data(){ return { username: "", // 会员账户名 level: 0, // 会员登录 } }, }).mount("#app") </script> </body> </html> ``` ### 2.4.4 v-show v-show用法和v-if大致一样,区别在于2点: 1. v-show后面不能v-else或者v-else-if 2. v-show隐藏元素时,使用的是css样式的display:none来隐藏的, 而v-if是直接从HTML文档中移除元素[ DOM操作中的remove ] ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <!-- <p v-if="username">[v-if]欢迎回到xx网站,{{username}}</p>--> <!-- <p v-show="username">[v-show]欢迎回到xx网站,{{username}}</p>--> <p v-show="username">[v-show]欢迎回到xx网站,{{username}}</p> <p v-show="!username">欢迎访问xx网站,尊敬的游客!1111</p> <p v-show="level === 0" class="l0">您是普通会员!</p> <p v-show="level === 1" class="l1">您是vip会员!</p> <p v-show="level === 2" class="l2">您是vvip会员!</p> <p v-show="level === 3" class="l3">您是svip会员!</p> <p v-show="![0,1,2,3].includes(level)">您是签到会员!</p> </div> <script> var vm = Vue.createApp({ data(){ return { username: "", level: 0, } } }).mount("#app") </script> </body> </html> ``` 当HTML页面中有使用了vue以外的其他前端插件,这些插件也操作了和vue控制的内容范围重叠的内容,则需要使用v-show。 ## 2.5 列表渲染指令 在vue中,可以通过v-for指令可以将一组数据渲染到页面中,数据可以是**数组**或者对象。 ```html 数据是数组: <ul> <!--book是列表的每一个元素--> <li v-for="book in book_list">{{book.title}}</li> </ul> <ul> <!--book是列表的每一个元素,index是每个元素的下标--> <li v-for="(book, index) in book_list">第{{ index+1}}本图书:{{book.title}}</li> </ul> <script> var vm1 = new Vue({ el:"#app", data:{ book_list:[ {"id":1,"title":"图书名称1","price":200}, {"id":2,"title":"图书名称2","price":200}, {"id":3,"title":"图书名称3","price":200}, {"id":4,"title":"图书名称4","price":200}, ] } }) </script> 数据是对象: <ul> <!--i是每一个value值--> <li v-for="value in book">{{value}}</li> </ul> <ul> <!--i是每一个value值,j是每一个键名--> <li v-for="attr, value in book">{{attr}}:{{value}}</li> </ul> <script> var vm1 = new Vue({ el:"#app", data(){ return { book: { // "attr":"value" "id":11, "title":"图书名称1", "price":200 }, } } }) </script> ``` 课堂代码; ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> .table{ border-collapse: collapse; border: 1px solid red; width: 600px; } .table td, .table th{ border: 1px solid red; height: 40px; line-height: 40px; font-size: 12px; text-align: center; } .table .attr{ line-height: 18px; } </style> </head> <body> <div id="app"> <p>循环显示数组内容</p> <!-- <table class="table">--> <!-- <tr>--> <!-- <th>序号[正序]</th>--> <!-- <th>序号[倒序]</th>--> <!-- <th>ID</th>--> <!-- <th>图书</th>--> <!-- <th>价格</th>--> <!-- <th>属性</th>--> <!-- <th>是否第一行数据</th>--> <!-- <th>是否最后一行数据</th>--> <!-- </tr>--> <!--<!– <tr v-for="book in book_list">–>--> <!-- <tr v-for="(book, key) in book_list">--> <!-- <td>{{book_list.length-key}}</td>--> <!-- <td>{{key+1}}</td>--> <!-- <td>{{book.id}}</td>--> <!-- <td>{{book.title}}</td>--> <!-- <td>{{book.price}}</td>--> <!-- <td v-if="key === 0">√</td>--> <!-- <td v-else>×</td>--> <!-- <td v-if="key === book_list.length-1">√</td>--> <!-- <td v-else>×</td>--> <!-- </tr>--> <!-- </table>--> <p>循环显示对象属性</p> <table class="table"> <tr> <th>ID</th> <th>图书</th> <th>价格</th> <th>属性</th> </tr> <tr v-for="(book, key) in book_list"> <td>{{book.id}}</td> <td>{{book.title}}</td> <td>{{book.price}}</td> <!-- <td class="attr">--> <!-- <div v-for="value in book.attr_data">属性名:{{value}}</div>--> <!-- </td>--> <td class="attr"> <div v-for="(value, attr) in book.attr_data">{{attr}}:{{value}}</div> </td> </tr> </table> </div> <script> var vm = Vue.createApp({ data(){ return { book_list: [ {"id":31,"title":"图书名称1","price":200, "attr_data": {"正文语种": "英文", "页数": "541", "开本": "16开", "出版时间": "2000-11-01", "出版社": "人民邮电出版社"}}, {"id":12,"title":"图书名称2","price":200, "attr_data": {"正文语种": "中文", "页数": "511", "开本": "16开", "出版时间": "2010-11-01", "出版社": "人民邮电出版社"}}, {"id":33,"title":"图书名称3","price":200, "attr_data": {"页数": "501", "出版时间": "2019-12-01", "出版社": "人民邮电出版社"}}, {"id":54,"title":"图书名称4","price":200, "attr_data": { "页数": "671", "开本": "16开", "出版时间": "2019-03-01", "出版社": "人民邮电出版社"}}, {"id":14,"title":"图书名称4","price":200, "attr_data": {}}, ] } } }).mount("#app") </script> </body> </html> ``` 练习: ```html goods_list: [ {"name":"python入门","price":150}, {"name":"python进阶","price":100}, {"name":"python高级","price":75}, {"name":"python研究","price":60}, {"name":"python放弃","price":110}, ] # 把上面的数据采用table表格输出到页面,价格大于100的一行数据需要添加背景色橙色[orange] ``` 代码: ```vue <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> .table{ border-collapse: collapse; border: 1px solid red; width: 600px; } .table td, .table th{ border: 1px solid red; height: 40px; line-height: 40px; font-size: 12px; text-align: center; } .bg{ background-color: orange; } </style> </head> <body> <div id="app"> <table class="table"> <tr> <th>序号</th> <th>商品名</th> <th>价格</th> <th>购买数量</th> <th>单品统计</th> </tr> <tr v-for="(goods, key) in goods_list" :class="{bg: goods.price>100}"> <td>{{key+1}}</td> <td>{{goods.name}}</td> <td>{{goods.price}}</td> <td> <button @click="sub(goods)">-</button> <input type="text" size="1" v-model="goods.num"> <button @click="goods.num+=10">+</button> </td> <td></td> </tr> </table> </div> <script> var vm = Vue.createApp({ data(){ return { goods_list: [ {"name":"python入门","price":150, num: 0}, {"name":"python进阶","price":100, num: 0}, {"name":"python高级","price":75, num: 0}, {"name":"python研究","price":60, num: 0}, {"name":"python放弃","price":110, num: 0}, ] } }, methods:{ sub(goods){ goods.num-=10; if(goods.num<0){ goods.num = 0; } } } }).mount("#app") </script> </body> </html> ``` 上面的练习虽然完成了,但是怎么统计累加的商品数量,则及时的显示总商品的价格等等,就需要我们继续往下学习vue的功能。 # 3. Vm对象提供的选项API 所谓的选项API就是在实例化vm对象时,往createApp中传递进行选项参数,例如,我们已经使用过的data或者methods就是选项api。 ## 3.1 过滤器 Vue3.0已经被淘汰了过滤器这个选项,所以我们这里使用2.6.11版本来完成代码的编写。 过滤器,就是vue允许开发者自定义的文本格式化函数,可以使用在两个地方:输出内容和操作数据中。 定义过滤器的方式有两种:全局过滤器和局部过滤器。 ### 3.1.1 使用Vue.filter()进行全局定义 js/filters.js,代码: ```javascript // 全局范围定义的过滤器 Vue.filter("money1", function(v){ //就是来格式化(处理)v这个数据的 if(v==0){ return v } return v.toFixed(2)+"元" }) ``` ### 3.1.2 在vm对象中通过filters选项api来局部定义 ```vue <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="./assets/vue@2.7.8.js"></script> <script src="./assets/filter.js"></script> </head> <body> <div id="app"> <p>{{price|money}}</p> <p>{{price|mon}}</p> <p>{{money_format(price)}}</p> </div> <script> var vm = new Vue({ // 相当于vue3.x的 Vue.createApp() el: "#app", // 相当于vue3.x的mount绑定视图方法 data(){ return { message: "hello, vue2.x", price: 3.55555 } }, methods: { money_format(data){ // 过滤器完全可以被methods选项中定义的函数所代替,所以在vue3.x以后成为了废弃特性 return `¥${data.toFixed(2)}` } }, filters: { // 局部过滤器,是当前vm对象的属性方法存在,所以无法被外界使用 mon(data){ return `¥${data.toFixed(2)}` } } }) </script> </body> </html> ``` ## 3.2 计算属性和侦听属性 ### 3.2.1 计算属性 所谓的计算属性,是vue提供给我们开发者用于编写代码时保存计算出新的数据结果的变量。主要通过computed选项进行声明的。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <input type="text" size="1" v-model.number="num1">+ <input type="text" size="1" v-model.number="num2">={{result}} </div> <script> var vm = Vue.createApp({ data(){ return { num1: 10, num2: 10, } }, computed: { // 计算属性选项API,里面的成员就是一个属性方法,用于保存在vm中其他变量的计算结果 result(){ return this.num1+ this.num2 } } }).mount("#app") </script> </body> </html> ``` ### 3.2.2 侦听属性 侦听属性,可以帮助我们侦听data某个数据的变化,从而做相应的自定义操作。 侦听属性是一个对象,它的键是要监听的对象或者变量,值一般是函数,当侦听的data数据发生变化时,会自定执行的对应函数,这个函数在被调用时,vue会传入两个形参,第一个是变化前的数据值,第二个是变化后的数据值。 ```html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> input{ outline: none; border: 1px solid #333; } </style> </head> <body> <div id="app"> 账户:<input ref="username" type="text" v-model="username" @blur="check_username"><br><br> 口令:<input ref="password" type="text" v-model="password"><br><br> </div> <script> var vm = Vue.createApp({ data(){ return { username: "", password: "" } }, watch: { // 侦听选项API,成员就是data变量名 username(new_data, old_data){ // 侦听data中的username console.log(`old_data=${old_data}, new_data=${new_data}`) let length = this.username.length; if(length>=6 && length<=16){ this.$refs.username.style.border="1px solid blue"; }else{ this.$refs.username.style.border="1px solid red"; } }, password(new_value, old_value){ // 参数为:修改前的变量值以及修改后的变量值 if(/^\d+$/.test(this.password)){ this.$refs.password.style.border="1px solid red"; }else{ this.$refs.password.style.border="1px solid blue"; } } }, methods:{ check_username(){ console.log("check_username执行了。") } } }).mount("#app") </script> </body> </html> |
@dblclick | 鼠标双击事件 | |
@submit | 表单提交事件 | |
@focus | 获取焦点事件 | |
@blur | 失去焦点事件 | |
@change | 值发生改变事件 |
二 操作样式
控制标签 | 格式 | 示例 | ||
class类名【常用】 |
|
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> .p1{ background-color: yellow; } .p2{ color: red; } </style> </head> <body> <div id="app"> <p>用法1::class属性值是一个class类名的变量</p> <p :class="cls1">一段文本信息</p> <hr> <p>用法2::class属性值是一个json对象</p> <p :class="{p1: b1, p2: b2}">一段文本信息</p> <hr> <p>用法3::class属性值是一个对象变量名</p> <p :class="p_cls1">一段文本信息</p> <hr> <p>用法4::class属性值是一个数组,数组的成员是data中声明的用于控制样式的json对象</p> <p :class="[cls2,cls3]">一段文本信息</p> <hr> <p>用法5: :class属性值时一个数组变量名</p> <p :class="arr">一段文本信息</p> <p>注意::class属性在同一个标签中,只能出现一次,后面出现的:class属性会被vue忽略掉,但是:class可以和class属性组合使用,class也只能在同一个标签中出现一次</p> <p class="p1" :class="cls2" :class="cls3">一段文本信息</p> </div> <script> var vm = Vue.createApp({ data(){ return { cls1: "p1", b1: true, b2: true, p_cls1: { p1: true, p2: false }, cls2: { p2: true, }, cls3: { p1: true, }, arr: [ {p1: true}, {p2: true}, ] } }, methods: { } }).mount("#app"); </script> </body> </html>
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> <style> p{ padding: 0; margin: 0; } .title-list span{ display: inline-block; /* 设置元素的显示模式:行级块状元素 */ height: 60px; line-height: 60px; width: 120px; background-color: #bbb; text-align: center; cursor: pointer; } .title-list .activate{ background-color: yellow; } .content-list .content{ background-color: yellow; display: none; width: 370px; height: 280px; } .content-list .current{ display: block; } </style> </head> <body> <div id="optioncard"> <div class="title-list"> <span class="activate">国内新闻</span> <span>国际新闻</span> <span>银河新闻</span> </div> <div class="content-list"> <div class="content current"> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> <p>国内新闻列表</p> </div> <div class="content current"> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> <p>国际新闻列表</p> </div> <div class="content"> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> <p>银河新闻列表</p> </div> </div> </div> <script> </script> </body> </html> |
||
style样式 |
|
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="assets/vue.global.3.2.20.js"></script> </head> <body> <div id="app"> <p>用法1::style的值是一个json对象</p> <p :style="{'font-size': size, color: col1}">一段文本信息</p> <hr> <p>用法2::style的值是一个对象变量名</p> <p :style="sty1">一段文本信息</p> <hr> <p>用法3::style的值是一个数组,数组的成员是样式组成的对象</p> <p :style="[sty2, sty3]"></p> <p>用法4::style的值是一个数组变量名</p> <p :style="sty_list"></p> </div> <script> var obj = { backgroundColor: "red", "border-radius": "100%", } var vm = Vue.createApp({ data(){ return { size: '24px', col1: 'red', sty1: { "text-align": "center", "color": "yellow", "background-color": "red", }, sty2: { "width": '150px', "height": '150px', }, sty3: { "background-color": "red", }, sty_list: [ obj, { "width": '150px', "height": '150px', }, ] } }, methods: { } }).mount("#app"); </script> </body> </html> |
三 条件渲染指令
指令 | 示例 |
v-if |
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <!-- vue对象最终会把条件的结果变成布尔值 --> <p v-if="username">欢迎回到xx网站,{{username}}</p> <p v-else>欢迎回到xx网站,尊敬的游客</p> <p v-else-if="level===0">您是vip会员</p> <p v-else-if="level===1">您是class=10svip会员</p> <p v-else-if="level===2">您是mvip会员</p> <p v-else-if="level===3">您是msvip会员</p> </div> <script> const vm =Vue.createApp({ data(){ return { username: "", level: 0, } }, }).mount("#app") </script> </body> </html> |
v-else | |
v-else-if | |
v-show |
![]() <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> </head> <body> <div id="app"> <!-- vue对象最终会把条件的结果变成布尔值 --> <p v-show="username">欢迎回到xx网站,{{username}}</p> <p v-show="!username">欢迎回到xx网站,尊敬的游客</p> <p v-show="level===0">您是vip会员</p> <p v-show="level===1">您是class=10svip会员</p> <p v-show="level===2">您是mvip会员</p> <p v-show="level===3">您是msvip会员</p> </div> <script> const vm =Vue.createApp({ data(){ return { username: "", level: 0, } }, }).mount("#app") </script> </body> </html> |
v-show用法和v-if大致一样,区别在于2点:
-
-
v-show隐藏元素时,使用的是css样式的display:none来隐藏的,而v-if是直接从HTML文档中移除元素[ DOM操作中的remove ]。下图为v-show隐藏元素
四 列表渲染指令
在vue中,可以通过v-for指令可以将一组数据渲染到页面中,数据可以是数组或者对象。

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <script src="https://unpkg.com/vue@next"></script> <style> .table{ border-collapse: collapse; border: 1px solid red; width: 600px; } .table td, .table th{ border: 1px solid red; height: 40px; line-height: 40px; font-size: 12px; text-align: center; } .bg{ background-color: orange; } </style> </head> <body> <div id="app"> <table class="table"> <tr> <th>序号</th> <th>商品名</th> <th>价格</th> <th>购买数量</th> <th>单品统计</th> </tr> <tr v-for="(goods, key) in goods_list" :class="{bg: goods.price>100}"> <td>{{key+1}}</td> <td>{{goods.name}}</td> <td>{{goods.price}}</td> <td> <button @click="sub(goods)">-</button> <input type="text" size="1" v-model="goods.num"> <button @click="goods.num+=10">+</button> </td> <td></td> </tr> </table> </div> <script> var vm = Vue.createApp({ data(){ return { goods_list: [ {"name":"python入门","price":150, num: 0}, {"name":"python进阶","price":100, num: 0}, {"name":"python高级","price":75, num: 0}, {"name":"python研究","price":60, num: 0}, {"name":"python放弃","price":110, num: 0}, ] } }, methods:{ sub(goods){ goods.num-=10; if(goods.num<0){ goods.num = 0; } } } }).mount("#app") </script> </body> </html>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 【自荐】一款简洁、开源的在线白板工具 Drawnix