Vue2 基本使用 & 常用指令

目标:
使用Vue指令完成页面结构的渲染
使用Vue调试工具辅助Vue的开发

掌握Vue的两个特性:数据驱动视图、双向数据绑定
掌握Vue的底层原理 MVVM – model数据源、view视图/页面结构、viewmodel vue实例
掌握Vue六大类指令的使用

vue2指令新学到的东西:
属性绑定指令中的:对象写法
事件绑定指令中的:参数问题$event事件修饰符按键修饰符
双向绑定指令中的:v-model修饰符
条件渲染指令中的:v-if配套的v-else指令
列表渲染指令中的:key属性绑定

vscode插件推荐:Volar、Vue VSCode Snippets。 简单说明(CSDN)

Vue的优势:MVVM的数据驱动视图 – 在vue中,程序员不需要操作DOM,只需要把数据维护好即可。
因此,在vue项目中,墙裂不建议安装和使用jQuery,因为没有操作DOM的需求,如果有也是极少的。

[toc]

简介

Vue 2.x 官方文档(已不再维护)
Vue是一套用于构建用户界面的前端框架
构建用户界面:用vue往html页面填充数据
框架:一套现成的解决方案,程序员只能遵守框架的规范去编写业务功能

学习vue就是学习vue框架中规定的用法
vue的指令、组件(是对UI结构的复用)、路由、Vuex、vue组件库

Vue的优势:MVVM的数据驱动视图 – 在vue中,程序员不需要操作DOM,只需要把数据维护好即可。
因此,在vue项目中,墙裂不建议安装和使用jQuery,因为没有操作DOM的需求,如果有也是极少的。

vue的两个特性:

  1. 数据驱动视图
    vue会监听数据的变化,自动重新渲染页面的结构
    注意:数据驱动视图是单向的数据绑定
  2. 双向数据绑定
    填写表单时,自动把内容同步到数据源中

    在网页中,form表单负责采集数据,Ajax负责提交数据

MVVM – vue的底层原理

MVVM是 vue 实现数据驱动视图和双向数据绑定的核心原理。
MVVM 指的是 Model(数据源)、View(视图) 和 ViewModel(vue实例),它把每个 HTML 页面都拆分成了这三个部分。

在MVVM概念中:
Model 表示当前页面渲染时所依赖的数据源
View 表示当前页面所渲染的 DOM 结构。(页面结构,也即是视图)
ViewModel 表示 vue 的实例,它是MVVM的核心。(也就是vue)
image

  • MVVM的工作原理:
    ViewModel作为MVVM的核心,是它把当前页面的数据源(Model)和页面的结构(View)连接在了一起。
    image
    当数据源发生变化时,会被ViewModel监听到,VM会根据最新的数据源自动更新页面的结构
    当表单元素的值发生变化时,也会被VM监听到,VM会把变化过后最新的值自动同步到Model数据源中

vue的版本

当前,vue共有3个大版本,其中:
3.x版本的vue 于2020-09-19发布
2.x版本的vue 已于 2023 年 12 月 31 日停止维护
1.x版本的vue几乎被淘汰,不再建议学习与使用

基本使用

  1. 基本使用步骤

    1. 导入VUE.js脚本文件
      可以借助 script 标签直接通过 CDN(提供 npm 包服务) 来使用 Vue:
      <script src="https://cdn.jsdelivr.net/npm/vue@2/dist/vue.js"></script>
    2. 在页面声明一个将要被vue所控制的区域
    3. 创建vm实例对象(vue实例对象)
  2. 基本代码与MVVM的对应关系
    model:data指向的对象
    view:el指向的选择器
    ViewModel:new Vue()构造函数得到的实例对象

指令

指令(Directives)是vue为开发者提供的模板语法,用于辅助开发者渲染页面的基本结构。
指令是vue开发中最基础、最常用、最简单的知识点

vue的指令 按照不同用途 可以分为如下6大类:

  1. 内容渲染指令:v-text{{}}v-html

    v-test 会覆盖默认文本内容,一般使用{{}}插值表达式
    v-text和差值表达式只能渲染纯文本内容
    v-html可以把带标签的字符串渲染成HTML内容

  2. 属性绑定指令: v-bind / :xxx=

    差值表达式只能用在元素的内容节点中,不能用在属性节点中
    v-bind用法:<input type="text" v-bind:placeholder="tips">
    vue规定 v-bind: 指令可以简写为:

    在vue提供的模版渲染语法中,除了支持绑定简单的数据值之外,还支持JS表达式的运算
    但是只能写简单的JS表达式,不能写if等复杂的JS语句,如字符串拼接等:

    1
    {{number + 1}}、{{ok?'YES':'NO'}}、{{msg.split('').reserve().join('')}}//反转字符串

    • v-bind的对象写法
      <xxx v-bind="{x:100,y:200}"/> 等同于:<xxx :x="100" :y="200"/>
  3. 事件绑定指令:v-on / @

    语法如 v-on:clock="add" 简写@click="add"
    methods下的函数变量也支持简写:add:function(){} --> add(){}
    在处理函数中修改数据的值可以通过vm(接受vue实例的变量名)来修改:vm.count,但是不推荐,推荐用this

    • 绑定事件并传参

      在调用的地方传参 @click="add(1)"

    • 参数问题

      • 如果定义的函数变量是有参数的
        1. add(n){} -- @click="add(1)" 正常传参 n//1
        2. add(n){} -- @click="add()" n//undefined
        3. add(n){} -- @click="add" n被认定为事件对象PointerEvent,通常我们会定义为e/event
      • 如果是多个参数,如
        1. add(a,b){} -- @click="add(1,2)" 正常传参 a//1 b//2
        2. add(a,b){} -- @click="add(1)" a//1 b//undefined
        3. add(a,b){} -- @click="add()" a/un b//un
        4. add(a,b){} -- @click="add" a//事件对象PointerEvent ,b//undefined
    • 事件对象$event(不常用)

      vue提供了内置变量$event,它就是原生DOM的事件对象e
      在绑定事件的时候,如果不传参 add(e){} -- @click="add" , 我们会接受到一个事件对象e
      如果传参,@click="add(1)",我们就接收不到这个事件对象了
      我们既要传参,又要用到事件对象e,如想要从事件对象上拿到e.target(触发事件的事件源) ,这个时候就可以用$event
      $event使用:传$event作参数进去,拿形参接收
      add(n,e){} -- @click="add(1,$event)"
      add(e,n){} -- @click="add($event,1)"

    • 事件修饰符

      在事件处理函数中,调用event.preventDefault()(阻止默认行为)或event.stopPropagation()(阻止冒泡)是非常常见的需求。
      因此,vue提供了事件修饰符的概念,辅助程序员更方便的对事件的触发进行控制
      @click.prevent="show"绑定了show事件,同时阻止了默认行为
      常见的5个事件修饰符如下:

    事件修饰符 说明
    .prevent 阻止默认行为(例如:阻止a链接的跳转、表单的提交等)
    .stop 阻止事件冒泡
    .capture 以 捕获模式 触发当前的 事件处理函数
    .once 绑定的事件只触发1次
    .self 只有在 event.target 是当前元素自身时 触发事件处理函数
    • 按键修饰符(用的不是很多)

      监听键盘事件时,经常需要判断详细的按键
      此时,可以为键盘的相关事件添加按键修饰符,如:
      <input @keyup.enter="submit"> – 只有在keyEnter时,调用vm.submit()
      <input @keyup.esc="clearInput"> – 只有在keyEsc时,调用vm.clearInput()

  4. 双向绑定指令 v-model

    用来辅助程序员在不操作DOM的前提下,快速获取表单的数据
    能够产生数据交互的只有表单元素,所以只有表单元素才能使用v-model,才有意义
    表单元素 input、textarea、select
    v-model内部会判断绑定元素的类型,根据元素类型来决定将绑定的值给哪个属性。如复选框checkbox就是给checked属性,如果是text框就是value属性

    • v-model修饰符

      为了方便对用户输入的内容进行处理,vue为v-model指令提供了3个修饰符:

    修饰符 作用 示例
    .number 自动将用户的输入值转为数值类型 <input v-model.number="age"/>
    .trim 自动过滤用户输入的首尾空白字符 <input v-model.trim="msg"/>
    .lazy 在”change”时而非”input”时更新 <input v-model.lazy="msg"/>

    lazy的作用是input事件(表单处于焦点时候)不更新,失去焦点触发change事件才更新

  5. 条件渲染指令 v-ifv-show

    辅助开发者按需控制DOM的显示与隐藏
    v-if动态的把元素DOM从页面添加和移除
    v-show是通过css动态添加display:none样式来显示和隐藏
    如果要频繁切换元素的显示状态,show的性能更好
    如果刚进入页面,某些元素默认不需要被展示,而且后期这个元素很可能也不需要被展示出来,此时v-if性能更好
    这个只是说给面试官听的,在实际开发中,绝大多数情况不用考虑性能问题,直接使用v-if就好了!
    因为在大多数情况下,这种性能差异是微不足道的,除非在处理大量组件或频繁切换时才会产生明显影响。

    • 页面的执行(一个v-if的好问题)

      Q:如果我们页面有一个<p v-if="flag"></p> -- flag=false,因为页面是从上往下执行的,那么页面是先创建p标签再移除呢,还是一开始就不创建呢?
      A:当我们用了vue-cli以后,用到单文件组件(.vue文件)的时候,它是先编译,然后再去运行。
      先把整个网页编译成js,然后完整的去执行。标签也是被当做js去运行的,去加载的,这个问题就不存在了
      在 Vue 中,会根据 v-if 指令来决定是否渲染 DOM 元素。当 flag 初始值为 false 时,<p> 标签不会被创建到 DOM 中,Vue 在编译阶段会将 v-if 条件为 false 的元素直接移除
      具体的流程如下:
      1. Vue 开始解析模板,并执行编译步骤。
      2. 当解析到带有 v-if 指令的元素时,Vue 会根据条件的真假决定是否将该元素包含在虚拟 DOM 中。
      3. 如果 flag 的初始值为 false,则 Vue 不会将 <p> 标签添加到虚拟 DOM 中。
      4. 最终,Vue 将虚拟 DOM 渲染为真实的 DOM,此时 <p> 标签不会出现在页面上。
      因此,页面上不会先创建 <p> 标签再移除,而是在一开始就不会创建 <p> 标签。

    • v-if配套的指令 – v-else

      多个元素按需展示
      注意:v-else指令必须配合v-if指令一起使用,否则不会被识别:

      1
      2
      3
      4
      <div v-if="type === 'A'">优秀</div>
      <div v-else-if="type === 'B'">良好</div>
      <div v-else-if="type === 'C'">一般</div>
      <div v-else></div>

  6. 列表渲染指令 v-for:key 重要

    辅助开发者基于一个数组来循环渲染一个列表结构
    v-for指令需要使用item in items形式的特殊语法
    v-for支持一个可选的第二个参数,即当前项的索引(item,index) in items
    注意:v-for指令中的 item项 和 index索引 都是形参,可以根据需要命名

    • 强调v-for循环中key值的绑定

      官方推荐在用v-for的时候一定要绑定一个key属性,既提升性能、又防止列表状态紊乱。而且尽量把id作为key的值(id唯一)
      官方对key的值类型有要求,只能是字符串或数字类型,并且key的值必须唯一,不能重复(相当于id)
      也不能以index为值,如果key以索引为值,会数据紊乱,key必须唯一且稳定,不唯一就会终端报错,唯一又不稳定就会数据紊乱。
      <div v-for="(item,index) in items" :key="item.id"></div>
      如果使用v-for只是为了循环渲染出内容:key可以绑定为index索引,因为这个时候并没有实际的作用,只是为了不让报错而已
      不懂key到底有什么用的可以去了解下diff算法和虚拟dom?
      key是元素的标识,具有唯一性,diff算法同层比较会根据key判断,dom是在原基础上更新,还是删除再重新创建,若key不唯一,会造成dom额外的删除再创建,消耗性能

扩展知识

lable复选框的for属性

下面这个示例中,如果要选中男,应该点击对应的复选框,点击男不行,这样用户的体验很不好,可操作区域非常窄。
应该把它的可操作区域给放大,点击复选框还是男都可以选中,此时就用到了for属性

1
2
3
4
5
<input type="checkbox">
<label for=""></label>
<hr>
<input type="checkbox">
<label for=""></label>

for指向id,希望点这个lable让谁被选中,就for那个元素的id

1
2
3
4
5
<input type="checkbox" id="cb1">
<label for="cb1"></label>
<hr>
<input type="checkbox" id="cb2">
<label for="cb2"></label>

a元素的JavaScript 伪协议

<a href="javascript:;" @click="remove">删除</a>
这段代码是一个 HTML 锚点元素 <a> 的写法,其中javascript:; 是一个 JavaScript 伪协议,用于在点击链接时执行 JavaScript 代码或阻止默认行为。

通常情况下,当用户点击这个链接时,浏览器会执行 JavaScript:; 这里的 JavaScript 代码是空的,所以实际上不会发生任何操作。
这种写法通常用于创建一个占位符链接,或者作为一个“空链接”,用于在不跳转页面的情况下执行一些 JavaScript 操作,比如触发事件或者执行某些函数

JS - filter() 方法 – Array.prototype.filter()

filter() 方法是 JavaScript 中数组的一个内置方法,用于过滤数组中的元素,并返回一个符合条件的新数组。
如:
let arr = [1,2,3].filter(item=>item>1) //[1,2]
let arr = [{id:1,name:"zs"},{id:2..}].filter(item => item.id !=2) // [{id:1,name:"zs"}]

但是,除了数组外,filter() 方法还可以应用于类数组对象和可迭代对象。例如,字符串也可以通过 filter() 方法进行过滤操作。

下面是一个例子,演示如何在字符串中使用 filter() 方法来过滤出特定的字符:

1
2
3
const str = 'Hello World!';
const filteredStr = Array.prototype.filter.call(str, char => char !== 'l');
console.log(filteredStr.join('')); // 输出:Heo Word!

在这个例子中,我们首先使用 Array.prototype.filter.call() 来调用 filter() 方法,并将字符串 str 当作第一个参数传入。然后,我们定义了一个过滤条件,即过滤掉所有的 ‘l’ 字符。最后,我们将过滤后的字符数组通过 join() 方法连接成一个新的字符串,并输出结果。

总之,虽然 filter() 方法通常用于数组,但通过一些技巧,我们也可以在其他类型的对象上使用它。