vuejs学习三:v-on、v-if、v-for

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可以用上面的过滤器进行¥符号添加和保留两位小数。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值