Vue语法基础

文章目录

  • 模板语法
    • 插值:mustache语法
      • v-once
    • v-bind
      • 案例:v-bind绑定class
      • 案例:v-bind结合v-for实现一个小需求
      • 案例:v-bind绑定style
  • 计算属性与侦听器
    • 计算属性:computed
      • 计算属性的setter和getter方法
      • 计算属性和methods对比
    • 侦听器:watch
  • Class和Style绑定
  • 条件渲染
    • `v-if`、`v-else-if`、`v-else`
      • 案例:切换登陆方式
    • v-show
  • 列表渲染
    • v-for
      • :key属性
  • 事件处理
    • 监听事件:`v-on:`
      • 冒泡问题:`.stop`修饰符
      • 阻止默认事件`.prevent`修饰符
      • `keyup/keydown`事件与`.enter`修饰符
      • `.once`修饰符
  • 表单输入绑定
    • v-model
    • 绑定radio
    • 绑定checkbox
    • 绑定select
    • 修饰符
  • 购物车实战

模板语法

插值:mustache语法

数据绑定最常见的形式就是使用Mustache语法 (双大括号) 的文本插值

<span>Message: {
    { msg }}span>
<span>Message: {
    { Firstname+lastName }}span>

插值表达式,可以是一个变量,也可以是一个表达式,可以进行简单的计算

但一般不推荐这么干,Vue中有更优雅的实现方式

v-once

<div id=app>
  <h1 v-once>{
    {message}}h1>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue'
    }
  })
script>

v-once修饰后,{ {message}}只会在初始化获取一次值,后续message的变化,不会影响dom中的数据展示

v-bind

有了插值表达式,可以让dom标签的内容实现动态化,但是我们想让dom标签的属性动态化该怎么办?

我们使用v-bind,将dom标签的属性进行绑定,实现动态

<div id=app>
  <img src="imgUrl" alt="测试">
  <img v-bind:src="imgUrl" alt="测试">
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      imgUrl: 'http://tuchuang.zhangln.com/xbVhJM.png'
    }
  })
script>

实际被浏览器解析的html如下

Vue语法基础_第1张图片

因为使用了v-bind指令,src的值可以动data中获取了

  • 缩写

测试可以缩写成测试

v-bind是可以省略的,保留:即可

案例:v-bind绑定class


<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js">script>
  <title>Documenttitle>
  <style>
    .active1 {
      
      color: red;
    }

    .active2 {
      
      color: gold;
    }
  style>
head>
<body>
<div id=app>
  <h2 :class="active">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      active: 'active1'
    }
  })
script>
body>
html>

通过修改active的值,动态的将不同的样式绑定到了h2标签

  • 对象语法
<div id=app>
  <h2 :class="{active1:isActive1,active2:isActive2}">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      isActive1: true,
      isActive2: false
    }
  })
script>

active1active2是两个样式,通过isActive1和isActive2的布尔值,确定是否需要将对应的样式添加上来。

如果一次性将一个json对象添加在class上,代码有点复杂,我们可以使用计算属性(computed,后续讲到)或methods中

<div id=app>
  <h2 :class="getClass()">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      isActive1: true,
      isActive2: false
    },
    methods: {
      
      getClass: function () {
      
        return {
      active1: this.isActive1, active2: this.isActive2};
      }
    }
  })
script>

当我们的需求中,需要对一个元素不停的切换样式的时候,就可以使用这种办法。

  • 数组语法

作用和对象语法一样,用的比较少,我们来简单做个演示

<div id=app>
  <h2 :class="classes">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      classes:['active1','active2']
    }
  })
script>

相当于把两个样式都绑定给了标签

与对象语法一样,数组语法也可以使用计算属性或methods获取

案例:v-bind结合v-for实现一个小需求

需求:在用v-for生成的列表中,点击哪个元素,哪个元素就变色

<body>
<div id=app>
  <ul>
    <li v-for="(item,index) in movies" @click="changeClass(index)" :class="getClass(index)">{
    {index}} - {
    {item}}li>
  ul>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      movies: ['海王', '海尔兄弟', '火影忍者', '进击的巨人'],
      isActive: [false, false, false, false]
    },
    methods: {
      
      getClass: function (index) {
      
        console.log('计算' + index + '的class');
        return {
      active1: this.isActive[index]};
      },
      changeClass: function (index) {
      
        console.log('点击了' + index);
        console.log('当前配置:' + this.isActive);
        //数组的深拷贝
        let newIsActive = JSON.parse(JSON.stringify(this.isActive));
        for (let i = 0; i < newIsActive.length; i++) {
      
          newIsActive[i] = i == index ? true : false;
        }
        console.log('新的配置:' + newIsActive);
        this.isActive = newIsActive;
      }
    }
  })
script>
body>
  • 更简洁的写法
<div id=app>
  <ul>
    <li v-for="(item,index) in movies" @click="changeClass(index)" :class="getClass(index)">{
    {index}} - {
    {item}}li>
  ul>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      movies: ['海王', '海尔兄弟', '火影忍者', '进击的巨人'],
      currentIndex: -1
    },
    methods: {
      
      getClass: function (index) {
      
        return index == this.currentIndex ? {
      active1: true} : {
      active1: false};
      },
      changeClass: function (index) {
      
        this.currentIndex = index;
      }
    }
  })
script>

案例:v-bind绑定style

  • 对象语法
<h2 :style="{
        fontSize:'50px'}">{
    {message}}h2>
<div id=app>
  <h2 :style="{
        fontSize:finalSize+'px'}">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      finalSize: 50
    }
  })
script>

觉得style属性太长了的话,可以抽取成方法

<div id=app>
  <h2 :style="getStyles()">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      finalSize: 50
    },
    methods: {
      
      getStyles: function () {
      
        return {
      fontSize: this.finalSize + 'px'};
      }
    }
  })
script>
  • 数组语法
<div id=app>
  <h2 :style="[style1,style2]">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      style1: {
      fontSize: this.finalSize + 'px'},
      style2: {
      backgroundColor: 'red'},
    }
  })
script>

这个数组语法,就和绑定class的数组语法非常像了,只不过class的时候,每个数组元素是一个class样式,这里的每个数组元素是一个对象类型的内联样式

计算属性与侦听器

计算属性:computed

<body>
<div id=app>{
    {fullName}}div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      firstName: '张',
      lastName: '三'
    },
    computed: {
      
      fullName: function () {
      
        return this.firstName + this.lastName;
      }
    }
  })
script>

当插值表达式中的结果计算逻辑比较复杂的时候,就可以使用计算属性

计算属性的setter和getter方法

每个计算属性其实都包含了一个setter和getter方法

上例中,我们就使用了getter方法来进行读取,有时候也可以提供setter方法进行设置

<div id=app>{
    {fullName}}div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      firstName: '张',
      lastName: '三'
    },
    computed: {
      
      fullName: {
      
        get() {
      
          console.log("调用了get");
          return this.firstName + " " + this.lastName;
        },
        set(newValue) {
      
          console.log("调用了set");
          const names = newValue.split(" ");
          this.firstName = names[0];
          this.lastName = names[1];
        }
      }
    }
  })
script>

setter方法会在设置fullName值的时候被调用

计算属性和methods对比

  • 计算属性会监控所依赖的数据的值是否发生了变化,只有变化了,才会执行计算
  • methods每次模板编译都会执行。只要有响应式属性改变,视图刷新,函数就执行

侦听器:watch

虽然计算属性在大多数情况下更合适,但有时也需要一个自定义的侦听器。这就是为什么 Vue 通过 watch 选项提供了一个更通用的方法,来响应数据的变化。当需要在数据变化时执行异步或开销较大的操作时,这个方式是最有用的。

<div id=app>{
    {fullName}}div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      firstName: '张',
      lastName: '三',
      fullName: ''
    },
    watch: {
      
        //如果firstName发生变化,则函数执行
      firstName() {
      
        this.fullName = this.firstName + this.lastName;
      }
    }
  })
script>

Class和Style绑定

条件渲染

v-ifv-else-ifv-else

<div id=app>
  <div v-if="isA">Adiv>
  <div v-else-if="isB">Bdiv>
  <div v-else>Cdiv>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      isA: true,
      isB: false
    }
  })
script>

案例:切换登陆方式

<div id=app>
  <div v-if="showUserName">
    <input type="text" placeholder="用户名..." key="u1">
    <button>登陆button>
  div>
  <div v-else-if="showEmail">
    <input type="text" placeholder="邮箱..." key="u2">
    <button>登陆button>
  div>
  <button @click="changeLoginWay">切换button>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      showUserName: true,
      showEmail: false
    },
    methods: {
      
      changeLoginWay() {
      
        this.showUserName = !this.showUserName;
        this.showEmail = !this.showEmail;
      }
    }

  })
script>

这里为两个input设置了key,并且设置key的值不同。

是为了不想让Vue复用input。

这里的原理性解释涉及到Vue的虚拟DOM,后续再说

v-show

<div id=app>
  <h2 v-show="isShow">{
    {message}}h2>
div>
<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      message: 'Hello Vue',
      isShow: false
    }
  })
script>
  • v-show与v-if比较

与v-if类似,v-show也可以用于决定元素的显示与否,但是实现形式是不同的。

v-if是对dom的操作,是在增删dom节点,v-show只是操作

Hello Vue

为元素设置一下内联样式而已

当页面元素显示与隐藏频繁切换的时候,建议使用v-show,如果是一次性操作,则选择使用v-if

列表渲染

v-for

<div id=app>
  <ul>
    <li v-for="item in names">{
    {item}}li>
  ul>
div>

<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      names: ['中国', '美国', '英国']
    }
  })
script>
  • 获取索引值
<li v-for="(item,index) in names">{
    {index}} - {
    {item}}li>
  • 遍历对象
<div id=app>
  <ul>
    <li v-for="(item,key) in info">{
    {key}} - {
    {item}}li>
  ul>
div>

<script>
  let app = new Vue({
      
    el: '#app',
    data: {
      
      info: {
      
        name: 'why',
        age: 18,
        height: 1.88
      }
    }
  })
script>

key就是对象的属性名,item就是对象属性的值

:key属性

官方推荐,使用v-for的时候,为对应的元素或组件添加上一个:key属性,

为节点做一个唯一标识。

在Vue虚拟DOM的Diff算法中会用到。

可以帮助更高效的更新虚拟DOM

  • { {key}} - { {item}}
  • 注意,不要用index作为:key的值

    事件处理

    监听事件:v-on:

    v-on:可以简写为@

    <div id="example-2">
      
      <button v-on:click="greet">Greetbutton>
    div>
    
    <script>
        var example2 = new Vue({
          
          el: '#example-2',
          data: {
          
            name: 'Vue.js'
          },
          // 在 `methods` 对象中定义方法
          methods: {
          
              //可以简写为greet(){......}
            greet: function (event) {
          
              // `this` 在方法里指向当前 Vue 实例
              alert('Hello ' + this.name + '!')
              // `event` 是原生 DOM 事件
              if (event) {
          
                alert(event.target.tagName)
              }
            }
          }
        })
    script>
    
    • 获取事件参数

    上述案例中,我们没有传递event参数,但是function中是可以使用的

    可是,如果我们需要传递普通参数,同时也要获取event,那该怎么办?

    答案:greet(args,$event)

    冒泡问题:.stop修饰符

    <div id=app>
      <div @click="divClick">
        哇哈哈
        <button @click="btnClick">点我呀button>
      div>
    div>
    <script>
      let app = new Vue({
          
        el: '#app',
        data: {
          
          message: 'Hello Vue'
        },
        methods: {
          
          divClick() {
          
            console.log("div被点击了");
          },
          btnClick() {
          
            console.log("button被点击了");
          }
        }
      })
    script>
    

    在这段代码中,如果点击了button,div上的click也是会被触发的,怎么办呢?

    答案:添加.stop修饰符:

    除了.stop修饰符外,还有很多修饰符可以支持

    阻止默认事件.prevent修饰符

    比如对于submit类型的input,默认是会提交表单的

    <div id=app>
      <form>
        <input type="submit" value="提交" @click.prevent="submitClick">
      form>
    div>
    <script>
      let app = new Vue({
          
        el: '#app',
        data: {
          
          message: 'Hello Vue'
        },
        methods: {
          
          divClick() {
          
            console.log("div被点击了");
          },
          btnClick() {
          
            console.log("button被点击了");
          },
          submitClick() {
          
            console.log("点击提交");
          }
        }
      })
    script>
    

    用了修饰符后,就不会自动提交表单了

    keyup/keydown事件与.enter修饰符

    监听按键按下与弹起,

    <div id=app>
      <input type="text" @keyup="keyClickUp">
    div>
    <script>
      let app = new Vue({
          
        el: '#app',
        data: {
          
          message: 'Hello Vue'
        },
        methods: {
          
          divClick() {
          
            console.log("div被点击了");
          },
          btnClick() {
          
            console.log("button被点击了");
          },
          submitClick() {
          
            console.log("点击提交");
          },
          keyClickUp() {
          
            console.log("点击了按键");
          }
        }
      })
    script>
    

    如果只想监听回车键,则

    还可以设置要监听的键的代码,如

    .once修饰符

    <button @click.once="btnClick">按钮button>
    

    事件仅被触发一次

    表单输入绑定

    v-model

    你可以用 v-model 指令在表单