vue的两个特性
数据驱动视图
vue会监听数据的变化,从而自动重新渲染页面的结构,数据驱动视图是单向的数据绑定。即vue帮我操作dom元素来渲染页面,开发者不用再操作dom了。
双向数据绑定
在网页中,form表单负责采集数据,ajax负责提交数据。
而vue呢,会在填写表单时,双向数据绑定可以辅助开发者在不操作dom的前提下,自动将用户填写的内容同步到数据源中。
vue基础语法
基本使用步骤
- 导入vue.js的script脚本文件
- 在页面中声明一个将要被vue所控制的dom区域
- 创建vm实例对象(vue实例对象)
//1.导入vue的库文件,在window全局就有个了vue这个构造函数 <script src="./vue-2.6.12.js"></script> <script> //2.创建vue的实例对象 const vm = new Vue({ //4.属性是固定的写法,表示当前vm实例要控制页面上的哪个区域, // 接收的值是一个选择器 el:'#app', //5.data对象就是要渲染到页面上的数据 data:{ username:'zzl' } }) </script>结果演示
vue的指令
指令时vue为开发者提供的模版语法,用于辅助开发者渲染页面的基本结构。
- 内容渲染指令
- 属性绑定指令
- 事件绑定指令
- 双向绑定指令
- 条件渲染指令
- 列表渲染指令
内容渲染指令
用来辅助开发者渲染dom元素的文本内容,常用的内容渲染指令如下:
- v-text
- {{}}
- v-html
v-text(不推荐)
<!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> <!-- 3.希望vue能控制下面的这个div,把数据填充到div内部 --> <div id="app"> <!-- 把username对应的值,渲染到第一个p标签中 --> <p v-text="username"></p> <p v-text="gender">性别</p> </div> <!-- 1.导入vue的库文件,在window全局就有个了vue这个构造函数--> <script src="./vue-2.6.12.js"></script> <script> //2.创建vue的实例对象 const vm = new Vue({ //4.属性是固定的写法,表示当前vm实例要控制页面上的哪个区域, // 接收的值是一个选择器 el: '#app', //5.data对象就是要渲染到页面上的数据 data: { username: 'zzl', gender:'男' } }) </script> </body> </html>结果演示
{{}} 插值表达式
它专门用来解决v-text会覆盖默认文本内容的问题,相当于占位符。
<p>性别:{{gender}}</p>结果演示
v-html
v-text和插值表达式智能渲染纯文本内容,如果要把包含html标签的字符串渲染为页面的html元素,需要使用v-html指令
<!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> </head> <body> <!-- 3.希望vue能控制下面的这个div,把数据填充到div内部 --> <div id="app"> <!-- 把username对应的值,渲染到第一个p标签中 --> <p v-text="username"></p> <p>性别:{{gender}}</p> <div v-html="info"></div> </div> <!-- 1.导入vue的库文件,在window全局就有个了vue这个构造函数--> <script src="./vue-2.6.12.js"></script> <script> //2.创建vue的实例对象 const vm = new Vue({ //4.属性是固定的写法,表示当前vm实例要控制页面上的哪个区域, // 接收的值是一个选择器 el: '#app', //5.data对象就是要渲染到页面上的数据 data: { username: 'zzl', gender:'男', info:'<h1 style="color:red">渣渣龙</h1>' } }) </script> </body> </html>结果演示
属性绑定指令
v-bind属性绑定指令可以为元素属性动态单向绑定属性值。
<!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> <!-- 3.希望vue能控制下面的这个div,把数据填充到div内部 --> <div id="app"> <input type="text" placeholder="请看右边的框"> <input type="text" v-bind:placeholder="tips"> <!-- v-bind简写为: --> <input type="text" :placeholder="tips"> </div> <!-- 1.导入vue的库文件,在window全局就有个了vue这个构造函数--> <script src="./vue-2.6.12.js"></script> <script> //2.创建vue的实例对象 const vm = new Vue({ //4.属性是固定的写法,表示当前vm实例要控制页面上的哪个区域, // 接收的值是一个选择器 el: '#app', //5.data对象就是要渲染到页面上的数据 data: { tips:'zzl' } }) </script> </body> </html>结果演示
属性添加相关计算
<!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> <!-- 3.希望vue能控制下面的这个div,把数据填充到div内部 --> <div id="app"> <div>1+2的结果是:{{1+2}}</div> <div :title="'box'+index">鼠标放我身上</div> </div> <!-- 1.导入vue的库文件,在window全局就有个了vue这个构造函数--> <script src="./vue-2.6.12.js"></script> <script> //2.创建vue的实例对象 const vm = new Vue({ //4.属性是固定的写法,表示当前vm实例要控制页面上的哪个区域, // 接收的值是一个选择器 el: '#app', data:{ index:3 } }) </script> </body> </html>结果演示
{{number+1}} {{ok ? 'yes' : 'no'}} ...
事件绑定指令
v-on事件绑定指令
用来辅助开发者为dom元素绑定事件监听
v-on:事件名称="事件处理函数的名称"
<!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> <div id="app"> <p>count的值是{{count}}</p> <!-- 可以传参 --> <button v-on:click="add">+1</button> <!-- v-on可以简写为@ --> <button @click="sub">-1</button> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', data: { count:0 }, //methods定义事件处理函数 methods:{ add(e){ // console.log(e) this.count+=1 }, sub(){ vm.count-=1 } } }) </script> </body> </html>结果演示
事件对象
vue提供了内置变量$event,他就是原生dom的事件对象e
<!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> <div id="app"> <p>count的值是{{count}}</p> <!-- 如果count是偶数,则按钮背景颜色变成红色,否则取消背景颜色 --> <!-- vue提供了内置变量$event,他就是原生dom的事件对象e,不带小括号,它默认自带事件对象e,带小括号的话事件对象为$event,因为e被小括号里的值给覆盖了--> <button @click="add(1,$event)">+1</button> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', data: { count: 0 }, //methods定义事件处理函数 methods: { add(n,e){ this.count+=n //判断count的值是否为偶数 if(this.count%2 ===0){ //偶数 e.target.style.backgroundColor='red' }else{ e.target.style.backgroundColor='' } } } }) </script> </body> </html>结果演示
事件修饰符
在事件处理函数中调用event.preventDefault()或event.stopPropagation(0是非常常见的需求,这里vue提供了事件修饰符的概念,来辅助开发者放方便的对事件的触发进行控制,常见的事件修饰符如下:
<!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> <div id="app"> <!-- <a href="https://www.wangxuelong.vip" @click.prevent="show">跳转到你想看到的页面</a> --> <!-- 给a链接绑定一个click事件,同时要阻止链接的默认行为,这里用到了事件修饰符 --> <a href="https://www.wangxuelong.vip" @click.prevent="show">跳转到你想看到的页面</a> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', //methods定义事件处理函数 methods: { show(e){ //阻止链接默认跳转 // e.preventDefault(); console.log('点击了') } } }) </script> </body> </html>结果演示
按键修饰符
实际开发中,esc和enter键使用的较多。
<!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> <div id="app"> <!-- 判断用户是否按下了esc键 ,按下了就清空数据--> <input type="text" @keyup.esc="clear"> <p>按esc键清空</p> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', data: { }, //methods定义事件处理函数 methods: { clear(e){ //重置为空 e.target.value='' } } }) </script> </body> </html>结果演示
双向绑定指令
v-model指令
vue提供了v-model双向绑定指令,可以在不操作dom的前提下来对表单元素进行表单数据操作。
<!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> <div id="app"> <p>用户的名字:{{username}}</p> <input type="text" v-model="username"> <hr> <p>用户地址:{{city}}</p> <select v-model="city"> <option value="">请选择城市</option> <option value="北京">北京</option> <option value="上海">上海</option> </select> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', //5.data对象就是要渲染到页面上的数据 data: { username: 'zzl', city:'请选择城市' } }) </script> </body> </html>结果演示
v-model指令的修饰符
<!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-model修饰符</title> </head> <body> <div id="app"> <input type="text" v-model.number="n1">+<input type="text" v-model.number="n2">=<span>{{n1+n2}}</span> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', //5.data对象就是要渲染到页面上的数据 data: { n1:1, n2:2 } }) </script> </body> </html>结果演示
条件渲染指令
它用来按需控制dom的显示与隐藏,它分别有以下两个主要指令。
- v-if:它会动态的创建和移除元素,即源代码里看不到
- 如果刚进入页面,某些元素不需要首先加载,并且后期这个元素很可能也不会被展示出来,这个时候v-if性能更好,因为它时动态创建和移除。
- v-show:它只是添加样式disply:none来显示隐藏,源代码里能看到。
- 如果要频繁的切换元素的显示状态,v-show性能更好。
<!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> <div id="app"> <p v-if="flag">这是被v-if控制的元素</p> <p v-show="flag">这是被v-show控制的元素</p> <button v-on:click="ft">改为true</button> <button @click="ff">改为flase</button> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', //5.data对象就是要渲染到页面上的数据 data: { // flag为true则显示被控制的元素,否则隐藏被控制的元素 flag:true }, methods:{ ft(){ this.flag=true; }, ff(){ this.flag=false; } } }) </script> </body> </html>结果演示
v-else-if指令
它充当v-if的”else-if”块,可以连续使用,它必须和v-if指令搭配才能使用。
<!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>elseif</title> </head> <body> <div id="app"> <div v-if="type==='zzl'">渣渣龙</div> <div v-else-if="type==='wxl'">王学龙</div> <div v-else="type==='ll'">龙</div> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', //打开开发者工具控制type data: { type:'zzl' }, }) </script> </body> </html>结果演示
列表渲染指令
v-for是基于一个数组来循环渲染一个列表结构。它还支持一个可选的第二个参数,即当前项的索引,语法格式为(item,index) in list。
<tr v-for="(item,index) in list" :key="item.id"> 只要用到了v-for指令,那么一定要绑定一个:key属性,既提升性能,又防止列表状态紊乱。 尽量把id(字符串或者数字类型)作为key的值,且不能重复。 避免使用index索引当作key值,因为index相较于与值的绑定,它就不具有唯一性。
<!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> <link rel="stylesheet" href="./bootstrap.css"> </head> <body> <div id="app"> <table class="table table-bordered table-hover"> <thead> <th>索引</th> <th>id</th> <th>姓名</th> </thead> <tbody> <!-- 在tr身上也可访问到item --> <!-- <tr v-for="(item) in list" :title="item.name"> --> <!-- 官方建议:只要用到了v-for指令,那么一定要绑定一个:key属性 --> <!-- 尽量把id(字符串或者数字类型)作为key的值,且不能重复 --> <tr v-for="(item,index) in list" :key="item.id"> <td>{{index}}</td> <td>{{item.id}}</td> <td>{{item.name}}</td> </tr> </tbody> </table> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', data: { list:[ {id:1,name:'zzl'}, {id:2,name:'wxl'}, {id:3,name:'ll'} ] } }) </script> </body> </html>、结果演示
案例
需求,做一个动态列表,可以通过状态来控制是否可以被删除,可以添加数据。利用双向绑定、条件渲染、列表渲染来实现,具体代码如下。
<script> const vm = new Vue({ el: '#app', data: { nextId:4, brand:'', list: [ { id: 1, flag:true, name: 'zzl' }, { id: 2, flag:false,name: 'wxl' }, { id: 3, flag:true,name: 'll' } ], }, methods:{ add(){ if(this.brand===''){ return alert('不能输入空') } this.list.push({id:this.nextId,flag:true,name:this.brand}) this.nextId++ }, remove(id){ this.list=this.list.filter(row=>row.id!==id) } } }) </script>结果演示
过滤器
在vue3中已经删去了过滤器,所以本篇文章只记个基础的笔记。过滤器常用语文本的格式化,它可以用在插值表达式和v-bind属性绑定上,而且过滤器应该添加到表达式的尾部,由管道符把表达式传给过滤器函数内部。
<!-- 通过管道符把message传给capitalize过滤器并调用,对message的值进行格式化 --> <p>{{message | capitalize}}</p>
私有过滤器
只在当前vue实例中使用。
<!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> <div id="app"> <p>h变成大写字母:{{message | daxie}}</p> </div> <script src="./vue-2.6.12.js"></script> <script> const vm = new Vue({ el: '#app', data: { message:'h' }, //过滤器函数必须定义到filters节点下 filters:{ //mes就是管道符前面的message daxie(mes){ //一定要有一个返回值 return mes.charAt(0).toUpperCase() } } }) </script> </body> </html>
全局过滤器
如果希望在多个vue实例之间共享过滤器,需要定义全局过滤器。
<!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> <div id="app"> <p>h变成大写字母:{{message | daxie}}</p> </div> <div id="app2"> <p>g变成大写字母:{{message | daxie}}</p> </div> <script src="./vue-2.6.12.js"></script> <script> // 全局过滤器 // Vue.filter()方法接收两个参数, // 第一个是全局过滤器的名字,第二个是过滤器的v处理函数 Vue.filter('daxie', (mes) => { return mes.charAt(0).toUpperCase() }) const vm = new Vue({ el: '#app', data: { message:'h' } }) const vm2 = new Vue({ el: '#app2', data: { message:'g' } }) </script> </body> </html>结果演示
message会传给第一个过滤器,第一个过滤器return的结果会传给第二个过滤器pipei <p>h变成大写字母:{{message | daxie | pipei}}</p>
<p>{{message | daxie(age1,age2)}}</p> ///////////////////////////////////// Vue.filter('daxie',(mes,arg2,arg2))
动画与过渡
动画
<template> <div> <button @click="isShow=!isShow">显示/隐藏</button> <!-- appear首次进入就有动画效果 --> <transition name="zzlActive" :appear="true"> <h1 v-show="isShow">zzl</h1> </transition> </div> </template> <script> export default { name:'Act', data(){ return{ isShow:true } } } </script> <style scoped> h1{ background-color: blue; } .zzlActive-enter-active{ animation: act 1s; } .zzlActive-leave-active{ /* reverse就是反向 */ animation: act 1s reverse; } @keyframes act{ from{ //类似从-100像素到0像素 transform: translateX(-100%); } to{ transform: translateX(0px); } } </style>
过渡
<template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition-group可以针对里面有多个过渡,必须指定key --> <transition-group name="zzl" :appear="true"> <h1 v-show="isShow" key="1">wxl</h1> <h1 v-show="isShow" key="2">ll</h1> </transition-group> </div> </template> <script> export default { name: 'Act', data() { return { isShow: true } } } </script> <style scoped> h1 { background-color: blue; transition: 0.5s; } /* 进入的起点 离开的终点*/ .zzl-enter ,.zzl-leave-to { transform: translateX(-100%); } /* 进入和离开的整个过程 */ /* .zzl-enter-active,.zzl-leave-active{ transition: 1s; } */ /* 进入的终点 离开的起点*/ .zzl-enter-to, .zzl-leave { transform: translateX(0); } </style>
引入第三方动画库
<!--https://animate.style/--> <template> <div> <button @click="isShow = !isShow">显示/隐藏</button> <!-- transition-group可以针对里面有多个过渡,必须指定key --> <transition-group name="animate__animated animate__bounce" enter-active-class="animate__swing" leave-active-class="animate__swing" :appear="true" > <h1 v-show="isShow" key="1">wxl</h1> <h1 v-show="isShow" key="2">ll</h1> </transition-group> </div> </template> <script> import 'animate.css' export default { name: 'Act', data() { return { isShow: true } } } </script> <style scoped> h1 { background-color: blue; transition: 0.5s; } </style>