Vue自学之路 笔记--2.Vue常用指令

173 阅读5分钟

Vue指令

MVVM模式设计模式

用数据驱动视图改变,不用在操作dom元素

  • MVVM,一种软件架构模式,决定了写代码的思想和层次

    • M: model数据模型 (data里定义)
    • V: view视图 (html页面)
    • VM: ViewModel视图模型 (vue.js源码)
  • MVVM通过数据双向绑定让数据自动地双向同步 不再需要操作DOM

    • V(修改视图) -> M(数据自动同步)
    • M(修改数据) -> V(视图自动同步)
  • 数据驱动思想:vue不推荐操作DOM,直接操作数据

1. 在vue中,不推荐直接手动操作DOM!!!

2. 在vue中,通过数据驱动视图,不要在想着怎么操作DOM,而是想着如何操作数据!!

3.使用vue指令,有简写的语法建议使用简写语法

1.插值表达式 {{ }}

可以在标签之中,直接插入数据内容 又名:声明式渲染 /文本插值

语法 :{{ 表达式 }}

作用:可以在视图中显示data中的数据

<template>
  <div>
    <h1>{{ msg }}</h1>
    <h2>{{ obj.name }}</h2>
    <h3>{{ obj.age > 18 ? '成年' : '未成年' }}</h3>
  </div>
</template><script>
export default {
  data() { // 格式固定, 定义vue数据之处
    return {  // key相当于变量名
      msg: "hello, vue",
      obj: {
        name: "Vue世界",
        age: 19
      }
    }
  }
}
</script><style>
</style>

总结:dom中插值表达式赋值,vue的变量必须在data中赋值

2. v-bind

给标签属性设置vue变量的值

vue 指令,实质上就是特殊的html标签属性,以v-开头

每个指令,都有独立的作用

  • 语法:v-bind:属性名=“vue变量”
  • 简写::属性名=“vue变量”
<!-- vue指令-v-bind属性动态赋值 -->
<a v-bind:href="url">我是a标签</a>
<img :src="imgSrc">

总结:把vue的变量赋值到dom标签上,改变标签效果

3.v-on

给标签绑定事件,函数一定要写在methods中

  • 语法:v-on:事件名=“要执行的代码 || 函数名 || 函数名(实参)”
  • 简写:@事件名=“要执行的代码 || 函数名 || 函数名(实参)”
<!-- vue指令:   v-on事件绑定-->
<p>你要买商品的数量: {{count}}</p>
<button v-on:click="count = count + 1">增加1</button>
<button v-on:click="addFn">增加1个</button>
<button v-on:click="addCountFn(5)">一次加5件</button><button @click="subFn">减少</button><script>
    export default {
        data(){
            return{
                count : 1,
            };
        },
        methods: {
            addFn(){ // this代表export default后面的组件对象(下属有data里return出来的属性)
                this.count++
            },
            addCountFn(num){
                this.count += num
            },
            subFn(){
                this.count--
            }
        }
    }
</script>

总结:把事件直接写在dom标签上,省去了传统js中操作dom的部分

3.1 v-on事件常用修饰符(鼠标)

在事件后面.修饰符名,给事件带来更方便,强大的功能

  • 语法:@事件名.修饰符=“函数”

    • .stop ------ 阻止事件冒泡
    • .pre --------阻止默认行为
    • .once ----------- 程序运行期间,只触发一次事件处理函数
<template>
  <div @click="fatherFn">
    <p @click.stop="onFn">点击阻止冒泡</p>
    <a href="http://www.baidu.com" @click.prevent.stop>点击去百度</a>
    <p @click.once="tFn">点击观察事件处理函数执行几次</p>
  </div>
</template><script>
export default {
  methods: {
    fatherFn() {
      console.log("父亲被点击");
    },
    onFn() {
      console.log("儿子被点击");
    },
    tFn() {
      console.log("11111");
    },
  },
};
</script><style>
</style>

3.2 v-on事件常用修饰符(键盘)

  • 语法:@事件名.修饰符=“函数”

    • @keyup.enter ------- 检测回车键
    • @keyup.esc ---------- 检测退出键

更多修饰符

<template>
  <div>
    <!-- 1.绑定键盘按下事件,.enter回车 -->
    <input type="text" @keydown.enter="entFn" />
    <!-- 2. .esc修饰符  退出键 -->
    <input type="text" @keydown.esc="escFn" />
  </div>
</template><script>
export default {
  methods: {
    entFn() {
      console.log("触发了enter");
    },
    escFn() {
      console.log("触发了esc");
    },
  },
};
</script><style>
</style>

总结:修饰符的使用能更加高效的完成需求,不需要进行繁琐的dom操作

4.v-model

把value属性和vue数据变量,双向绑定到一起

  • 语法:v-model=“vue数据变量”
  • 双向数据绑定
  • MVVM设计模型
<template>
  <div>
    <!-- 
        v-model:是实现vuejs变量和表单标签value属性, 双向绑定的指令
    -->
    <div>
      <span>用户名:</span>
      <input type="text" v-model="username" />
    </div>
    <div>
      <span>密码:</span>
      <input type="password" v-model="pass" />
    </div>
    <div>
      <span>来自于: </span>
      <!-- 下拉菜单要绑定在select上 -->
      <select v-model="from">
        <option value="北京市">北京</option>
        <option value="南京市">南京</option>
        <option value="天津市">天津</option>
      </select>
    </div>
    <div>
      <!-- (重要)
      遇到复选框, v-model的变量值
      非数组 - 关联的是复选框的checked属性
      数组   - 关联的是复选框的value属性
       -->
      <span>爱好: </span>
      <input type="checkbox" v-model="hobby" value="抽烟">抽烟
      <input type="checkbox" v-model="hobby" value="喝酒">喝酒
      <input type="checkbox" v-model="hobby" value="写代码">写代码
    </div>
    <div>
      <span>性别: </span>
      <input type="radio" value="男" name="sex" v-model="gender">男
      <input type="radio" value="女" name="sex" v-model="gender">女
    </div>
    <div>
      <span>自我介绍</span>
      <textarea v-model="intro"></textarea>
    </div>
  </div>
</template><script>
export default {
  data() {
    return {
      username: "",
      pass: "",
      from: "",
      hobby: [], 
      sex: "",
      intro: "",
    };
    // 总结:
    // 特别注意: v-model, 在input[checkbox]的多选框状态
    // 变量为非数组, 则绑定的是checked的属性(true/false) - 常用于: 单个绑定使用
    // 变量为数组, 则绑定的是他们的value属性里的值 - 常用于: 收集勾选了哪些值
  }
};
</script>

总结:目前v-model只能用在表单元素上,学到组件后会使用v-model高级用法

4.1 v-model修饰符

修饰符让v-model有了更简单,强大的功能

  • 语法 v-model.修饰符=“vue变量”

    1. .number -----------以parseFloat转为数字类型
    2. .trim --------------- 去除首位空白字符
    3. .lazy ----------------- 在change触发时而非input触发时
<template>
  <div>
    <div>
      <span>年龄:</span>
      <input type="text" v-model.number="age">
    </div>
    <div>
      <span>座右铭:</span>
      <input type="text" v-model.trim="title">
    </div>
    <div>
      <span>自我介绍:</span>
      <textarea v-model.lazy="intro"></textarea>
    </div>
  </div>
</template><script>
export default {
  data() {
    return {
      age: "",
      title: "",
      intro: ""
    }
  }
}
</script>

总结: v-model修饰符, 可以对值进行预处理, 非常高效好用

5.v-html和v-text

更新DOM对象的innerText和innerHTML,会覆盖插值表达式

  • 语法

    • v-text=“vue变量”
    • v-html=“vue变量”
<template>
  <div>
    <p v-text="str"></p>
    <p v-html="str"></p>
  </div>
</template><script>
export default {
  data() {
    return {
      str: "<p>我是一个p标签</p>"
    }
  }
}
</script>

v-text将值当作普通字符串显示,v-html将值当作html解析

6.v-show和v-if

控制标签的显示/隐藏

  • 语法

    • v-show=“vue变量”
    • v-if=“vue变量 ”
  • 原理

    • v-show 使用标签的display:none属性进行隐藏(适合频繁切换)
    • v-if 会对DOM树进行移除
  • v-if高级使用

    • v-else-if
    • v-else
<template>
  <div>
    <h1 v-show="isOk">v-show的盒子</h1>
    <h1 v-if="isOk">v-if的盒子</h1>
​
    <div>
      <p v-if="age <16 ">我还是个孩子</p>
      <p v-else-if="age <18 ">我长大了</p>
      <p v-else>可以去娱乐场所了</p>
    </div>
  </div>
</template><script>
export default {
  data() {
    return {
      isOk: true,
      age: 15
    }
  }
}
</script>

总结: 使用v-show和v-if以及v-else指令, 方便通过变量控制一套标签出现/隐藏

7.v-for

列表渲染,所在标签结构, 按照数据数量, 循环生成,给谁循环就把v-for加到谁身上

  • 语法

    • v-for(值,索引) in 目标结构
    • v-for 值 in 目标结构
  • 目标结构

    • 可以遍历数组 / 对象 / 数字 / 字符串 (可遍历结构)
<template>
  <div id="app">
    <div id="app">
      <!-- v-for 把一组数据, 渲染成一组DOM -->
      <!-- 口诀: 让谁循环生成, v-for就写谁身上 -->
      <p>学生姓名</p>
      <ul>
        <li v-for="(item, index) in arr" :key="item">
          {{ index }} - {{ item }}
        </li>
      </ul>
​
      <p>学生详细信息</p>
      <ul>
        <li v-for="obj in stuArr" :key="obj.id">
          <span>{{ obj.name }}</span>
          <span>{{ obj.sex }}</span>
          <span>{{ obj.hobby }}</span>
        </li>
      </ul>
​
      <!-- v-for遍历对象(了解) -->
      <p>老师信息</p>
      <div v-for="(value, key) in tObj" :key="value">
        {{ key }} -- {{ value }}
      </div>
​
      <!-- v-for遍历整数(了解) - 从1开始 -->
      <p>序号</p>
      <div v-for="i in count" :key="i">{{ i }}</div>
    </div>
  </div>
</template><script>
export default {
  data() {
    return {
      arr: ["小明", "小欢欢", "大黄"],
      stuArr: [
        {
          id: 1001,
          name: "孙悟空",
          sex: "男",
          hobby: "吃桃子",
        },
        {
          id: 1002,
          name: "猪八戒",
          sex: "男",
          hobby: "背媳妇",
        },
      ],
      tObj: {
        name: "小黑",
        age: 18,
        class: "1期",
      },
      count: 10,
    };
  },
};
</script>

总结: vue最常用指令, 铺设页面利器, 快速把数据赋予到相同的dom结构上循环生成

7.1 v-for更新检测

当v-for遍历的目标结构改变, Vue触发v-for的更新

  • 口诀

    • 数组变更方法, 就会导致v-for更新, 页面更新

      • 数组方法作用到原数组上的,会导致v-for更新,页面更新
    • 数组非变更方法, 返回新数组, 就不会导致v-for更新, 可采用覆盖数组或this.$set()

      • 数组方法返回一个新数组的,不会导致v-for更新,页面不更新
<template>
  <div>
    <ul>
      <li v-for="(val, index) in arr" :key="index">
        {{ val }}
      </li>
    </ul>
    <button @click="revBtn">数组翻转</button>
    <button @click="sliceBtn">截取前3个</button>
    <button @click="updateBtn">更新第一个元素值</button>
  </div>
</template><script>
export default {
  data(){
    return {
      arr: [5, 3, 9, 2, 1]
    }
  },
  methods: {
    revBtn(){
      // 1. 数组翻转可以让v-for更新
      this.arr.reverse()
    },
    sliceBtn(){
      // 2. 数组slice方法不会造成v-for更新
      // slice不会改变原始数组
      // this.arr.slice(0, 3)
​
      // 解决v-for更新 - 覆盖原始数组
      let newArr = this.arr.slice(0, 3)
      this.arr = newArr
    },
    updateBtn(){
      // 3. 更新某个值的时候, v-for是监测不到的
      // this.arr[0] = 1000;
​
      // 解决-this.$set()
      // 参数1: 更新目标结构
      // 参数2: 更新位置
      // 参数3: 更新值
      this.$set(this.arr, 0, 1000)
    }
  }
}
</script><style></style>
  • 以下数组方法会发生页面改变,v-for会检测到并更新页面

    • push()`
    • pop()
    • shift()
    • unshift()
    • splice()
    • sort()
    • reverse()
  • 以下方法页面不会改变

    • slice()`
    • filter()
    • concat()

注意: vue不能监测到数组里赋值的动作而更新, 如果需要请使用Vue.set() 或者this.$set(), 或者覆盖整个数组

总结:只有改变原数组目标结构的方法,才会让v-for更新

7.2 v-for就地更新

v-for的默认行为会尝试原地修改元素而不是移动他们

v-for更新检测.png

这种 虚拟DOM对比方式, 可以提高性能 - 但是还不够高