Vue2学习计划五:v-on、v-model、v-if、v-for和v-show

一、v-on事件监听

1.1 v-on基本使用

我们前面学习了,{{}}和v-bind,这两货可以让我们将Vue实例中的数据绑定到DOM中。那么,产品经理又开始有奇怪的需求了,比如我们要点击按钮更换图片怎么办?怎么办呢?我们目前只会将数据绑定到DOM上,如何监听DOM里的事件,然后作用到Vue实例数据上呢?别急,这正是今天要学的v-on的主场。

产品经理太可恶,我们实现一个其他的事件监听案例,实现一个计数器。有按钮加和按钮减,然后将数值展示出来。

  <div id="app">
    <h2>{{count}}</h2>
    <button v-on:click="increment">+</button>
    <button v-on:click="decrement">-</button>
    <br>
    <button @click="count++">++</button>
    <button @click="count--">--</button>
  </div>
  <script src="./../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        count: 0
      },
      methods: {
        increment(){
          return this.count++;
        },
        decrement(){
          return this.count--;
        }
      }
    })
  </script>

代码分析:

  • 实现了v-on正常写法和更常用的语法糖写法

  • 一般v-on绑定了方法,如最上面的+和-按钮,但是运算简单时,可以直接运算,如后面++和--按钮

延伸分析(v-on参数传递问题):

上面代码里的方法都是不带参数的。点击按钮是事件监听,鼠标位置也可以是事件监听,那么怎么将DOM元素事件里的信息传递回来呢?下一节可以正是登场了。

1.2 v-on的参数传递问题

开始之前,我想请大家思考3个问题:

  1. 方法定义时没有参数,调用时(v-on绑定时)加不加括号有什么区别?

  2. 方法定义时有一个参数,事件调用时省略了方法的小括号,此时会发生什么?

  3. 方法定义时,需要传入DOM事件信息和其他参数,但是事件调用时,省略小括号会发生什么?只写一个参数会发生什么?

这种抽象的东西,我们只能上代码,然后带着上面的问题,去代码中分析,希望能将抽象具体化。下面的代码展现了同一个方法调用时加不加小括号,传不传入参数,传入浏览器事件的区别。

<div id="app">
    <h2>问题1:{{message1}}</h2>
    <button v-on:click="btn1Click">btn1</button>
    <button v-on:click="btn1Click()">btn1()</button>
    <button v-on:click="initMsg">初始化显示信息</button>
    <hr>
    <h2>问题2:{{message2}}</h2>
    <button @click="btn2Click">btn2</button>
    <button @click="btn2Click()">btn2()</button>
    <button @click="btn2Click('123')">btn2('123')</button>
    <hr>
    <h2>问题3:{{message3}}</h2>
    <button @click="btn3Click">btn3</button>
    <button @click="btn3Click()">btn3()</button>
    <button @click="btn3Click('abc')">btn3('abc')</button>
    <button @click="btn3Click('abc', $event)">btn3('abc', $event)</button>
  </div>
  <script src="./../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message1: '请点击',
        message2: '请点击',
        message3: '请点击'
      },
      methods: {
        initMsg(){
          this.message1 = '请点击';
          this.message2 = '请点击';
          this.message3 = '请点击';
        },
        btn1Click(){
          this.message1 = "btn1 clicked."
        },
        btn2Click(data){
          this.message2 = 'btn2 clicked ' + data;
        },
        btn3Click(data, event){
          this.message3 = 'btn3 clicked '+ data + ' - ' + event;
        }
      }
    })
  </script>

代码分析:

  • 方法定义时没有参数,那么调用时加不加括号都一样

  • 方法定义时有一个参数

    • 调用时不加小括号,Vue会默认将浏览器产生的event事件当作实参传入

    • 调用时只有小括号没有实参,此时在方法内部的形参为undefined

  • 方法定义时有两个参数,一个是数据,另一个是浏览器产生的事件对象

    • 调用时不加小括号,Vue会默认将浏览器产生的event事件当作第一个实参传入,第二个为undefined

    • 调用时只有小括号没有实参,在方法内部的两个形参都为undefined

    • 调用时只有一个实参,在方法内部的另一个形参为undefined

注意:

  1. 调用时,要传入浏览器的事件对象,使用$event

  2. 方法定义时有参数,调用时不加小括号,默认第一个实参为浏览器事件对象

  3. 方法定义时有参数,调用时没有传入,则都为undefined

1.3 v-on的修饰符使用

Vue总是很贴心,毕竟是一个JS框架,当然会替我们着想了。我们拿到浏览器事件对象是用来进行加工处理的,那么Vue同样提供了一些修饰符帮我们处理浏览器事件对象。

  • .stop 调用event.stopPropagation()用于阻止默认事件冒泡

  • .prevent 调用event.preventDefault()用于阻止默认事件,比如提交按钮,点击后会默认提交然后转跳,用.prevent可以阻止

  • .{keyCode | keyAlias} 当事件从特定键触发时才触发回调。keyCode指键盘的编码,用于监听键盘的事件。

  • .native 监听组件根元素的原生事件,必须用在组件中

  • .once 只触发一次

接下来放上一坨代码举例示范

 <div id="app">
<!-- 1. .stop修饰符的使用-->
  <div @click="divClick">.stop修饰符举例<button @click.stop="btnClick">.stop</button></div>

<!--  2. .prevent修饰符的使用-->
  <form action="baidu">
    <input type="submit" value="提交" @click.prevent="submitClick">
  </form>

<!--  3. 监听某个键盘的键帽,这里监听enter-->
  <input type="text" @keyup.enter="keyUp">

<!--  4. .once修饰符的使用-->
  <button @click.once="btn2Click">btn2</button>
  </div>
  <script src="./../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message: 'hello vue'
      },
      methods: {
        btnClick(){
          console.log('btn clicked.')
        },
        divClick(){
          console.log('div clicked.')
        },
        submitClick(){
          console.log("submit btn clicked")
        },
        keyUp(){
          console.log('keyUp')
        },
        btn2Click(){
          console.log('btn2 clicked.')
        }
      }
    })
  </script>

效果示例:

image-20210801164235487.png

二、v-model实现表单元素和数据的双向绑定

v-model主要用于表单元素和数据的双向绑定,使用v-model="数据",实现改变数据,表单元素也改变。

v-model其实是一个语法糖,完全可以自己实现,它本质上是包含两个操作:

  • v-bind绑定input元素的value值

  • v-on指令给当前元素绑定input事件

<div id="app">
    <h2>message:{{message}}</h2>
    <input type="text" v-model="message">
    <hr>
    <input type="text" :value="message" @input="valueChange">
    <hr>
    <input type="text" :value="message" @input="message = $event.target.value">
  </div>
  <script src="./../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message: '你好啊'
      },
      methods: {
        valueChange(e){
          this.message = e.target.value
        }
      }
    })
  </script>

代码解析:

  • :value="message"将message绑定至input元素的value属性上

  • input元素里有个input事件,用于监听用户是否输入数据

  • input="message = $event.target.value"监听input事件,然后将事件的值传递给message

2.1 v-model结合radio类型使用

使用v-model即可将输入放入数据中,然后就可以进行处理和传输

在radio多个单选框中,JS的做法是将多个radio添加name属性,并且name属性值相同,从而只能从中选一个。在Vue中,如果v-model绑定的是同一个属性,那么name属性可以删除。在Vue中实现单选框的代码如下:

<div id="app">
    <h2>你选择的性别是:{{sex}}</h2>
    <label for="male"><input type="radio" id="male" value="男" v-model="sex">男</label>
    <label for="female"><input type="radio" id="female" value="女" v-model="sex">女</label>
  </div>
  <script src="./../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        sex: '男' //如要要有默认值,则在这里定义,此时默认值为男
      }
    })
  </script>

2.2 v-model结合checkbox类型使用

checkbox有两种用法,一种是单选,一种是多选。单选绑定的是一个变量,而多选框checkbox则是绑定了一个数组。

<div id="app">
<!--  单选框使用-->
  <h2>{{message}}</h2>
  <label for="agree">
    <input type="checkbox" id="agree" v-model="isAgree">同意协议
  </label>
  <button :disabled="!isAgree">下一步</button>
  <hr>
<!--  多选框使用-->
  <label for="basketball"><input type="checkbox" value="篮球" id="basketball" v-model="hobbies">篮球</label>
  <label for="football"><input type="checkbox" value="足球" id="football" v-model="hobbies">足球</label>
  <label for="ppball"><input type="checkbox" value="乒乓球" id="ppball" v-model="hobbies">乒乓球</label>
  <label for="ymball"><input type="checkbox" value="羽毛球" id="ymball" v-model="hobbies">羽毛球</label>
  <h2>你选择的兴趣爱好是:{{hobbies}}</h2>
</div>

<script src="./../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: "hello vue",
      isAgree: false,
      hobbies: []
    }
  })
</script>

2.3 v-model修饰符的使用

v-model当然也有修饰符,总共有3个需要提一下:

  • lazy修饰符:默认情况下,v-model是在input事件中同步输入框的内容,一旦有内容发生改变,对应data中的数据就会自动发送改变,这样的机制会使得变化很快。lazy修饰符可以让数据在失去焦点或者回车时才更新。

  • number修饰符:默认情况下,输入框中的内容都会当作字符串类型进行处理,加上number修饰符后,就可以将输入框里的内容自动转为数字类型

  • trim修饰符:过滤输入框中内容左右两遍的空格

如何使用,我们还是用代码实现一下:

<div id="app">
    <h3>lazy修饰符使用</h3>
    <h3>{{message}}</h3>
    <input type="text" v-model.lazy="message">
    <hr>
    <h3>number修饰符</h3>
    <h3>{{typeof num}}-{{num}}</h3>
    <input type="text" v-model.number="num">
    <hr>
    <h3>trim修饰符</h3>
    <h3>{{showMsg}}</h3>
    <input type="text" v-model.trim="showMsg">
  </div>
  <script src="./../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message: '请输入',
        num: 0,
        showMsg: '展示空格'
      }
    })
  </script>

三、v-if条件判断

其实也就是if...else的条件判断,我印象中,我实现的两个假电商项目中,使用得较少。直接上代码了,代码实现了v-if的使用,v-if和v-else的使用,以及v-if和v-else-if和v-else的使用,最终还在计算属性中使用了v-if等条件判断

  <div id="app">
    <h2 v-if="isShow">{{message}}</h2>
    <button @click="changeView">{{show}}</button>

    <!--2.使用v-if和v-else-->
    <h2 v-if="isShow">{{message}}</h2>
    <h2 v-else>{{noMessage}}</h2>
    <button @click="changeView1">按钮</button>

    <!--3.使用v-if和v-else-if和v-else-->
    <input type="text" v-model="score">
    <h2 v-if="score>=90">优秀</h2>
    <h2 v-else-if="score>=80">良好</h2>
    <h2 v-else-if="score>=60">及格</h2>
    <h2 v-else>不及格</h2>
    <h1>{{result}}</h1>
  </div>
  <script src="./../js/vue.js"></script>
  <script>
    const app = new Vue({
      el: '#app',
      data: {
        message: 'hello vue',
        isShow: true,
        show: '不显示',
        score: 50
      },
      methods: {
        changeView(){
          this.isShow = !this.isShow
          if(this.show == '显示'){
            this.show = '不显示'
          }else
            this.show = '显示'
        },
        changeView1(){
          this.isShow = !this.isShow
        }
      },
      computed: {
        result(){
          let showMessage = ''
          if(this.score >= 90){
            showMessage = '优秀'
          }else if(this.score >= 80){
            showMessage = '良好'
          }else if(this.score >= 60){
            showMessage = '及格'
          }else{
            showMessage = '不及格'
          }
          return showMessage
        }
      }
    })
  </script>

四、v-for

一般for循环都是用来遍历的,在Vue里也是。一般用于遍历数组和对象

遍历数组时,分为两种情况,需要索引值和不需要索引值

<!--1. 不需要索引时,items是数组-->
<li v-for="item in items">{{item}}</li>
<!--2. 需要索引时,items是数组-->
<li v-for="(index, item) in items">{{index}}-{{item}}</li>

遍历对象时,有三种情况:

<!--1. v-for遍历对象,只获取value-->
<li v-for="item in obj">{{item}}</li>
<!--2. v-for遍历对象,同时获取key和value-->
<li v-for="(key, value) in obj">{{key}}-{{value}}</li>
<!--3. v-for遍历对象,获取key、value和序号值-->
<li v-for="(key, value, index) in obj">{{index+1}...{{key}}-{{value}}</li>

4.1 v-for绑定和不绑定key的区别

我们将之前先来完成一下看图描述。

1.png

第一步,我们有个一堆相同的元素ABCDE,此时想将F插入到B后面

第二步,按照DOM的算法,是将c更新成f,d更新成了c,e更新成了d这样循环下去。其实就是数组的移位思想。

第三步,这就是有没有key的对比,没有key的是左边图,有key的是右边图。有了key就能根据key来识别元素,从而达到从数组插入变成链表插入的效果。

五、v-show显示

主要用于展示元素,这里主要的问题就是和v-if的区别。毕竟v-if也可以用来展示或者隐藏元素

主要区别有以下:

  • v-if条件为false时,不会有对应的元素存在DOM中

  • v-show条件为false时,仅将元素的display属性设置为none

先来看代码使用一下:

<div id="app">
<!-- v-if:当条件为false时,包含v-if的元素,根本就不存在于dom中 -->
  <h2 v-if="isShow">{{message}}</h2>

  <!-- v-show:当条件为false时,v-show只是给我们的元素添加了一个行内样式: display:none -->
  <h2 v-show="isShow">{{message}}</h2>
</div>

<script src="./../js/vue.js"></script>
<script>
  const app = new Vue({
    el: '#app',
    data: {
      message: "hello vue",
      isShow: true
    }
  })
</script>

那么肯定有小伙伴心中会有疑惑,v-if使用范围更大,记住v-if不就行了嘛?实际上开发中,确实使用v-if的较多。但是两者还是有区别的,当需要在显示和隐藏之间切换很频繁时,使用v-show,当只有一次切换时,使用v-if。

原因就是,v-if是对元素进行销毁和创建,而v-show只是CSS状态的切换,这就是为什么显示和隐藏频繁切换时要使用v-show的原因了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342

推荐阅读更多精彩内容