v-on,v-if,v-for
1 v-on
1.1 参数
如果不需要传参 v-on绑定的方法的参数可以不写
当省略括号时,绑定的方法可以接收页面的event作为形参
<div id="app">
<h1 @click="test1">123</h1>
<!--不省略小阔号是无法获得event参数的-->
<h1 @click="test1()">123</h1>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '您好'
},
methods: {
test1(event) {
console.log(event);
console.log(1);
}
}
})
</script>
那么如何手动的传入event参数呢?
<h1 @click="test1(123,$event)">222</h1>
1.2 修饰符
@click.stop 修饰符阻止冒泡
<body>
<div id="app">
<h1 @click="test1">111
<button @click.stop="test2">222</button>
</h1>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const app = new Vue({
el: '#app',
data: {
message: '您好'
},
methods: {
test1() {
console.log(1);
},
test2() {
console.log(2);
}
}
})
</script>
@click.prevent 可以阻止元素的默认事件,例如下面的默认提交按钮
<form action="baidu">
<button type="submit" @click.prevent="test3">按钮</button>
</form>
@keyup.enter @keyup监听所有键帽抬起事件,加上enter只监听回车事件
<!-- 监听键盘点击-->
<input type="text" @keyup.enter="test3">
native 监听组件事件
@click.once 只有点击第一次才触发
2 v-if else等
v-if的一个作用是控制元素是否显示出来
<body>
<div id="app">
<h2 v-if="isShow">
<p>{{message}}</p>
<p>{{message}}</p>
<p>{{message}}</p>
</h2>
<h1 v-else>isShow 为 false 显示我</h1>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
message:'您好',
isShow:true
}
})
</script>
如果逻辑比较复杂,还是在methods或者计算属性中实现比较好。
2.1 案例
需求:点击按钮,前面的登录框从用户名登录变成邮箱登录
<body>
<div id="app">
<div v-if="btnFlag">用户名登录:<input type="text" placeHolder="用户名登录"></div>
<div v-else>邮箱登录:<input type="text" placeHolder="邮箱登录"></div>
<button @click="btnFlag=!btnFlag">点我切换</button>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
btnFlag:true
},
})
</script>
这个案例有个小问题,当我们在input框中输入数据,再点击切换后input中输入的值并不会改变。按理说这两个input都不是同一个input了,怎么回事呢?
vue的标签会先放到内存里面,我们一般称之为虚拟dom,在进行dom渲染时会尽可能复用已经存在的元素,而不是再创建个新的。vue发现原来的input元素不再使用,就拿来做else中的input了。
解决:给对应的input添加key
<div v-if="btnFlag">用户名登录:<input type="text" key="1" placeHolder="用户名登录"></div>
<div v-else>邮箱登录:<input type="text" key="2" placeHolder="邮箱登录"></div>
2.2 v-show
决定是否把元素显示出来.
v-show 和v-if 不显示元素的效果不同,v-if中不显示的元素根本就不会显示在dom中。而v-show不显示的元素只是增加了display:none 的行内元素,但是元素还是存在在dom里面。如果显示和隐藏的元素切换很频繁,使用v-show。
3 v-for
3.1 遍历对象
<div id="app">
<ul>
<li v-for="(value,key) in info">{{value}}=>{{key}}</li>
</ul>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
info:{
name:'aaa',
age:'19',
height:199
}
}
})
</script>
v-for使用时推荐绑定一个key,为什么呢?如果绑定key之后,vue在对li进行增加和删除等操作时会效率更高。
正常情况下对li进行插入操作:比如5个li内容分别为abcde,在bc之间插一个f,那么他会把原来的c替换成f,然后依次替换,这样的效率比较低。使用key之后他会比较两者的不同再进行修改和替换。
注意绑定key需要能和内容一一对应(所以不要绑定索引,因为元素数量顺序的变化会影响索引)
但是key不能有重复的。下面例子中的info为对象。
<li v-for="(value,key) in info" :key="key">{{value}}=>{{key}}</li>
3.2 数组方法中哪些是响应式
push、pop() 删除最后的元素、shift(删除第一个元素)、unshift在数组前面添加若干元素
splice(start, num…ele) 从start开始后面num个元素用ele替换,ele没输就用删除。
reverse 数组反转
注意: 使用数组下标进行数组改变是不具备响应式的。
可以使用vue的set方法
<div id="app">
<ul>
<li v-for="item in message">{{item}}</li>
</ul>
<button @click="change">改变</button>
</div>
</body>
<script src="../js/vue.js"></script>
<script>
const app=new Vue({
el:'#app',
data:{
message:["aaa","bbb",'ccc','ddd']
},
methods:{
change(){
Vue.set(this.message,0,"eee")
}
}
})
</script>
4 案例
-
加号减号,可以改变书的数量
-
总价为书价格*数量的和
-
移除将删除一整行
-
全部删除后显示购物车为空
4.1 自己写的
自己写的如下:
<style>
* {
padding: 0;
margin: 0;
user-select: none;
}
#app {
width: 700px;
margin: 50px auto;
}
table {
width: 700px;
border-collapse: collapse;
margin: auto;
}
td {
border: 1px solid #C6C6C6;
line-height: 50px;
padding: 0 15px;
}
.center {
text-align: center;
}
.header td {
background: #F6F6F6;
}
td button {
border: 1px solid grey;
padding: 0 5px;
border-radius: 1px;
outline: none;
}
.qBtn {
font-size: 12px;
margin: 2px;
border-radius: 3px;
outline: none;
background: #fff;
box-shadow: 0 1px 1px rgba(0, 0, 0, 0.2);
}
</style>
</head>
<body>
<div id="app">
<table>
<tr class="header">
<td></td>
<td>书籍名称</td>
<td>出版日期</td>
<td>价格</td>
<td class="center">购买数量</td>
<td class="center">操作</td>
</tr>
<tr v-for="(book,index) in books">
<td class="center">{{index+1}}</td>
<td>《{{book.name}}》</td>
<td>{{book.data}}</td>
<td>¥{{book.price}}</td>
<td class="center">
<button class="qBtn" @click="minusBook(index)">-</button>
{{book.quantity}}
<button class="qBtn" @click="addBook(index)">+</button>
</td>
<td class="center">
<button @click="delBook(index)">移除</button>
</td>
</tr>
</table>
<h4 v-show="books.length===0">购物车为空</h4>
总价:¥{{totalPrice}}.00
</div>
</body>
<script>
const app = new Vue({
el: '#app',
data: {
books: [
{name: "算法导论", data: "2006-9", price: 85, quantity: 1},
{name: "UNIX编程技术", data: "2006-2", price: 59, quantity: 1},
{name: "编程珠玑", data: "2008-10", price: 39, quantity: 1},
{name: "代码大全", data: "2006-3", price: 128, quantity: 1},
]
},
methods: {
minusBook(index){
if (this.books[index].quantity>0){
this.books[index].quantity--;
}
},
addBook(index){
this.books[index].quantity++;
},
delBook(index){
this.books.splice(index,1);
}
},
computed: {
totalPrice() {
if (this.books.length===0){
return 0
}else if (this.books.length===1){
return this.books[0].price*this.books[0].quantity;
}else {
return this.books.reduce(function (pre, cur,ind) {
if (ind===1){pre=pre.price*pre.quantity}
return cur.price*cur.quantity+pre;
});
}
},
isEmpty(){
return this.books.length===0;
}
}
})
</script>
4.2 对比总结
通过对比老师写的
总结如下:
- 关于table的样式 突出一个相对好看
table {
border: 1px solid #e9e9e9;
/*边框折叠*/
border-collapse: collapse;
border-spacing: 0;
}
th, td {
padding: 8px 16px;
border: 1px solid #e9e9e9;
text-align: left;
}
th {
background: #f7f7f7;
color: #5c6b77;
font-weight: 600;
}
-
关于过滤器
表中的价格保留两位小数使用 num.isFixed(2) 保留两位小数
配合vue的filter使用效果更佳,filter为option之一
过滤器,通过|符号使用,|前的东西会作为参数传到过滤器中,return的结果显示到页面
<td>{{book.price|showPrice}}</td>
filters: {
showPrice(price) {
return '¥' + price.toFixed(2);
}
- 关于减少按钮不能小于零
我的做法是在method里进行判断
还可以这样
<button @click="decrement(index)" :disabled="book.quantity <=1">-</button>
button的disabled属性为true则按钮不可以交互
- 关于总价格的计算
computed:{
totalPrice(){
let totalPrice=0;
for (let i=0;i<this.books.length;i++){
totalPrice+=this.books[i].price*this.books[i].quantity
}
return totalPrice;
}
}
正常遍历挺好的,reduce在数组长度为1时只会返回遍历的元素。计算出的totalPrice可以用上面的过滤器进行¥符号添加和保留两位小数。