Vue框架的使用笔记
1. Vue框架简介
Vue.js是一套用于前端构建用户界面的渐进式框架。
什么是框架?框架是一套封装了多个功能开发套件的代码包,是一种简单、高效的工具箱。
Vue官网:vuejs.org
中文官方手册:https://cn.vuejs.org/guide/introduction.html
Vue API有两种风格:选项式API(Vue2);组合式API(Vue3)
2. 创建vue项目
首先创建一个项目文件夹,VScode中打开该文件夹,新建一个终端,并
2.1 输入初始化vue脚手架指令
1  | npm init vue@latest  | 
这一指令会执行创建vue项目, 并弹出一堆可选功能的选项如下。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22Need to install the following packages:
  create-vue@3.7.2
Ok to proceed? (y) y                                //确认创建的vue版本
Vue.js - The Progressive JavaScript Framework
√ Project name: ... vue001                          //输入项目名称,不能有大写
√ Add TypeScript? ... No / Yes                      //这里有关TypeScript
√ Add JSX Support? ... No / Yes                     //这里有关React
√ Add Vue Router for Single Page Application development? ... No / Yes      //这里有关路由
√ Add Pinia for state management? ... No / Yes      //这里有关Pinia状态管理
√ Add Vitest for Unit Testing? ... No / Yes         //以下是一些测试文件的功能支持
√ Add an End-to-End Testing Solution? » No
√ Add ESLint for code quality? ... No / Yes
Scaffolding project in C:\Users\63015\Desktop\前端笔记\07-vueproject\vue001...
Done. Now run:
  cd vue001             //打开项目文件夹
  npm install           //安装项目依赖
  npm run dev           //运行项目
2.2 启动vue项目三连
1  | PS C:\Users\63015\Desktop\前端笔记\07-vueproject> cd vue001 //打开项目文件夹  | 
2.3 开发环境
采用VSCode + Volar扩展插件
2.4 Vue项目的目录结构
在新建终端使用tree指令,我们可以得到vue项目的目录树,其中一级目录下的资源文件与文件夹有:1
2
3
4
5
6
7
8
9.vscode         //vscode工具的配置文件夹(删除了也不会影响项目本身的运行)
node_modules    //vue项目的运行依赖文件夹(npm install指令安装的vue依赖)
public          //资源文件夹(存放浏览器图标等资源)
src             //源码文件夹(写的代码都在这里)
.gitignore      //Git的忽略文件(Git用)
index.html      //HTML入口文件(基底)
package.json    //信息描述文件(项目名称、版本、运行脚手架、依赖等)
readme.md       //注释文件(写啥都行)
vite.config.js  //vue配置文件(跨域、打包等配置)
看完vue项目的目录结构,我们得知src是主要的编写区域,其中components文件夹中存放了一些基础的vue代码,会被src目录下的App.vue主文件调用,所以一开始我们的代码都是存在App.vue这个文件内。
App.vue中最基础结构如下:
1  | <template>  | 
然后,打开本地端口5173就可以看到渲染后的窗口了。
2.5 components调用
承接上文记录,App.vue是我们的主代码,components文件夹中存放的是我们自己添加自定义的子代码。那么如何在主代码中调用呢?1
2
3
4
5
6
7
8
9
10//此段在App.vue内
<script setup>
    //此处调用components
    import Helloworld from './components/HelloWorld.vue'
</script>
<template>
    //此处渲染components
    <Helloworld/>
</template>
如此一来,就形成了树状结构。
3. Vue模板语法
vue使用的是一种基于HTML的模板语法,该语法的特点:通过声明方式将组件的实例数据绑定到DOM上。
个人理解:我在js中通过声明一堆属性和数据,然后属性和数据自己就跑到DOM上。
最终实现的是只修改js部分也可以干涉H5以变更页面显示。
以下就是一些常见的模板语法:
3.1 文本插值 (Mustache写法)
我在js中写的文字,可以传到html的标签中,从而显示。
1  | <template>  | 
这种语法叫做“双括号语法/大胡子语法/Mustache语法”
3.2 JS表达式
在{{  }}中,我们也可以使用一些简单的js表达式,对传入数据进行微调表达。
1  | <template>  | 
在这里,return后面可以跟这些变量/对象,但不可以跟逻辑语句/非单一表达式。因此,在{{  }}中最好不要放逻辑语句,应当尽量在js中进行逻辑处理后,直接把结果丢给template。
3.3 原始HTML插值 (v-html)
上面的文本插值只能将键值后的数据直接传给标签,并不能支持原生HTML的写法,因此需要使用v-html标签属性(指令)来引入含有HTML写法的数据。
1  | <template>  | 
3.4 属性绑定 (v-bind:)
除了上文中的文本信息可以绑定,标签的一些其他属性也可以进行绑定,需要用到v-bind指令来引入标签的style属性/选择器。
1  | <template>  | 
但如果绑定的组件的键值为Null/Undefined,则会忽略这次调用。
且由于v-bind指令十分常用,故而可以直接用冒号进行简写:
1  | <div :id="dyanmicId" :class="dynamicClass"> </div>  | 
3.4.1 小案例:属性绑定布尔值,调用开关
属性绑定有一种应用,即是调用布尔值控制按钮的启用/禁用。
1  | <template>  | 
3.4.2 小案例:属性绑定多个值
一次次属性绑定会很繁琐,一次性绑定对象的多个值会更为方便。
1  | <template>  | 
4. 条件渲染
在vue中,有提供条件渲染的功能,相关的条件语句如下:
- v-if
 - v-else
 - v-else-if
 - v-show
 
4.1 v-if (单分支)
v-if用于条件渲染,当表达式为真时,会渲染一块内容。
1  | <template>  | 
4.2 v-else (双分支)
v-else是和v-if相对应的条件渲染指令。
1  | <template>  | 
4.3 v-else-if (多分支)
v-else-if是一个组合的多分支条件渲染的条件渲染指令。
1  | <template>  | 
4.4 v-show (单分支)
v-show与v-if相似,都是单分支的条件判断渲染,用法与v-if一样。
1  | <template>  | 
但是,v-if是每次都进行了条件判断后再渲染与否,事件监听和子组件都会销毁重建(真实且惰性);而v-show其实本身早就渲染,只是切换了css的display属性。两者各有妙用。
【总结】v-if的切换开销大,如果条件很少变动,则v-if更合适。v-show初始开销相对较大,如果条件频繁切换,则v-show更合适。
5. 列表渲染 (v-for)
在vue中,我们还可以使用v-for指令和item in items写法来基于一个数组来渲染一个列表。
1  | <template>  | 
其中,v-for是指令,item in items是指令值,item是迭代项的别名(自定义,一般不改),items是源数据的数组名(键值名)
5.1 小案例:复杂数据列表渲染
在一个项目中,要渲染的源数据通常来源于网络请求,就是json格式。
下面会给出一个复杂数据的列表渲染-小型案例:
1  | <template>  | 
另外,其中的item in items写法中的in也可以用of替代,写作item of items,即:
1  | <div v-for="item of result"></div>  | 
5.2 v-for的位置索引(item,index)
此外,v-for也支持对于迭代项的位置索引。即对于每一个迭代项,除了读出它的内容,还可以读出它的序号(index)。
1  | <template>  | 
5.3 v-for遍历对象属性(item,key,index)
因此,v-for也支持对对象进行遍历。除了数据遍历调出、位置序号调出,也可以调出属性键值。
1  | <template>  | 
5.4 对key(数据标识节点)的管理
继上一节中的内容,对于一个对象中的一条数据:"id":123456,
- 其中
123456是属性的值,数据的内容,通常在v-for中使用value/item来调用。 - 其中
id是属性的键值,属性的名称,通常在v-for中使用key来调用。 - 以外,该数据在数组中的次序号码,下标,通常在
v-for中使用index来调用。 
但这一节中,我们主要关注另一个key,也就是key attribute,(数据节点标记)的管理。
与(item,key,index)中的key属性键值不同,这里的key不是指每条数据的属性的名称,而是对数据库中遍历时的每条数据的一个独一无二的编号,是一个属性(类似python的for-v-k)
1  | <p v-for="(item,index) in names" :key="index"> {{ item }} </p>  | 
这里的key是一个通过v-bind绑定的特殊属性;
一般情况下,每一个v-for都需要一个key,用于在遍历索引中识别。
例如:如果数据库中每条数据都有id属性,也可以这么指定key——:key="item.id",这样每条数据的id属性就作为key属性存在了。
1  | <template>  | 
6. 事件处理 (@)
在vue中,可以用v-on指令(简写为@)来监听DOM事件,并于事件触发时执行对应的js,基本语法如下:
1  | <button v-on:click="methodName"> 我是按钮,点击触发methodName </button>  | 
其中,methodName和handler这俩所在的位置即是事件处理器的值。
而事件处理器的值可以是:
- 事件触发时,执行的内联式js语句。(内联事件处理器)
 - 一个指向组件上定义的方法的属性名称/路径。(方法事件处理器)
 
6.1 内联事件处理器
内联事件处理器一般用于简单场景。语法示范如下:
1  | <template>  | 
6.2 方法事件处理器
遇到较为复杂的事件时,可以用函数名称填写值,然后具体逻辑丢到js中去写。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<template>
    //这里直接将要执行的函数名称addcount写在了事件触发器的值内。
    <button @click="addcount"> 我是木鱼,点击功德+1 </button>
    <p> 当前功德:{{ count }} </p>
</template>
<script>
export default {
    data(){
        return{
            count:0
        }
    },
    //方法事件的函数写在methods中,所有的方法/函数都丢到这里。
    methods:{
        //addcount函数
        addcount(){
            this.count++       //读取data-return里面的数据, 用this.count
        }
    }
}
</script>
7. 事件传参
事件的参数,可以获取event对象和其他对象,通过事件名来传递参数。
有什么作用?可以在事件函数中进行对象操作,反向干预H5。
7.1 获取Event对象
vue中的event对象即是原生js的Event对象,包含了事件本身的数据信息。
1  | <template>  | 
7.2 事件传递参数
这里实现的是从事件触发值的参数传到方法的事件函数的参数中的普通传参。
下面是基础结构:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<template>
    <button @click="addcount('我是参数')"> 我是木鱼,点击功德+1 </button>
    <p> 当前功德:{{ count }} </p>
</template>
<script>
export default {
    data(){
        return{
            count:0
        }
    },
    methods:{
        addcount(msg){          //通过msg接收addcount的第一个参数
            console.log(msg)    //输出msg即可看见这个参数的具体内容
            this.count++
        }
    }
}
</script>
事件传参案例
为了便于理解事件传参,先看看事件传参的应用案例。
例:现有一组数组,使用列表渲染后,需要实现——点击页面上任意的名字,都在后台输出对应的名字。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22<template>
    <h3>事件传参</h3>
    {/* 2. 用v-for列表渲染出来 */}
    <p @click="getNameHandler(item)" v-for="(item,index) of names" :key="index"> {{item}} </p>
    {/* 3. 给p标签添加一个事件getNameHandler;把item当成参数传给事件 */}
</template>
<script>
export default {
    data(){
        return{
            names:["momoeven","niord","anson"]  //1. data中给一个names数组
        }
    },
    methods:{
        //4. 创建事件函数,并用name接收传参
        getNameHandler(name){
            console.log(name)       //5. 实现点谁显示谁
        }
    }
}
</script>
7.3 事件传参时获取event对象
现在理解了事件传参,和获取event对象,有无可能同时传参并获取event对象呢?
使用,$event是可以的。
1  | <template>  | 
8. 事件修饰符
事件修饰符可以用来简化代码。
比如:阻止默认事件;阻止事件冒泡等。
更多事件修饰符可以看:https://cn.vuejs.org/guide/essentials/event-handling.html#event-modifiers
8.1 阻止默认事件
如果现在有一个a标签,需求是点击a标签只记录但是不进行跳转。这就需要用到阻止默认事件来阻止默认的a标签跳转。
范例如下: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="#" >超链接</a>
    {/* 这里使用了艾特click.prevent来简化阻止默认事件的写法 */}
</template>
<script>
export default {
    data(){
        return{
        
        }
    },
    methods:{
        clickHandle(){
            //e.preventDefault();   //这里是阻止默认事件的原本写法(记得获取e)
            console.log(已点击);
        }
    }
}
</script>
8.2 阻止事件冒泡
事件冒泡是指同一个操作同时触发了多个事件,比如子元素触发了然后父元素也触发了。
阻止事件冒泡就是当子元素触发后,阻止父元素继续触发。
范例如下: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<template>
    <h3>阻止事件冒泡</h3>
    <div @click="clickDiv">
        <p @click.stop="clickP">测试冒泡</p>
        {/* 这里使用了艾特click.stop来简化阻止事件冒泡的写法 */}
    </div>
</template>
<script>
export default {
    data(){
        return{
        
        }
    },
    methods:{
        clickDiv(){
            console.log("div");
        },
        clickP(){
            //e.stopPropagation();   //这里是阻止事件冒泡的原本写法(记得获取e)
            console.log("p");
        },
    }
}
</script>











