Vue3速成笔记

Vue3速成

Vue简介

渐进式框架

Vue是一个框架,也是一个生态,其功能覆盖了大部分前端开发常见的需求。

Vue的设计非常注重灵活性和"可以被逐步集成"这个特点。根据不同的需求场景,你可以用不同的方式使用Vue:

  • 无需构建步骤,渐进式增强静态的HTML
  • 在任何页面中作为Web Components嵌入
  • 单页应用(SPA)
  • 全栈/服务端渲染(SSR)
  • Jamsstack/静态站点生成(SSG)
  • 开发桌面端、移动端、WebGL、甚至是命令行终端中的界面

Vue版本

Vue3涵盖了Vue2的知识体系,当然Vue3也增加了很多新特性

官网文档:https://cn.vuejs.org/

淘宝npm镜像改成了https://registry.npmmirror.com

Vue API风格

Vue的组件可以按照两种不同的风格书写:

  • 选项式API —-> 偏向于Vue2
  • 组合式API —-> 偏向于Vue3

Vue项目项目结构

1
2
3
4
5
6
7
8
.vscode			----> VSCode工具的配置文件
node_modules	----> Vue项目的运行依赖文件夹
public			----> 资源文件夹(浏览器图标)
src				----> 源码文件夹
.gitnore		----> git忽略文件
index.html       ----> 入口HTML文件
package.json	 ----> 信息描述文件
vite.config.js	 ----> Vue配置文件 

模板语法

Vue使用一种基于HTML的模板语法,是我们能够声明式地将其组件实例的数据绑定到呈现的DOM上。所有的Vue模板都是语法层面合法的HTML,可以被符合规范的浏览器和HTML解析器解析

文本插值

最基本的数据绑定形式是文本插值,使用的是"Mustache"语法(即双大括号)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<template>
 <h3>模板语法</h3>
 <p>{{ msg }}</p>
</template>

<script>
export default{
  data(){
    return{
      msg:"神奇的语法"
    }
  }
}
</script>

使用JS表达式

每个绑定仅支持单一表达式,也就是一段能够被求值的JavaScript代码。一个简单的判断方法是是否可以合法地写在return后面

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
<template>
 <h3>模板语法</h3>
 <p>{{ msg }}</p>
 <p>{{ number + 1 }}</p>
 <p>{{ msg.split('').reverse().join('') }}</p>
</template>

<script>
export default{
  data(){
    return{
      msg:"神奇的语法",
      ok:true,
      number:10
    }
  }
}
</script>

无效

1
2
3
4
5
<!-- 这是一个语句而非表达式 -->
{{var a = 1}}

<!-- 条件控制也不支持请使用三元表达式 -->
{{if(ok){return message} }}

原始HTML

双大括号将会将数据插值为纯文本,而不是HTML。若想插入HTML,你需要使用v-html指令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
 <h3>模板语法</h3>
 <p>{{ msg }}</p>
 <p>{{ number + 1 }}</p>
 <p>{{ msg.split('').reverse().join('') }}</p>
 <p>{{ rawHtml }}</p>
 <p v-html="rawHtml" ></p>
</template>

<script>
export default{
  data(){
    return{
      msg:"神奇的语法",
      ok:true,
      number:10,
      rawHtml:"<a href='https://bilibili.com'>哔哩哔哩</a>"
    }
  }
}
</script>

属性绑定

双大括号不能在HTML attributes中使用。想要响应式地绑定一个attribute,应该使用v-bind指令

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
<script>
  export default{
    data(){
      return{
        dynamicClass:"active",
        dynamicId:"appid"
      }
    }
  }

</script>

<template>
  <div v-bind:id="dynamicId" v-bind:class="dynamicClass">测试</div>
</template>

v-bind指令指示Vue将元素的idattribute与组件的dynamicId属性保持一致。如果绑定的值是null或者undefined,那么该attribute将会从渲染的元素上移除

简写

因为v-bind非常常用,我们提供了特定的简写语法

1
<div :id="dynamicId":class="dynamicClass">测试</div>

布尔型Attribute

布尔型attribute依据true/false值来决定attribute是否应该存在于该元素上,disabled就是最常见的例子之一

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<script>
  export default{
    data(){
      return{
        dynamicClass:"active",
        dynamicId:"appid",
        isButtonDisabled:false
      }
    }
  }

</script>

<template>
  <div v-bind:id="dynamicId" v-bind:class="dynamicClass">测试</div>
  <button :disabled="isButtonDisabled">Button</button>
</template>

动态绑定多个值

如果你有像这样的一个包含多个attribute的JavaScript对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
<script>
  export default{
    data(){
      return{
        objectOfAttrs:{
          id:'container',
          class:'wrapper'
        }
      }
    }
  }

</script>

<template>
  <div v-bind="objectOfAttrs">测试</div>
</template>

条件渲染

vue中,提供了条件渲染,这类似于JavaScript中的条件语句

  • v-if
  • v-else
  • v-else-if
  • v-show

v-if

v-if指令用于条件性地渲染一块内容,这块内容只会在指令的表达式返回真值时才被渲染

v-else

可以使用v-elsev-if添加一个"else区块"

v-else-if

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<template>
    <h3>条件渲染</h3>
    <div v-if="flag">你看得见我吗</div>
    <div v-else>那你看得见我吗</div>
    <div v-if="type === 'A'">A</div>
    <div v-else-if="type === 'B'">B</div>
    <div v-else-if="type === 'C'">C</div>
    <div v-else>Not A/B/C</div>
</template>

<script>
    export default{
        data(){
            return{
                flag:false,
                type:"D"
            }
        }
    }
</script>

v-show

另一个可以用来按条件显示一个元素地指令是v-show,其用法基本一样

v-if Vs v-show v-if是"真实的"按条件渲染,因为他确保了在切换时候,条件区块内的事件监听器和子组件都会被销毁与重建

v-if也是惰性的:如果在初次渲染时条件值为false,则不会做任何事情。条件区块只有当条件首次变为true的时候才会被渲染

相比之下,v-show简单许多,元素无论初始条件如何,始终会被渲染,只有CSSdisplay属性会被切换

总的来说,v-if有更高的切换开销,而v-show有更高的初始渲染开销。因此,如果需要频繁切换,则使用v-show较好;如果在运行时绑定条件很少改变,则v-if会更合适

列表渲染

我们可以使用v-for指令基于一个数组来渲染一个列表。v-for指令的值需要使用item in items形式的特殊语法,其中items是源数据的数组,而item是迭代项的别名(类似于for each)

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<template>
    <h3>列表渲染</h3>
    <p v-for="item in names">{{ item }}</p>
</template>

<script>
    export default{
        data(){
            return{
              names:["百战程序员","尚学堂","IT"]  
            }
        }
    }
</script>

复杂数据

大多数情况下,我们渲染的数据源来源于网络请求,也就是JSON格式

image-20240208172435522

v-for也支持使用可选的第二个参数表示当前项的位置索引

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<template>
    <h3>列表渲染</h3>
    <p v-for="(item,index) in names">{{ item }}-{{ index }}</p>
</template>

<script>
    export default{
        data(){
            return{
              names:["百战程序员","尚学堂","IT"]  
            }
        }
    }
</script>

也可以使用of来代替in

v-for="item of names"

v-for与对象

也可以使用v-for来遍历一个对象的所有属性

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<template>
    <h3>列表渲染</h3>
    <p v-for="(item,index) in names">{{ item }}-{{ index }}</p>
    <p v-for="(value,key,index) of userInfo">{{ value }}-{{ key }}-{{ index }}</p>
</template>

<script>
    export default{
        data(){
            return{
              names:["百战程序员","尚学堂","IT"],
              userInfo:{
                name:"iwen",
                age:20,
                sex:"男"
              }  
            }
        }
    }
</script>

通过key管理状态

Vue默认按照"就地更新"的策略来更新通过v-for渲染的元素列表。当数据项的顺序改变时,Vue不会随之移动DOM元素的顺序,而是==就地更新每个元素==,确保它们在原本指定的索引位置上渲染

为了给Vue一个提示,以便它可以跟踪每个节点的标识,从而重用和重新排序现有的元素,你需要为每个元素对应的块提供一个唯一的keyattribute:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<template>
    <h3>Key属性添加</h3>
    <p v-for="(item,index) of names" :key="index">{{ item }}</p>
</template>

<script>
    export default {
        data(){
            return {
                names:["111","222","333"]
            }
        }
    }
</script>

补充:

key在这里是一个通过v-bind绑定的特殊attribute,推荐在任何可行的时候为v-for提供一个keyattribute,key绑定的值期望是一个基础类型的值,例如字符串或者number类型

key的来源

请不要使用index作为key的值,要确保每一条数据的唯一索引不会发生变化

事件处理

我们可以使用v-on指令(简写为@)来监听DOM事件,并在事件触发时执行对应的Javascript。用法:v-on:click="methoodName"@click="handler"

事件处理器的值可以是:

  1. 内联事件处理器:事件被触发时执行的内联JavaScript语句(与onclick类似)
  2. 方法事件处理器:一个指向组件上定义的方法的属性名或者路径

内联事件处理器

内联事件处理器通常用于简单场景

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
<template>
    <h3>内联事件处理器</h3>
    <button @click="count++">Add</button>
    <p>{{ count }}</p>
</template>

<script>
    export default {
        data(){
            return {
                count:0
                //双向绑定
            }
        }
    }
</script>

方法事件处理器

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
    <h3>内联事件处理器</h3>
    <button @click="addCount">Add</button>
    <p>{{ count }}</p>
</template>

<script>
    export default {
        data(){
            return {
                count:0
            }
        },
        methods:{
            addCount(){
                //读取到data里的数据
                this.count++;
            }
        }
    }
</script>

事件传参

事件参数可以获取event对象和通过事件传递数据

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
    <h3>事件传参</h3>
    <p @click="getNameHandler(item,$event)" v-for="(item,index) of names" :key="index">{{ item }}</p>
</template>

<script>
    export default {
        data(){
            return {
               names:["iwen","ime","frank"]
            }
        },
        methods:{
            //如果定义的函数中既有传参又有事件,那么在标签中应该在形参中添加$event
            getNameHandler(name,e){
                console.log(name);
                console.log(e);
            }
        }
    }
</script>

事件修饰符

在处理事件时调用event.preventDefault()event.stopPropagation()是很常见的。尽管可以直接在方法内调用,但如果方法能更关注于数据逻辑而不用去处理DOM事件的细节会更好

为解决这一问题,Vue为v-on提供了事件修饰符,常用有以下几个:

  • .stop
  • .prevent
  • .once
  • .enter
  • ···

阻止默认事件

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
<template>
    <h3>事件修饰符</h3>
    <a @click.prevent="clickHandle" href="https://bilibili.com">b站</a>
</template>

<script>
    export default {
        data(){
            return {
               
            }
        },
        methods:{
            clickHandle(e){
                //阻止默认事件
                // e.preventDefault();
                console.log("点击了")
            }
        }
    }
</script>

阻止事件冒泡

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<template>
    <h3>事件修饰符</h3>
    <a @click.prevent="clickHandle" href="https://bilibili.com">b站</a>
    <div @click="clickDiv">
        <p @click.stop="clickP">测试冒泡</p>
    </div>
</template>

<script>
    export default {
        data(){
            return {
               
            }
        },
        methods:{
            clickHandle(e){
                //阻止默认事件
                // e.preventDefault();
                console.log("点击了")
            },
            clickDiv(){
                console.log("Div")
            },
            clickP(e){
                //阻止事件冒泡
                // e.stopPropagation();
                console.log("P")
            }

        }
    }
</script>

数组变化侦测

变更方法

Vue能够侦听响应式数组的变更方法,并在他们被调用时触发相关的更新。这些变更方法包括:

  • push()
  • pop()
  • shift()
  • unshift()
  • splice()
  • sort()
  • reverse()

替换一个数组

变更方法,顾名思义就是对调用它们的原数组进行变更。相对地,也有一些不可变方法,例如filter()concat()slice(),这些都不会更改原数组,而是返回一个新数组。当遇到的是非变更方法时,我们需要将旧的数组替换新的

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<template>
    <button @click="addUI">click</button>
    <ul>
        <li v-for="(item,index) of names" :key="index">{{ item }}</li>
    </ul>
</template>

<script>
    export default{
        data(){
            return{
                names:["iwen","ime","frank"]
            }
        },
        methods:{
            addUI(){
                //引起UI自动更新
                //this.names.push("sakura")
                //不会引起UI自动更新
                this.names = this.names.concat(["sakura"])
            }
        }
    }
</script>

计算属性

模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
    <h3>{{ it.names }}</h3>
    <p>{{ itbaizhan }}</p>
</template>

<script>
    export default{
        data(){
            return{
               it:{
                names:"百战程序员",
                content:["前端","Java","python"]
               }
            }
        },
        //计算属性
        computed:{
            itbaizhan(){
                return this.it.content.length>0?'Yes':'No'
            }
        }
    }
</script>

计算属性缓存VSmethod

重点区别:

计算属性:计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算

方法:方法调用总是会在重渲染发生时再次执行函数

Class绑定

数据绑定的一个常见需求场景是操纵元素的CSS class列表,因为class是attribute,我们可以和其他attribute一样使用v-bind将它们和动态的字符串绑定。但是,在处理比较复杂的绑定时,通过拼接生成字符串是麻烦且出错的。因此,Vue专门为classv-bind用法提供了特殊的功能增强。除了字符串外,表达式的值也可以是对象或数组

绑定对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
<template>
    <p :class="{'active':isActive,'textError':hasError}">Class样式绑定</p>
    <p :class="classObject">Class样式绑定2</p>
</template>

<script>
    export default{
        data(){
            return{
               isActive:true,
               hasError:true,
               classObject:{
                'active':true,
                'textError':true
               }
            }
        }
    }
</script>

<style>
    .active{
        color: red;
    }
</style>

绑定数组

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
<template>
    <p :class="{'active':isActive,'textError':hasError}">Class样式绑定</p>
    <p :class="classObject">Class样式绑定2</p>
    <p :class="[arrActive,arrHasError]">Class样式绑定3</p>
    <p :class="[isActive?'active':'']">Class样式绑定4</p>
</template>

<script>
    export default{
        data(){
            return{
               isActive:true,
               hasError:true,
               classObject:{
                'active':true,
                'textError':true
               },
               arrActive:"active",
               arrHasError:"text-Error"
            }
        }
    }
</script>

<style>
    .active{
        color: red;
    }
</style>

数组和对象

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<template>
    <div :class="[{'active':isActive},errorClass]">11</div>
</template>

<script>
    export default{
        data(){
            return{
               isActive:true,
               errorClass:"text-danger"
            }
        }
    }
</script>

<style>
    .active{
        color: red;
    }
</style>

温馨提示

数组和对象嵌套使用的时候,只能数组嵌套对象,不能反其道而行

Style绑定

与上文中的Class绑定类似

侦听器

我们可以使用watch选项在每次响应式属性发生变化的时候触发一个函数

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
<template>
    <h3>侦听器</h3>
    <p>{{ message }}</p>
    <button @click="onUpdated">修改数据</button>
</template>
<script>
import { onUpdated } from 'vue';

    export default{
        data(){
            return {
                message:"Hello"
            }
        },
        methods:{
            onUpdated(){
                this.message = "World"
            }
        },
        watch:{
            //函数名需要和侦听的变量保持一致
            message(newValue,oldValue){
                //数据发生变化,自动执行的函数
                console.log(newValue,oldValue);
            }
        }
    }
</script>

表单输入绑定

在前端处理表单时,我们常常需要将表单输入框的内容同步给JavaScript中相应的变量。手动连接值绑定和更改事件监听器可能会很麻烦,v-model指令帮我们简化了这一步骤

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<template>
    <h3>表单输入绑定</h3>
    <form>
        <input type="text" v-model="message">
        <p>{{ message }}</p>
        <input type="checkbox" id="checkbox" v-model="checked">
        <label for="checkbox">{{ checked }}</label>
    </form>

</template>
<script>
    export default {
        data() {
            return {
                message:" ",
                checked:false
            }
        }
    }
</script>
Licensed under CC BY-NC-SA 4.0
comments powered by Disqus
使用 Hugo 构建
主题 StackJimmy 设计