本节讲了Vue基础语法的使用,包括插值语法、动态绑定属性(v-bind)、计算属性(computed)、事件监听(v-on)、条件判断(v-if…)、v-if和v-show的不同、循环遍历(v-for)、过滤器的使用以及双向绑定(v-model)
插值语法
mustache
Vue.js 使用了基于 HTML 的模板语法,允许开发者声明式地将 DOM 绑定至底层 Vue 实例的数据。所有 Vue.js 的模板都是合法的 HTML,所以能被遵循规范的浏览器和 HTML 解析器解析。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| <div id="app"> <h1>{{message}}</h1> <h2>{{a + b}}</h2> <h2>{{a + ' ' + b}}</h2> <h2>{{a + '' + b}}</h2> <h2>{{c * 6}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊', a: 1, b: 2, c: 3, } }) </script>
|
效果
其它
- v-once:只显示第一次的数据
- v-text:解析为文本,同mustache
- v-html:解析为html
- v-cloak:等解析完后再显示数据
- v-pre:不解析mustache语法
动态绑定属性(v-bind)
作用:v-bind用于动态绑定一个或多个属性值,或者向另一个组件传递props值(这个学到组件时再介绍)
缩写::
预期:any (with argument) | Object (without argument)
参数:attrOrProp (optional)
动态绑定src以及href
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div id="app"> <img v-bind:src="imgUrl" alt="" width="500px"> <a v-bind:href="url">Dong</a> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> var app = new Vue({ el: '#app', data: { imgUrl: 'https://ypigy.gitee.io/img/code.jpg', url: 'https://ypigy.gitee.io/' } })
|
动态绑定class(对象语法)
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="app"> <h2 v-bind:class="a()">{{message}}</h2> <button v-on:click='change'>点我变色</button> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> var app = new Vue({ el: '#app', data: { message: '你好哦', ispink: true, isblue: false }, methods: { change: function(){ this.ispink = !this.ispink }, a: function(){ return {pink:this.ispink,blue:this.isblue} } } }) </script>
|
动态绑定class(数组语法)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <div id="app"> <h2 :class='[a,b]'>{{message}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> var app = new Vue({ el: "#app", data: { message: "你好啊", a: 'aaa', b: 'bbb' } }) </script>
|
动态绑定style
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div id="app"> <h2 :style="{color: c, fontSize: s}">{{message}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> var app = new Vue({ el: '#app', data: { message: "你好", c: 'skyblue', s: '100px' } }) </script>
|
计算属性
简介:一般情况下,我们会使用插值语法将我们要展示的值渲染到页面,但有时候我们可能需要对一些数据进行相应的计算后再显示,这个时候我们就可以用实例化的Vue对象中定义一个computed属性中去定义详细的方法
简单计算属性
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <div id="app"> <h2>{{firstName}} {{lastName}}</h2> <h2>{{firstName + " " + lastName}}</h2> <h2>{{fullname}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '#app', data: { firstName: 'z', lastName: 'yy' }, computed: { fullname: function() { return this.firstName + ' ' + this.lastName } } }) </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
| <div id="app"> <h2>总价格{{totalPrice}}</h2> </div> <script src='../node_modules/vue/dist/vue.min.js'></script> <script> const app = new Vue({ el: '#app', data: { fruits: [{ id: 100, name: '苹果', price: 6 }, { id: 101, name: '菠萝', price: 10 }, { id: 102, name: '西瓜', price: 5 }, { id: 103, name: '栗子', price: 15 }, { id: 104, name: '百香果', price: 12 }, ] }, computed: { totalPrice: function() { let total = 0 total = this.fruits.reduce((accumulator, currentValue) => { return accumulator + currentValue.price }, 0) return total } } }) </script>
|
计算属性的setter和getter以及缓存
- 每个计算属性都包含一个getter和一个setter
- 使用getter来读取
- 在某些情况下也可以提供一个setter方法(不常用)
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="app"> <h2>{{totalprice}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> var app = new Vue({ el: '#app', data: { a: 'aaa', b: 'bbb', }, computed: { totalprice: { get: function(){ return this.a + ' ' + this.b }, set: function(c){ let d = c.split(' ') this.a = d[0] this.b = d[1] } } } }) </script>
|
事件监听
v-on介绍
作用:绑定事件监听器
缩写:@
预期:Function | Inline Statement | Object
参数:event
v-on基础
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
| <body> <div class="app"> <h1>{{message}}</h1> <button v-on:click="message ++">+</button> <button v-on:click="reduce">-</button> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '.app', data:{ message: 12, }, methods:{ reduce(){ this.message -- } }, }) </script> </body>
|
v-on参数
- 当形参没有定义时,动态绑定的事件名可以不加括号
- 当形参定义后,不加括号则会默认绑定windows创建的event对象,如若加括号没定义参数则会返回underfinde
- 当有参数且需要定义实参,同时需要用到windows创建的event对象,则使用$event定义
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
| <body> <div id="app">
<button @click="hhh(123,$event)">点我爱</button> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '#app', methods: { hhh(abc,e){ console.log(abc,e) } } }) </script> </body>
|
v-on修饰符
- 阻止事件冒泡:.stop
- 阻止默认事件:.prevent
- 监听键盘按键:{.keyCode,.keyAlies}
- 只触发一次回调:.once
- 监听组件根元素的原生事件:.native
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
| <body> <div id="app" @click="d"> 啦啦啦啦啦 <button @click.stop='c'>点我</button>
<form action="dong"> <input type="submit" @click.prevent='e'> </form>
<input type="text" @keyup.space='f'>
<button @click.once='c'>我只能点一次</button>
</div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '#app', methods: { c() { console.log('ccc') }, d() { console.log('ddd') }, e(){ console.log('aaa') }, f(){ console.log('你键入了空格') } } }) </script> </body>
|
条件判断
v-if、v-else-if、v-else
案例1(布尔判断)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div id="app"> <h1 v-if="ifTrue">我是一</h1> <h1 v-else>我是二</h1> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { ifTrue: false } }) </script>
|
案例2(成绩判断器)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div id="app"> <h1 v-if="score >= 80">优秀</h1> <h1 v-else-if="score >= 60">良好</h1> <h1 v-else>不及格</h1> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { score: 80 } }) </script>
|
登录切换案例以及问题
实现按钮切换登陆方式(用户名-邮箱)
- 定义初步页面
- 为不同输入框进行条件判断(v-if、v-else)
- 若条件为true,则使用用户名
- 条件为false,则使用邮箱
- 为切换按钮绑定事件,动态改变条件(v-on)
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
| <div id="app"> <span v-if="isTrue"> <h5>请输入用户名</h5> <input type="text" placeholder="请输入用户名"> </span> <span v-else> <h5>请输入邮箱</h5> <input type="text" placeholder="请输入邮箱"> </span> <button @click="c">切换登录方式</button> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { isTrue: true, }, methods: { c(){ this.isTrue = !this.isTrue } } }) </script>
|
出现的小问题:
如果我们在有输入内容的情况下,切换了类型,我们会发现文字依然显示之前的输入的内容。
但是按道理讲,我们应该切换到另外一个input元素中了。
在另一个input元素中,我们并没有输入内容。
为什么会出现这个问题呢?
问题解答:
这是因为Vue在进行DOM渲染时,出于性能考虑,会尽可能的复用已经存在的元素,而不是重新创建新的元素。
在案例中,Vue内部会发现原来的input元素不再使用,直接作为else中的input来使用了。
解决方案:
如果我们不希望Vue出现类似重复利用的问题,可以给对应的input添加key
并且我们需要保证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
| <div id="app"> <span v-if="isTrue"> <h5>请输入用户名</h5> <input type="text" placeholder="请输入用户名" key="username"> </span> <span v-else> <h5>请输入邮箱</h5> <input type="text" placeholder="请输入邮箱"> </span> <button @click="c">切换登录方式</button> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { isTrue: true, }, methods: { c(){ this.isTrue = !this.isTrue } } }) </script>
|
v-show
v-show的用法和v-if非常相似,也用于决定一个元素是否渲染:
v-if和v-show对比
v-if和v-show都可以决定一个元素是否渲染
v-if当条件为false时,压根不会有对应的元素在DOM中。
v-show当条件为false时,仅仅是将元素的display属性设置为none而已。
开发中的选择
当需要在显示与隐藏之间切换很频繁时,使用v-show
当只有一次切换时,通过使用v-if
案例
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div id="app"> <h1 v-show="a">你好啊</h1> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data:{ a: false } }) </script>
|
遍历循环
v-for遍历数组
v-for=”(项, 索引号) in 数组”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| <div id="app"> <ul> <li v-for="item in fruits">{{item}}</li> <li v-for="(item, index) in fruits">{{++index +'-'+item}}</li> </ul> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { fruits:['火龙果','橙子','香蕉','西瓜','栗子','苹果'] } }) </script>
|
v-for遍历对象
v-for=”(值, 键, 索引) in 对象”
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| <div id="app"> <ul> <li v-for="item in fruits">{{item}}</li> <li v-for="(item, key) in fruits">{{key +'-'+item}}</li> <li v-for="(item, key, index) in fruits">{{++index + '-'+key +'-'+item}}</li> </ul> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { fruits: { name: "火龙果", qualityGuaranteePeriod: "30天", producingArea: "China" } } }) </script>
|
组件的key属性
作用:key的作用主要是为了高效的更新虚拟DOM
为什么需要key属性
这个其实和Vue的虚拟DOM的Diff算法有关系。
这里我们借用React’s diff algorithm中的一张图来简单说明一下:
当某一层有很多相同的节点时,也就是列表节点时,我们希望插入一个新的节点
我们希望可以在B和C之间加一个F,Diff算法默认执行起来是这样的。即把C更新成F,D更新成C,E更新成D,最后再插入E,是不是很没有效率?
而如果有key属性,则每个值会与对应的key属性一一绑定,那么这个默认算法也就不再执行,而是通过像键值对一样的方式去匹配这些数据,保证代码的高效率
🔺vue中的数据是响应式的
因为Vue是响应式的,所以当数据发生变化时,Vue会自动检测数据变化,视图会发生对应的更新。
🔺根据索引修改数组数据是不能成功的,要么通过vue自带方法Vue.set(修改对象,修改索引,修改后的值)去修改数组数据,要么使用splice()方法修改
Vue中包含了一组观察数组编译的方法,使用它们改变数组也会触发视图的更新
- push()
- pop()
- shift()
- unshift()
- splice()
- sort()
- reverse()
splice()
简介:可以删除、修改、替换元素
格式:目标数组.splice(开始索引位置,删除(替换)元素个数,…元素(插入替换的元素))
过滤器
filters 官网介绍
作用:用于一些常见的文本格式化(过滤到你做想要的数据结果格式)
在html中定义过滤器
1
| <td>{{item.price | price}}</td>
|
vue对象中编写过滤器的具体实现方法
1 2 3 4
| filters: { price(p) { return '¥' + p.toFixed(2) }
|
v-model
前言: 表单控件在实际开发中是非常常见的。特别是对于用户信息的提交,需要大量的表单。
作用:Vue中使用v-model指令来实现表单元素和数据的双向绑定。
简单使用
当我们使用text控件并绑定某个数据时,修改text的输入内容时,相应的,这个数据也会被修改,同时,这个修改完后的数据也可以在其他地方渲染出来,这个时候,就实现了双向绑定
1 2 3 4 5 6 7 8 9 10 11 12 13
| <div id="app"> <input type="text" v-model="message"> <h2>{{message}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊' } }) </script>
|
原理(v-on结合v-bind)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <div id="app"> <input type="text" :value="message" v-on:input="change"> <h2>{{message}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '#app', data: { message: '你好啊' }, methods: { change(event) { this.message = event.target.value } } }) </script>
|
结合radio使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <div id="app"> <label for="male"> <input type="radio" name="sex" value="男" id="male" v-model="sex">男 </label> <label for="female"> <input type="radio" name="sex" value="女" id="female" v-model="sex">女 </label> <h2 v-if="sex.length === 1">你选择的性别是{{sex}}</h2> <h2 v-else>{{sex}}</h2>s </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: '#app', data: { sex: '请选择你的性别', }, }) </script>
|
结合checkbox使用
- 单个勾选框
- v-model即为布尔值。
- input的value并不影响v-model的值。
- 多个勾选框
- 当是多个复选框时,因为可以选中多个,所以对应的data中属性是一个数组
- 当选中某一个时,就会将input的value添加到数组中
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
| <div id="app"> <label for="agree"> <input type="checkbox" v-model="isAgree" id="agree">同意协议 </label> <h2>你选择的是{{isAgree}}</h2> <button :disabled="!isAgree">注册</button> </div>
<div id="app"> <input type="checkbox" v-model="fruits" value="苹果">苹果 <input type="checkbox" v-model="fruits" value="栗子">栗子 <input type="checkbox" v-model="fruits" value="李子">李子 <input type="checkbox" v-model="fruits" value="梨子">梨子 <input type="checkbox" v-model="fruits" value="橙子">橙子 <input type="checkbox" v-model="fruits" value="哈密瓜">哈密瓜 <h2>你选择的水果是{{fruits}}</h2> </div>
<script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { isAgree: false, fruits: [] } }) </script>
|
结合select使用
- 单选
- v-model绑定的是一个值。
- 当我们选中option中的一个时,会将它对应的value赋值到mySelect中
- 注意定义的位置
- 多选
- v-model绑定的是一个数组。
- 当选中多个值时,就会将选中的option对应的value添加到数组mySelects中
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
| <div id="app"> <select v-model="fruit"> <option value="苹果">苹果</option> <option value="梨子">梨子</option> <option value="西瓜">西瓜</option> <option value="香蕉">香蕉</option> <option value="桃子">桃子</option> <option value="哈密瓜">哈密瓜</option> </select> <h5 id="a">你选择的水果是{{fruit}}</h5> <select v-model="fruits" multiple> <option value="苹果">苹果</option> <option value="梨子">梨子</option> <option value="西瓜">西瓜</option> <option value="香蕉">香蕉</option> <option value="桃子">桃子</option> <option value="哈密瓜">哈密瓜</option> </select> <h5 id="b">你选择的水果是{{fruits}}</h5>
</div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { fruit: '香蕉', fruits: [] } }) </script>
|
值绑定
根据已有数据去渲染页面的同时,动态绑定这些数据
就是v-bind动态绑定值,同时,使用v-model双向绑定
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <div id="app"> <label v-for="item in fruits" :for="item"> <input type="checkbox" :value="item" :id="item" v-model="fruits">{{item}} </label> <h5>你选择了{{fruits}}水果</h5> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { fruits:['火龙果','橙子','香蕉','西瓜','栗子','苹果'] } }) </script>
|
v-model修饰符
lazy修饰符:
- 默认情况下,v-model默认是在input事件中同步输入框的数据的。
- 一旦有数据发生改变对应的data中的数据就会自动发生改变。
- lazy修饰符可以让数据在失去焦点或者回车时才会更新:
number修饰符:
- 默认情况下,在输入框中无论我们输入的是字母还是数字,都会被当做字符串类型进行处理。
- 但是如果我们希望处理的是数字类型,这个就可以直接将内容当做数字处理。
- number修饰符可以让在输入框中输入的内容自动转成数字类型:
trim修饰符:
- 如果输入的内容首尾有很多空格,通常我们希望将其去除
- trim修饰符可以过滤内容左右两边的空格
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22
| <div id="app"> <input type="text" v-model.lazy="message"> <h2>{{message}}</h2> <input type="number" v-model.number="num"> <h2>{{typeof num}}</h2> <input type="text" v-model.trim="hi"> <h2>{{hi}}</h2> </div> <script src="../node_modules/vue/dist/vue.min.js"></script> <script> const app = new Vue({ el: "#app", data: { message: "你好啊", num: 16, hi: "hhhhh" } }) </script>
|