目录
1.Vue.js
2.快速上手
2.数据响应式
1.reactive函数
2.ref函数
3.Vue工程化
1.安装node.js
2.脚手架创建项目
3.项目setup
4.vue指令
1.内容渲染指令
2.属性绑定指令
3.事件绑定指令
4.条件渲染指令
5.列表渲染指令
6.双向绑定指令
7.指令修饰符
8.样式绑定
5.计算属性
1.计算属性VS普通函数
2.计算属性完整写法
6.侦听器
7.组件
1.根组件
2.组件使用(局部注册)
3.组件使用(全局注册)
4.组件生命周期
1.钩子函数
5.scoped
6.组件通信
7.自定义指令和插槽
1.自定义指令
2.插槽
8.vue-router:路由管理器
1.基本使用
2.封装路由模块
3.声明式导航
4.编程式导航
5.路由嵌套
6.路由守卫
9.pinia:vue3状态管理
10.ElementPlus组件
1.表单组件
2.卡片组件
3.表格组件
4.树形组件
5.对话框组件
6.菜单组件
11.axios
12.运行服务器
1.Vue.js
Vue.js 是一个用于构建用户界面的渐进式JavaScript框架。它常用于构建单页应用程序,其中内容在用户与应用程序交互时以动态方式加载和更新。
Vue.js 遵循组件化架构,这意味着用户界面被划分为小型、可重用的组件,可以轻松地组合这些组件来构建复杂的界面。这些组件可以使用HTML、CSS和JavaScript编写,并且可以具有自己的数据、方法和生命周期钩子。
Vue.js 的一些关键特点包括其响应式系统,当底层数据发生变化时,可以高效且自动地更新界面。它还使用虚拟DOM实现,以优化渲染性能。
2.快速上手
1.在html文件中引入vue3:
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
2.创建一个vue实例,指定要渲染的元素:
const app = Vue.createApp({
setup() {
const msg='Hello World'
return {
msg
}
}
})
app.mount('#app')
3.使用双花括号语法将数据绑定在html模版中:
<div id="app">
{{ message }}
</div>
这样就成功在网页中打印出Hello World了!
在Vue 3中,可以使用setup
函数来编写组件的逻辑。setup
函数在创建组件实例时被调用,它接收两个参数:props
和context
。其中,props
是组件接收的属性,而context
提供了一些有用的API和上下文信息。
插值表达式{{表达式}}的花括号中可以传入以下表达式:
- 变量名
- 对象.属性
- 三元表达式
- 算数运算符
- 函数和方法的调用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h1>{{msg}}</h1>
<p>我叫{{obj.name}},今年{{obj.age}}岁了</p>
<p>{{obj.age>=18?'已成年':'未成年'}}</p>
<p>来年我就{{obj.age+1}}岁了</p>
<p>fn的返回值={{fn()}}</p>
<p>{{msg}}由{{msg.split(' ').length}}个单词组成的</p>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
Vue.createApp({
setup(){
const msg="Hello World"
const fn=()=>{
return 666
}
const obj={
name:'小Vue',
age:9
}
return{
msg,
obj,
fn
}
}
}).mount('#app')
</script>
</body>
</html>
2.数据响应式
1.reactive函数
reactive
函数是Vue 3中的一个全局API,用于创建响应式数据。它接收一个普通的JavaScript对象,并返回一个响应式代理对象。该代理对象会拦截对数据的访问和修改,以实现响应式的效果。使用reactive
函数可以将普通的JavaScript对象转换为响应式的数据对象,这意味着当数据发生变化时,相关的视图会自动更新以反映新的数据。
下面是reactive
函数的使用示例:
const { createApp, reactive } = Vue
createApp({
setup() {
const obj = reactive({
name: '小vue',
age: 9
})
return {
obj
}
}
}).mount('#app')
在上面的示例中,我们使用reactive
函数创建了一个响应式的数据对象obj
,其中包含两个属性name
和age
。现在,我们可以在组件中使用obj
对象,并且当name
或age
的值发生变化时,相关的视图会自动更新。
需要注意的是,reactive
函数只会将顶层的属性转换为响应式数据。如果obj
对象中包含嵌套的对象或数组,它们不会自动转换为响应式数据。对于这些情况,我们可以使用ref
或reactive
函数来手动创建并转换为响应式数据。
2.ref函数
ref
是Vue 3中的一个全局API,用于创建一个包装对象,使其变成响应式数据。它可以用于包装各种JavaScript类型,如基本类型(如数字、字符串、布尔值)以及复杂类型(如对象、数组等)。
使用ref
函数可以将一个值包装在Ref
对象中,通过这个Ref
对象访问和修改值。Ref
对象本身是一个响应式的代理对象,它会拦截对值的访问和修改,以实现响应式的效果。
我们可以通过对象.value
来访问和修改值,当值发生变化时,相关的视图会自动更新。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<div id="app">
<h3>{{msg}}</h3>
<p>我叫{{obj.name}},今年{{obj.age}}岁了</p>
<button @click="onClick">修改ref数据</button>
</div>
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<script>
const {createApp,ref}=Vue;
createApp({
setup(){
const msg=ref('Hello Vue3');
const obj=ref({
name:'小vue',
age:9
})
const onClick=()=>{
msg.value='你好,Vue3'
obj.value.name='Vue3'
obj.value.age='10'
}
return{
msg,
obj,
onClick
}
}
}).mount('#app')
</script>
</body>
</html>
总结:
- reactive:只能接收对象作为参数,不能接收基本类型
- ref:既可以接收基本类型,也可以接受引用类型,但在用js操作时,需要‘.value’
所以:
- 如果要将一个对象变为响应式,并且对象的属性是确定的,那么推荐用reactive
- 除此之外,推荐一律使用ref(对象的属性不确定/定义响应式数组/定义基本类型的响应式数据)
3.Vue工程化
1.安装node.js
要安装Node.js,需要按照以下步骤进行操作:
- 前往Node.js官方网站:https://nodejs.org/
- 在网站首页,您会看到两个版本可供选择:长期支持版本(LTS)和当前版本。如果您对稳定性更看重,建议选择LTS版本;如果您需要最新功能和更新,可以选择当前版本。
- 点击相应版本的下载按钮。根据操作系统,选择适合的安装文件。
- 下载完成后,运行安装文件。安装过程中会有一些默认设置,您可以根据自己的需求进行选择。
- 完成安装后,打开命令行工具(终端或命令提示符)。
- 输入以下命令来验证Node.js的安装:
如果看到了Node.js的版本号,表示安装成功。node -v
- 还可以输入以下命令来验证npm(Node.js的包管理器)的安装:
如果看到了npm的版本号,表示npm也已成功安装。npm -v
还可安装其它的包管理器yarn,pnpm
2.脚手架创建项目
有几个常用的Vue3脚手架可供选择:
-
Vite:Vite 是一个专为 Vue 3 开发构建的轻量级脚手架,它使用了现代的 ESM 模块加载器并利用浏览器原生 ES 模块支持,因此具有非常快速的冷启动和热更新。
-
Vue CLI:Vue CLI 是一个官方提供的脚手架工具,它支持创建和管理 Vue 3 项目。Vue CLI 提供了一个交互式的图形用户界面来帮助你快速生成项目模板,并且还提供了许多插件和扩展来帮助你定制项目的配置。
-
Vite + Vue Cli:你也可以结合使用 Vite 和 Vue CLI。使用 Vite 创建一个 Vue 3 项目作为模板,然后使用 Vue CLI 添加更多的插件和扩展来定制你的项目。
通常,我们使用以下命令来全局安装 @vue/cli
:
npm install -g @vue/cli
使用vite构建vue3项目 :
创建好的项目结构如下:
Vue 项目通常具有以下目录结构和文件:
- src 目录:这是项目的源代码根目录,包含了所有的 Vue 组件、样式、脚本等资源。
- public 目录:这个目录下通常存放着一些静态资源,如图片、字体等,以及 index.html 文件,它是网页的入口点。
- node_modules 目录:这里存储了通过 npm 安装的依赖包。
- package.json 文件:记录了项目的元数据,包括名称、版本号、作者、依赖项等信息。
- README.md 文件:这是一个 Markdown 文档,用于介绍项目的基本信息和使用方法。
- vite.config.js 文件(如果是使用 Vite 作为构建工具的项目):配置 Vite 的相关选项。
- .gitignore 文件:指定在 Git 仓库中需要忽略的文件或文件夹。
- index.html 文件:通常是单页应用的模板 HTML 文件。
- jsconfig.json 文件:为编辑器提供 JavaScript 相关的智能提示和导航功能。
- pnpm-lock.yaml 文件(如果是使用 pnpm 作为包管理器的项目):锁定依赖项的具体版本,确保在不同的环境中安装相同的依赖项。
使用vue cli构建vue3项目:
在一个典型的 Vue 项目中,通常有三个主要的入口文件:
main.js
:这是 Vue 项目的主入口文件。它负责创建 Vue 实例,并将根组件挂载到页面上。App.vue
:这是根组件文件。它定义了整个应用程序的结构和样式,并可以包含其他的子组件。index.html
:这是应用程序的 HTML 入口文件。它包含一个根div
元素,用于挂载 Vue 应用程序。
main.js:
// 导入项目的主要样式文件
import './assets/main.css'
// 从 'vue' 包中导入 createApp 函数,这是 Vue 3 中的新方法来创建一个 Vue 应用实例
import { createApp } from 'vue'
// 导入根组件 App.vue,这是 Vue 应用的顶层组件
import App from './App.vue'
// 使用 createApp 函数创建一个新的 Vue 应用实例,并将根组件 App 传递给它
// 然后调用 mount 方法将 Vue 应用挂载到 DOM 中的元素上,这里的 '#app' 是 HTML 中的一个元素的 id
createApp(App).mount('#app')
一个vue单文件由html+css+JavaScript三部分组成
为了避免样式冲突,可以给style文件添加scoped属性 。
vue文件浏览器不能识别,需要用vite打包成js,css交给index.html显示。
3.项目setup
在项目中使用setup函数原始版本:
<script>
export default{
setup(){
const msg='hello vue3+vite';
return {
msg
}
}
}
</script>
<template>
<h1>{{ msg }}</h1>
</template>
<style scoped></style>
简写版本:
<script setup>
const msg='hello world'
</script>
<template>
<h1>{{ msg }}</h1>
</template>
<style scoped></style>
在Vue文件中使用响应式函数:
<script setup>
import { ref, reactive } from 'vue'
const msg = ref('Hello World');
const obj=reactive({
name:'小Vue',
age:9
})
</script>
<template>
<h1>{{ msg }}</h1>
<p>我叫{{obj.name}},今年{{obj.age}}岁了</p>
</template>
<style scoped></style>
4.vue指令
在Vue中,指令是用于给HTML元素添加特定行为或功能的特殊属性。指令以v-
作为前缀,并通过Vue实例的数据进行动态更新。
分类:
- 内容渲染指令:把表达式的结果渲染到双标签中
- 属性绑定指令:把表达式的值于标签的属性动态绑定
- 事件绑定指令:用来于标签进行事件绑定,处理用户交互
- 条件渲染指令:根据表达式的true或false,决定标签是否展示
- 列表渲染指令:基于数组循环生成一套列表
- 双向绑定指令:数据和视图相互影响
1.内容渲染指令
在Vue中,常用的内容渲染指令有以下几种:
v-text:用于将数据的值渲染到元素的文本内容中。
<span v-text="message"></span>
v-html:用于将数据的值渲染为HTML格式的内容,并插入到元素中。
<div v-html="htmlContent"></div>
<script setup>
import {ref} from 'vue'
const str=ref('<span style="color:red;">Hello Vue3+vite</span>')
</script>
<template>
<div>
<p v-html="str"></p>
<p v-text="str"></p>
</div>
</template>
<style scoped>
</style>
2.属性绑定指令
v-bind:用于动态地绑定元素的属性或样式,将数据的值渲染到对应的属性中。
<img v-bind:src="imageUrl">
<img :src="imageUrl">
<script setup>
import {ref} from 'vue'
const msg=ref('Hello Vue3+vite')
const url=ref('http:/www.baidu.com')
const img=ref('https://image.meiye.art/pic_afonTgKOO5h3R1lblU4bl?imageMogr2/thumbnail/560x/interlace/1')
</script>
<template>
<div v-bind:title="msg">
{{ msg }}
</div>
<div :title="msg"><!--简写-->
{{ msg }}
</div>
<a :href="url">百度一下</a>
<img :src="img" alt="">
</template>
<style scoped>
</style>
3.事件绑定指令
v-on:用于绑定元素的事件,将方法或表达式与事件进行绑定。
<button v-on:click="handleClick">点击我</button>
<button @click="handleClick">点击我</button>
<script setup>
import {ref} from 'vue'
const count=ref(0)
const increase=()=>{
count.value++;
}
const add=(n)=>{
count.value+=n;
}
</script>
<template>
<div>
<p>{{ count }}</p>
<button v-on:click="count++">+1</button>
<button v-on:click="increase">+1</button>
<button v-on:click="add(3)">+3</button>
<button v-on:click="add(5)">+5</button>
</div>
</template>
<style scoped>
</style>
4.条件渲染指令
在Vue中,条件渲染指令用于根据特定条件来动态地渲染或移除元素。常用的条件渲染指令有以下几种:
v-if:根据条件是否为真来渲染或移除元素。
<div v-if="isShow">显示内容</div>
v-else:与v-if配合使用,在v-if的条件不满足时渲染该元素。
<div v-if="isShow">显示内容</div>
<div v-else>隐藏内容</div>
v-else-if:与v-if配合使用,在v-if的条件不满足时判断新的条件是否为真,为真则渲染该元素。
<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>其他类型</div>
v-show:根据条件是否为真来显示或隐藏元素,不会改变DOM结构。
<div v-show="isShow">显示内容</div>
<script setup>
import {ref} from 'vue'
const visible=ref(true)
const isLogin=ref(true)
const mark=ref(100)
</script>
<template>
<div>
<div class="red" v-show="visible"></div>
<div class="green" v-if="visible"></div>
<hr/>
<div v-if="isLogin">xxx,欢迎回来</div>
<div v-else>你好,请登录</div>
<hr/>
<div v-if="mark>=90">优秀</div>
<div v-else-if="mark>=70">良好</div>
<div v-else>差</div>
</div>
</template>
<style scoped>
.red,
.green{
width: 200px;
height: 200px;
}
.red{
background: red;
}
.green{
background: green;
}
</style>
5.列表渲染指令
v-for是Vue.js中常用的列表渲染指令。它允许你在Vue模板中循环遍历数组或对象,并为每个元素生成相应的内容。
用法示例:
<div v-for="item in items" :key="item.id">
{{ item.name }}
</div>
上述示例中,items
是一个数组,我们使用v-for指令将其遍历,并为每个元素生成一个<div>
标签。:key
属性用于提供唯一的标识符,以便Vue可以追踪每个元素的状态变化。
你也可以使用带索引的语法来获取当前元素的索引:
<div v-for="(item, index) in items" :key="item.id">
{{ index }} - {{ item.name }}
</div>
在上述示例中,我们添加了一个名为index
的变量来获取当前元素的索引。
除了遍历数组,v-for也可以用于遍历对象的属性:
<div v-for="(value, key) in myObject">
{{ key }}: {{ value }}
</div>
上述示例中,myObject
是一个对象,我们使用v-for指令遍历其属性,并为每个属性生成一个<div>
标签。
<script setup>
import {ref} from 'vue'
const nums=ref([11,22,33,44])
const goodsList=ref([
{id:1,name:'篮球',price:299},
{id:2,name:'足球',price:99},
{id:3,name:'排球',price:199}
])
const obj={
id:10001,
name:'bit',
age:9
}
</script>
<template>
<div>
<ul>
<li v-for="(item,index) in nums">
{{ item }}=>{{ index }}
</li>
</ul>
<div>
<div class="goods-item" v-for="item in goodsList">
<p>id={{ item.id }}</p>
<p>id={{ item.name }}</p>
<p>id={{ item.price }}</p>
</div>
<ul>
<li v-for="(value,key,index) in obj">
{{ value }}=>{{ key }}=>{{ index }}
</li>
</ul>
<ul>
<li v-for="(item,index) in 5">
{{ item }}=>{{ index }}
</li>
</ul>
</div>
</div>
</template>
<style>
</style>
6.双向绑定指令
v-model是Vue.js中常用的双向数据绑定指令。它可以将表单元素的值与Vue实例的数据属性进行双向绑定,当表单元素的值发生变化时,Vue实例的数据属性也会相应地更新,反之亦然。
用法示例:
<input v-model="message">
上述示例中,我们使用v-model指令将文本输入框的值与Vue实例中的message
属性进行双向绑定。当用户在输入框中输入文本时,message
属性的值会实时更新,反之亦然。
v-model指令适用于各种输入元素,如文本输入框、复选框、单选按钮等。具体用法会根据不同的表单元素类型有所差异,你可以根据具体需求查阅Vue.js官方文档来了解更多信息。
需要注意的是,v-model指令只能应用于具有value属性的表单元素,如果要使用v-model指令绑定自定义组件的值,你需要在该组件中实现value
和input
事件的自定义逻辑。
另外,v-model指令默认使用的是input
事件,你也可以使用.lazy
修饰符,将其更改为在change
事件触发时更新数据,或使用.number
修饰符将输入的值转换为数值类型。
<input v-model.lazy="message">
<input v-model.number="age">
上面的示例中,.lazy
修饰符会在输入框的change
事件触发时更新message
属性的值,.number
修饰符会将输入的值转换为数值类型并更新age
属性的值。
<script setup>
import {reactive} from 'vue'
const loginForm=reactive({
username:'',
password:''
})
</script>
<template>
账号:<input type="text" v-model="loginForm.username"><br><br>
密码:<input type="text" v-model="loginForm.password"><br><br>
<button>登录</button>
<button>重置</button>
</template>
<style>
</style>
7.指令修饰符
指令修饰符是Vue.js中用于扩展指令功能的特殊后缀。它们可以在指令后面使用点号(.)来进行链式调用,用于修改指令的行为或提供额外的功能。
常用的指令修饰符有以下几种:
-
.prevent
:修饰事件指令,阻止事件的默认行为。<form v-on:submit.prevent="onSubmit"> <!-- 阻止表单的默认提交行为 --> ... </form>
-
.stop
:修饰事件指令,阻止事件冒泡。<div v-on:click.stop="onDivClick"> <!-- 阻止点击事件冒泡 --> <button>Click me</button> </div>
-
.once
:修饰事件指令,只触发一次事件。<button v-on:click.once="onClick">Click me</button>
-
.capture
:修饰事件指令,指定事件侦听器将以捕获模式添加,即先捕获后冒泡。<div v-on:click.capture="onDivClick"> <!-- 以捕获模式添加点击事件侦听器 --> <button>Click me</button> </div>
-
.self
:修饰事件指令,只有事件发生在触发事件的元素本身时才触发事件。<div v-on:click.self="onDivClick"> <!-- 只有点击div本身时触发点击事件 --> <button>Click me</button> </div>
-
.once
:修饰自定义指令,保证指令只执行一次。<div v-my-directive.once="value"></div>
-
.sync
:修饰v-bind指令,实现父组件与子组件之间的双向数据绑定。<child-component v-bind:title.sync="parentTitle"></child-component>
-
.lazy
:修饰v-model指令,将更新数据的行为从默认的input
事件改为change
事件。<input v-model.lazy="message">
v-model指令用于实现双向数据绑定,它的修饰符可以用来改变绑定数据的行为。以下是几个常用的v-model修饰符:
-
.lazy
:在输入框失去焦点或按下回车键后才更新绑定的数据。默认情况下,v-model会在输入框的值发生改变时即时更新数据,但是使用.lazy
修饰符可以延迟更新的时机。 -
.number
:将输入框的值转换为数字类型。如果输入框的值是一个有效的数字字符串,则绑定的数据会被自动转换为数字类型。如果输入框的值无法转换为数字,则绑定的数据会保持原来的字符串类型。 -
.trim
:自动去除输入框前后的空格。当输入框失去焦点时,绑定的数据会自动去除前后的空格。
<script setup>
import { reactive } from "vue"
const goods=reactive({
name:'',
price:''
})
</script>
<template>
<div>
名称:<input type="text" v-model.lazy="goods.name"><br><br>
价格:<input type="text" v-model.trim.number="goods.price"><br><br>
</div>
</template>
<style scoped>
</style>
v-model用于其他属性上:
<script setup>
import { ref } from 'vue'
const intro=ref('')
const city=ref('SH')
const blood=ref('ab')
const isAgree=ref(false)
const hobby=ref([])
</script>
<template>
<div>
<textarea v-model="intro" cols="30" rows="4" placeholder="请输入自我介绍"></textarea>
<br>
<br>
<select v-model="city">
<option value="BJ">北京</option>
<option value="SH">上海</option>
<option value="SZ">深圳</option>
<option value="HZ">杭州</option>
</select>
<br>
<br>
<input v-model="blood" type="radio" value="a">A
<input v-model="blood" type="radio" value="b">B
<input v-model="blood" type="radio" value="ab">AB
<input v-model="blood" type="radio" value="o">O
<br>
<br>
<input type="checkbox" v-model="isAgree">是否同意用户协议
<br>
<br>
<input v-model="hobby" type="checkbox" value="LQ">篮球 <input v-model="hobby" type="checkbox" value="ZQ">足球
<input v-model="hobby" type="checkbox" value="YMQ">羽毛球 <input v-model="hobby" type="checkbox" value="PPQ">乒乓球
<br>
<input v-model="hobby" type="checkbox" value="PB">跑步 <input v-model="hobby" type="checkbox" value="YX">游戏
<input v-model="hobby" type="checkbox" value="PLT">普拉提 <input v-model="hobby" type="checkbox" value="LDW">拉丁舞
</div>
</template>
<style scoped>
</style>
8.样式绑定
样式绑定是Vue中一种动态设置元素样式的方法。Vue提供了多种方式来实现样式绑定:
-
对象语法:使用对象语法可以绑定一个计算属性或者一个返回对象的方法来动态设置样式。通过在模板中使用
v-bind:class
或者:class
指令,可以将一个对象作为参数传递,对象的属性名是样式类名,属性值是一个布尔值,用于判断是否应用该样式类。<div :class="{ 'active': isActive, 'error': hasError }"></div>
在上述例子中,
active
和error
是样式类名,isActive
和hasError
是布尔值,根据这两个布尔值的状态来动态添加或移除对应的样式类。 -
数组语法:使用数组语法可以绑定一个计算属性或者一个返回数组的方法来动态设置样式。通过在模板中使用
v-bind:class
或者:class
指令,可以将一个数组作为参数传递,数组的元素是样式类名,根据计算属性或方法返回的数组来动态设置样式。<div :class="[activeClass, errorClass]"></div>
在上述例子中,
activeClass
和errorClass
都是样式类名,根据计算属性或方法返回的数组来动态添加对应的样式类。 -
使用内联样式:使用
v-bind:style
或者:style
指令,可以绑定一个计算属性或者一个返回样式对象的方法来动态设置元素的内联样式。<div :style="{ color: activeColor, fontSize: fontSize + 'px' }"></div>
在上述例子中,
color
和fontSize
是样式属性,activeColor
和fontSize
是计算属性或方法返回的值,根据这些值来动态设置元素的内联样式。
<script setup>
import {ref} from 'vue'
const isActive=ref(true)
</script>
<template>
<p :class="isActive?'active':''">Activa1</p>
<p :class="{active:isActive}">Active2</p>
<p class="item":class="{active:isActive }">Active3</p>
</template>
<style scoped>
.active{
color: red;
}
</style>
<script setup>
import {ref,reactive} from 'vue'
const colorStr=ref('red')
const styleObj=reactive({
color:'green',
background:'yellow'
})
</script>
<template>
<div>
<p :style="{color:colorStr}">Style1</p>
<p :style="styleObj">Style2</p>
</div>
</template>
<style>
</style>
5.计算属性
在Vue 3中,计算属性仍然是一种非常有用的特性,可以用来动态计算和响应数据的变化。
与Vue 2相比,Vue 3对计算属性的写法有一些变化。在Vue 3中,我们可以使用computed
函数来创建计算属性,而不是使用Vue 2中的computed
选项。
import { ref, computed } from 'vue';
export default {
setup() {
const firstName = ref('John');
const lastName = ref('Doe');
const fullName = computed(() => {
return firstName.value + ' ' + lastName.value;
});
return {
firstName,
lastName,
fullName
};
}
};
在上面的例子中,我们使用computed
函数来定义一个计算属性fullName
,它依赖于firstName
和lastName
两个数据属性的值,并返回它们的拼接结果。
在模板中,我们可以直接访问这个计算属性:
<template>
<div>
{{ fullName }}
</div>
</template>
<script setup>
import { computed, ref } from 'vue'
const goodsList = ref([
{ id: 1, name: '篮球', num: 1 },
{ id: 2, name: '玩具', num: 3 },
{ id: 3, name: '书籍', num: 2 }
])
const totalNum=computed(()=>{
return goodsList.value.reduce((prev,item)=>prev+item.num,0)
})
console.log(totalNum.value)
</script>
<template>
<h3>比特人的礼物清单</h3>
<table>
<thead>
<tr>
<th>名字</th>
<th>数量</th>
</tr>
</thead>
<tbody>
<tr v-for="item in goodsList"::key="item.id">
<td>{{ item.name }}</td>
<td>{{ item.num }}</td>
</tr>
</tbody>
</table>
<p>礼物总数:{{totalNum}}个</p>
<p>礼物总数:<span v-text="totalNum"></span>个</p>
</template>
<style>
table {
width: 350px;
border: 1px solid #333;
}
table th,
table td {
border: 1px solid #333;
}
table td {
text-align: center;
}
</style>
1.计算属性VS普通函数
计算属性和普通函数之间有几个主要的区别:
-
缓存:计算属性具有缓存的功能,当计算属性依赖的数据没有发生改变时,它会直接返回上一次的计算结果,而不会重新执行计算。这样可以减少不必要的计算和性能消耗。而普通函数每次调用时都会执行其中的逻辑,没有缓存的能力。
-
响应性:计算属性是响应式的,意味着当依赖的数据发生变化时,计算属性会自动重新计算并更新。这使得计算属性可以用于实时响应数据的变化。普通函数没有这种响应性,它们在调用时只执行一次逻辑,之后不会再自动更新。
-
依赖追踪:计算属性会自动追踪它所依赖的数据,只有当这些数据发生改变时,计算属性才会重新计算。这样可以避免手动跟踪和管理依赖关系。普通函数没有依赖追踪的能力,需要手动指定和更新依赖。
-
用法:计算属性通常用于模板中,可以直接在模板中使用。普通函数则更适合用于组件的逻辑中,可以被其他方法或组件调用。
2.计算属性完整写法
需要修改计算属性的值时需要用到完整写法:get+set
<script setup>
import { computed } from 'vue'
// const uname=computed(()=>{
// return 'hello'
// })
const uname=computed({
get(){
return 'hello'
},
set(val){
console.log(val)
}
})
</script>
<template>
<input type="text" v-model="uname">
</template>
<style>
</style>
6.侦听器
在Vue中,侦听器(watcher)是一种用于监视数据变化并触发相应操作的机制。
Vue提供了两种侦听数据变化的方式:一种是通过watch
选项来设置侦听器,另一种是使用计算属性(computed property)。
使用watch
选项来设置侦听器时,你可以监听一个或多个数据的变化,并在数据变化时执行特定的操作。watch
选项接收一个对象作为参数,对象的键是要监听的数据,值是一个回调函数,当数据变化时,该回调函数会被调用。回调函数的参数包括新值和旧值,你可以根据需要在回调函数中进行操作。
<script setup>
import { reactive, ref, watch } from 'vue'
const keyword = ref('')
const obj = reactive({
username: '',
password: ''
})
watch(keyword, (newVal, oldVal) => {
console.log(newVal, oldVal)
})
watch(obj, (newVal, oldVal) => {
console.log(newVal, oldVal)
console.log(newVal === oldVal)
console.log(newVal === obj)
})
</script>
<template>
<div>
<input
type="text"
v-model="keyword"
placeholder="请输入关键字" />
<br />
<br />
<input
type="text"
v-model="obj.username"
placeholder="请输入用户名" />
<br />
<br />
<input
type="text"
v-model="obj.password"
placeholder="请输入密码" />
</div>
</template>
<style>
</style>
7.组件
Vue组件是Vue.js 框架中的可复用的代码块。组件可以包含HTML、CSS和JavaScript的代码,用来实现特定的功能或展示特定的内容。组件可以被多次使用,并且可以嵌套在其他组件中。每个组件都可以拥有自己的数据和逻辑,以及生命周期方法。Vue组件可以提高代码的可维护性和重用性。
在前端开发中,组件化已经成为主流的开发方式。通过将页面或应用拆分为多个组件,每个组件专注于特定的功能或UI元素,可以更好地隔离不同模块的代码,减少代码冗余,并且提高开发效率。同时,组件化也使得UI的复杂度得到有效地管理,便于团队协作和代码重用。
1.根组件
根组件(Root Component)是Vue.js应用程序的最顶层组件,通常被命名为App.vue。它是整个应用程序的入口点,包含了应用程序的主要结构和布局。
2.组件使用(局部注册)
在Vue.js中,我们可以通过局部注册的方式来使用组件。局部注册的组件只能在其父组件中使用,无法在其他组件中直接使用,哪个文件使用组件则哪个文件导入组件。
在App.vue文件中导入MyPanel组件
<script setup>
import MyPanel from './components/MyPanel.vue';
</script>
<template>
<MyPanel></MyPanel>
<my-panel></my-panel>
</template>
<style scoped>
</style>
3.组件使用(全局注册)
在Vue.js中,我们可以通过全局注册的方式来使用组件。全局注册的组件可以在项目的任何地方使用,无需再次注册。
// main.js
import Vue from 'vue'
import ChildComponent from './ChildComponent.vue'
Vue.component('child-component', ChildComponent)
4.组件生命周期
在Vue 3中,组件的生命周期被重新设计,主要有以下几个阶段:
-
创建阶段(Creation)
- beforeCreate:在实例初始化之后,数据观测和事件配置之前被调用。
- created:在实例创建完成后被立即调用。在这一阶段,实例已经完成以下配置:数据观测(data observer),属性和方法的运算,watch/event事件回调。但是,挂载阶段还没有开始,$el属性目前还不可用。
-
挂载阶段(Mounting)
- beforeMount:在挂载开始之前被调用。相关的render函数首次被调用。
- mounted:实例挂载完成后调用,此时DOM已经渲染完成。在这一阶段,可以进行DOM操作、事件监听等。
-
更新阶段(Updating)
- beforeUpdate:数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中对更新之前的状态做一些处理。
- updated:虚拟DOM重新渲染和打补丁之后调用。组件已经更新完成,可以进行DOM操作。
-
卸载阶段(Unmounting)
- beforeUnmount:在实例销毁之前调用。在此阶段,实例仍然完全正常。
- unmounted:实例销毁后调用。在此阶段,所有的事件监听器已被移除,所有的子实例也被销毁。
在Vue 3中,新增了两个生命周期钩子函数:
- beforeUnmount:在实例销毁之前调用,代替了Vue 2.x中的beforeDestroy。
- unmounted:实例销毁后调用,代替了Vue 2.x中的destroyed。
1.钩子函数
钩子函数(Lifecycle Hooks)是在组件的生命周期中执行的一些特定函数,它们可以让开发者在不同的阶段执行一些额外的逻辑或操作。在Vue中,钩子函数分为以下几类:
-
创建阶段:
- beforeCreate:在实例初始化之后,数据观测和事件配置之前被调用。
- created:在实例创建完成后被立即调用。在这一阶段,实例已经完成以下配置:数据观测(data observer),属性和方法的运算,watch/event事件回调。但是,挂载阶段还没有开始,$el属性目前还不可用。
-
挂载阶段:
- beforeMount:在挂载开始之前被调用。相关的render函数首次被调用。
- mounted:实例挂载完成后调用,此时DOM已经渲染完成。在这一阶段,可以进行DOM操作、事件监听等。
-
更新阶段:
- beforeUpdate:数据更新时调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中对更新之前的状态做一些处理。
- updated:虚拟DOM重新渲染和打补丁之后调用。组件已经更新完成,可以进行DOM操作。
-
卸载阶段:
- beforeUnmount:在实例销毁之前调用,代替了Vue 2.x中的beforeDestroy。
- unmounted:实例销毁后调用,代替了Vue 2.x中的destroyed。
钩子函数的执行顺序为:beforeCreate -> created -> beforeMount -> mounted -> beforeUpdate -> updated -> beforeUnmount -> unmounted。
在使用钩子函数时,可以在组件中定义对应的函数,并在需要的生命周期阶段进行相应的操作。Vue框架会自动调用这些钩子函数,开发者只需关注实现逻辑即可。
<script>
export default{
data(){
return{
count:0
}
},
methods:{
fn(){
console.log('fn函数执行了')
}
},
setup(){
console.log('0-setup')
},
beforeCreate(){
console.log('1-beforeCreate')
console.log(this.count)
console.log(this.fn)
},
created(){
console.log('2-created')
console.log(this.count)
// console.log(this.fn)
this.fn()
},
beforeMount(){
console.log('3-beforeMount')
console.log(document.querySelector('p'))
},
mounted(){
console.log('4-mounted')
console.log(document.querySelector('p'))
document.querySelector('p').style.color='red'
},
beforeUpdate(){
console.log('5-beforeUpdate')
// console.log(this.count)
document.querySelector('p')
console.log(document.querySelector('p').innerText)
},
updated(){
console.log('6-updated')
// console.log(this.count)
document.querySelector('p')
console.log(document.querySelector('p').innerText)
},
beforeUnmount(){
console.log('7-beforeUnmount')
},
unmounted(){
console.log('8-unmounted')
}
}
</script>
<template>
<div>
<p>{{ count }}</p>
<button @click="count++">+1</button>
</div>
</template>
<style scoped>
</style>
在Vue 3中,由于引入了Composition API,组件的生命周期钩子函数有所改变。下面是Vue 3中的钩子函数:
-
创建阶段:
- setup:在组件实例初始化之前被调用。在这个阶段,可以做一些初始化的工作,例如设置响应式数据、注册事件等。需要注意的是,在setup函数内部不能访问到this。
-
挂载阶段:
- onBeforeMount:在挂载开始之前被调用。可以执行一些准备工作,例如请求数据。
- onMounted:在实例挂载完成后调用。可以进行DOM操作、事件监听等。
-
更新阶段:
- onBeforeUpdate:在更新开始之前调用。可以在这里进行一些准备工作,例如计算所需的数据。
- onUpdated:在更新完成后调用。可以进行DOM操作、事件监听等。
-
卸载阶段:
- onBeforeUnmount:在实例销毁之前调用。可以进行一些清理工作,例如取消事件监听、清除定时器等。
- onUnmounted:在实例销毁后调用。可以进行一些最后的清理工作。
需要注意的是,在Vue 3中,beforeCreate、created、beforeMount、mounted等Vue 2.x中的钩子函数被废弃了,取而代之的是setup、onBeforeMount、onMounted等新的钩子函数。
使用钩子函数时,可以在组件中使用import { onBeforeMount, onMounted, onBeforeUnmount, onUnmounted, onBeforeUpdate, onUpdated } from 'vue'
来导入需要的钩子函数,并在组件中添加对应的逻辑。
5.scoped
在Vue 3中,"scoped"(作用域)是指一个特性,它使得组件内部定义的CSS样式只对该组件模板内的元素生效。这有助于避免在应用程序中使用组件时出现CSS样式冲突的情况。
要在Vue 3中使用scoped特性,可以在组件的单文件组件(SFC)的<style>标签中添加"scoped"属性。例如:
<template>
<div class="container">
<p>我是一个有作用域的组件。</p>
</div>
</template>
<style scoped>
.container {
background-color: red;
padding: 10px;
}
p {
color: white;
}
</style>
在上面的示例中,<style scoped>标签中定义的CSS样式只会应用于组件模板内部的元素(在本例中是.container类和p标签),而不会泄漏或影响应用程序的其他部分。
6.组件通信
在Vue 3中,你可以使用不同的方式来进行组件通信。以下是一些常见的选项:
-
Props/Attributes:父组件可以通过props向子组件传递数据,并在子组件中使用。
// 父组件 <template> <child-component :message="parentMessage"></child-component> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { data() { return { parentMessage: 'Hello from parent' }; }, components: { ChildComponent } }; </script> // 子组件 ChildComponent.vue <template> <div>{{ message }}</div> </template> <script> export default { props: { message: String } }; </script>
-
Emit/Events:子组件可以通过emit触发自定义事件,并将数据传递给父组件。
// 子组件 ChildComponent.vue <template> <button @click="onClick">Click me</button> </template> <script> export default { methods: { onClick() { this.$emit('custom-event', 'Hello from child'); } } }; </script> // 父组件 <template> <child-component @custom-event="handleEvent"></child-component> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { methods: { handleEvent(message) { console.log(message); // 输出:'Hello from child' } }, components: { ChildComponent } }; </script>
-
Provide/Inject:父组件可以通过provide提供数据,然后在子组件中通过inject进行注入
// 父组件 <template> <div> <child-component></child-component> </div> </template> <script> import ChildComponent from './ChildComponent.vue'; export default { provide() { return { sharedData: 'Hello from parent' }; }, components: { ChildComponent } }; </script> // 子组件 ChildComponent.vue <template> <div>{{ sharedData }}</div> </template> <script> export default { inject: ['sharedData'] }; </script>
在Vue 3中,有一个新的函数叫做defineProps,它用于定义组件的props属性。在Vue 3之前,我们使用的是props选项来定义组件的props,在Vue 3中,我们可以使用defineProps函数来达到同样的效果。
使用defineProps函数时,我们需要在组件中导入它,并在setup函数中调用它。defineProps函数接受一个参数,该参数是一个对象,用来定义组件的props属性。我们可以在这个对象中定义props的名称、类型、是否必需等配置信息。
下面是一个使用defineProps函数定义props的示例:
import { defineProps } from 'vue';
export default {
props: {
msg: {
type: String,
required: true,
},
count: {
type: Number,
default: 0,
},
},
setup() {
const props = defineProps({
msg: String,
count: {
type: Number,
default: 0,
},
});
// 在组件中可以直接使用props.msg和props.count来访问props属性值
return {
props,
};
},
};
在上面的示例中,我们使用defineProps函数来定义了两个props属性:msg和count。在组件中,我们可以直接使用props.msg和props.count来访问这些属性的值。
在Vue 3中,我们可以使用defineProps函数来定义组件的props属性,并通过传入props配置对象来进行类型校验。
在props配置对象中,我们可以使用以下属性来定义和校验props:
- type:指定props的类型,可以是JavaScript原生类型(如String、Number、Boolean等),也可以是自定义的类型(如Object、Array、Function等)。
- required:指定props是否为必需的,如果设置为true,则在使用组件时必须传入该props。
- default:指定props的默认值,如果在使用组件时没有传入该props,将会使用默认值。
- validator:自定义校验函数,可以通过该函数对传入的props进行进一步的校验。
下面是一个使用defineProps函数进行props校验的示例:
import { defineProps } from 'vue';
export default {
props: {
message: {
type: String,
required: true,
},
count: {
type: Number,
default: 0,
validator: (value) => value >= 0,
},
},
setup() {
const props = defineProps({
message: {
type: String,
required: true,
},
count: {
type: Number,
default: 0,
validator: (value) => value >= 0,
},
});
// 在组件中可以直接使用props.message和props.count来访问props属性值
return {
props,
};
},
};
在上面的示例中,我们定义了两个props属性:message和count。其中,message是必需的字符串类型,count是可选的数字类型,且必须大于等于0。如果在使用组件时没有传入message或者count不符合校验规则,会在控制台中输出警告信息。
7.自定义指令和插槽
1.自定义指令
在Vue 3中,我们可以使用directive
函数来自定义指令。下面是一个简单的示例:
import { directive } from 'vue';
const myDirective = directive('my-directive', {
mounted(el, binding) {
// 在指令绑定到元素上时执行的逻辑
console.log('指令已绑定', el, binding);
},
updated(el, binding) {
// 在指令所在组件的 VNode 更新时执行的逻辑
console.log('指令已更新', el, binding);
},
unmounted(el, binding) {
// 在指令从元素上解绑时执行的逻辑
console.log('指令已解绑', el, binding);
},
});
export default myDirective;
在上面的示例中,我们使用directive
函数创建了一个名为my-directive
的指令。该指令定义了mounted
、updated
和unmounted
三个生命周期钩子函数,分别在指令绑定到元素上、指令所在组件的 VNode 更新以及指令从元素上解绑时执行。
要在组件中使用自定义指令,只需在元素上使用v-my-directive
指令即可:
<template>
<div v-my-directive></div>
</template>
在上述示例中,当该组件渲染时,my-directive
指令会自动绑定到<div>
元素上,并触发mounted
生命周期钩子函数。
除了生命周期钩子函数,我们还可以在自定义指令的配置对象中定义其他属性和方法,例如bind
、beforeMount
、beforeUpdate
等。这些函数会在相应的生命周期阶段触发。
2.插槽
在Vue 3中,插槽的使用方式也有所改变。下面是一个简单的示例来演示Vue 3中插槽的用法:
<!-- ParentComponent.vue -->
<template>
<child-component>
<template #default>
<p>默认插槽内容</p>
</template>
<template #custom>
<p>自定义插槽内容</p>
</template>
</child-component>
</template>
<!-- ChildComponent.vue -->
<template>
<div>
<h2>子组件</h2>
<slot></slot>
<slot name="custom"></slot>
</div>
</template>
在上述示例中,我们定义了一个父组件ParentComponent
和一个子组件ChildComponent
。父组件中使用了child-component
组件,并在组件的标签内使用了两个模板标签template
,分别定义了默认插槽和名为custom
的插槽。
子组件中使用了slot
标签,它会在相应位置渲染父组件传递的插槽内容。默认插槽会被渲染在<slot></slot>
处,名为custom
的插槽会被渲染在<slot name="custom"></slot>
处。
这样,当父组件渲染时,子组件会将父组件传递的插槽内容插入到相应的位置。如果没有传递相应的插槽内容,则会显示默认插槽中的内容。
需要注意的是,在Vue 3中,插槽的写法使用了#
符号来标识插槽名称,而不再使用<slot>
标签的name
属性。
另外,还可以通过v-slot
指令来定义插槽。例如,可以使用v-slot:default
来定义默认插槽,使用v-slot:custom
来定义名为custom
的插槽。这种写法更加灵活,可以在一个标签上定义多个插槽。
<child-component>
<template v-slot:default>
<p>默认插槽内容</p>
</template>
<template v-slot:custom>
<p>自定义插槽内容</p>
</template>
</child-component>
8.vue-router:路由管理器
vue-router是Vue.js官方提供的路由管理插件。它允许开发者使用单页面应用(SPA)的方式构建多页面应用。通过使用vue-router,开发者可以定义路由映射关系,使得在浏览器的URL发生变化时,可以动态地加载不同的组件,并且在组件之间进行切换。这样可以提供更流畅的用户体验,同时也可以更好地管理应用的状态。vue-router还支持参数传递、嵌套路由、路由守卫等功能,使得开发者可以更灵活地控制页面之间的跳转和数据传递。
一种常见的做法是将页面放在一个独立的views或pages文件夹中,将组件放在一个components文件夹中。这样可以使得不同类型的文件有清晰的划分,易于维护和管理。
1.基本使用
使用pnpm下载vue-router:
pnpm i vue-router//下载vue-router
main.js中导入vue-router:
import {createRouter,createWebHashHistory} from 'vue-router'
createRouter({
history:createWebHashHistory(),
routes: []
})
createApp(App).mount('#app').use(router)
main.js中导入组件并挂载:
import Find from './views/Find.vue'
import My from './views/My.vue'
import Friend from './views/Friend.vue'
const router=createRouter({
history:createWebHashHistory(),
routes: [
{
path:'/find',
component:Find
},
{
path:'/my',
component:My
},
{
path:'/friend',
component:Friend
}
]
})
const app=createApp(App)
app.mount('#app')
app.use(router)
在App.vue中设置出口:
<template>
<div>
<router-view/>
</div>
</template>
这样在不同的路径就可以展示不同的页面效果了!
2.封装路由模块
在Vue 3中,可以使用Vue Router来封装路由模块。下面是一个简单的示例:创建一个 router.js 文件,引入 Vue 和 Vue Router,以及需要用到的页面组件:
import { createRouter, createWebHistory } from 'vue-router'
import Home from '@/views/Home.vue'
import About from '@/views/About.vue'
const routes = [
{
path: '/',
name: 'Home',
component: Home
},
{
path: '/about',
name: 'About',
component: About
},
// 其他路由配置...
]
const router = createRouter({
history: createWebHistory(),
routes
})
export default router
在主入口文件(main.js)中,引入 router.js 并使用 router:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount('#app')
在需要使用路由的地方,如 App.vue 或其他组件中,可以使用 <router-link>
和 <router-view>
来进行导航和显示:
<template>
<div>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-view></router-view>
</div>
</template>
这样,就封装了一个简单的路由模块,并且可以在应用中进行页面导航和展示。
3.声明式导航
在Vue 3中,可以使用<router-link>
组件实现声明式导航。<router-link>
组件会自动渲染成一个可点击的链接,当用户点击链接时,会自动触发路由的切换。
下面是一个简单的示例:
<template>
<div>
<router-link to="/">Home</router-link>
<router-link to="/about">About</router-link>
<router-link :to="{ path: '/contact', query: { id: 123 }}">Contact</router-link>
<router-view></router-view>
</div>
</template>
<router-link>
的to
属性可以接收一个路径字符串或一个代表目标位置的对象。你可以使用字符串路径来指定要导航到的路由,也可以使用包含路径和查询参数的对象。
还可以在<router-link>
上使用其他属性来设置样式、激活状态等。
注意,在使用<router-link>
时,需要确保在Vue应用中已经正确安装了Vue Router,并且在根组件中使用了<router-view>
来渲染路由组件。
在Vue 3中,可以使用<router-link>
的to
属性来进行声明式导航并传递参数。以下是几种常见的方式:
通过路径参数传参:
<router-link :to="`/user/${userId}`">User</router-link>
在此示例中,userId
是一个变量,用于构建带有动态参数的路径。
通过查询参数传参:
<router-link :to="{ path: '/user', query: { id: userId }}">User</router-link>
在此示例中,userId
是一个变量,作为查询参数传递给路由。
通过命名路由传参:
<router-link :to="{ name: 'user', params: { id: userId }}">User</router-link>
在此示例中,userId
是一个变量,作为命名路由的参数。
请注意,以上示例中的userId
是一个变量,你可以根据实际情况进行替换。同时,确保你已经设置了对应的路由规则和组件来接收和处理参数。
在接收参数的组件中,可以通过this.$route.params
来获取路径参数,通过this.$route.query
来获取查询参数。例如:
<template>
<div>
<p>User ID: {{ $route.params.id }}</p>
<p>Query ID: {{ $route.query.id }}</p>
</div>
</template>
上述示例会根据导航传递的参数来显示用户ID和查询ID。
4.编程式导航
在Vue 3中,可以使用this.$router.push
方法进行编程式导航。以下是一个示例:
<template>
<button @click="goToUser">Go to User</button>
</template>
<script>
export default {
methods: {
goToUser() {
this.$router.push('/user');
}
}
}
</script>
在上述示例中,当按钮被点击时,goToUser
方法会调用this.$router.push
方法,将用户导航到/user
路由。
如果你需要在导航时传递参数,可以将目标路由作为一个对象传递给this.$router.push
方法,如下所示:
<template>
<button @click="goToUser">Go to User</button>
</template>
<script>
export default {
methods: {
goToUser() {
this.$router.push({ path: '/user', query: { id: userId }});
}
}
}
</script>
在上述示例中,我们创建了一个对象,指定了目标路由path
为/user
,并使用query
属性传递了查询参数。
5.路由嵌套
在Vue 3中,可以通过路由嵌套来创建嵌套的视图结构。下面是一个示例,展示如何在Vue 3中进行路由嵌套:
首先,创建一个父路由组件,用于包含子路由组件的占位符:
<template>
<div>
<h1>Parent Component</h1>
<router-view></router-view>
</div>
</template>
然后,创建子路由组件,用于嵌套在父路由组件中:
<template>
<div>
<h2>Child Component</h2>
<router-view></router-view>
</div>
</template>
接下来,在路由配置中,定义父路由和子路由的关系:
import { createRouter, createWebHistory } from 'vue-router';
import ParentComponent from '@/components/ParentComponent.vue';
import ChildComponent from '@/components/ChildComponent.vue';
const routes = [
{
path: '/parent',
component: ParentComponent,
children: [
{
path: 'child',
component: ChildComponent
}
]
}
];
const router = createRouter({
history: createWebHistory(),
routes
});
export default router;
最后,将路由配置应用到Vue应用程序中:
在上述示例中,我们定义了一个父路由/parent
,以及一个子路由/parent/child
。在父路由组件中,使用<router-view><router-view>
占位符来渲染子路由组件。
这样,在访问/parent
路径时,父路由组件会渲染,并在占位符中渲染子路由组件;而在访问/parent/child
路径时,父路由组件和子路由组件都会渲染。
6.路由守卫
在Vue 3中,可以使用路由守卫来控制路由的访问权限和导航行为。下面是一些常用的路由守卫:
全局前置守卫:在路由导航之前被调用,可以用来进行身份验证或者全局的路由拦截。可以通过router.beforeEach
注册全局前置守卫。
import { createRouter, createWebHistory } from 'vue-router';
const router = createRouter({
history: createWebHistory(),
routes
});
router.beforeEach((to, from, next) => {
// 进行身份验证或者路由拦截逻辑
next();
});
路由独享的守卫:可以在路由配置中为特定的路由定义守卫,该守卫只在该路由被访问时执行。可以通过在路由配置对象上定义beforeEnter
函数来注册路由独享的守卫。
const routes = [
{
path: '/protected',
component: ProtectedComponent,
beforeEnter: (to, from, next) => {
// 进行身份验证或者路由拦截逻辑
next();
}
}
];
组件内的守卫:可以在组件中定义beforeRouteEnter
、beforeRouteUpdate
和beforeRouteLeave
这三个方法作为组件内的守卫。这些守卫可以访问组件的实例,并且可以用来处理组件在路由变化时的情况。
const SomeComponent = {
// ...
beforeRouteEnter(to, from, next) {
// 在路由进入组件之前调用
next();
},
beforeRouteUpdate(to, from, next) {
// 在当前路由改变,但是组件被复用时调用
next();
},
beforeRouteLeave(to, from, next) {
// 在离开当前组件的路由之前调用
next();
}
}
9.pinia:vue3状态管理
Pinia 是一个基于 Vue 3 的状态管理库。它提供了一种简单、强大和可扩展的方式来管理应用程序的状态。
要使用 Pinia,你需要先安装它并在你的 Vue 3 项目中引入它。以下是使用 Pinia 的基本步骤:
安装 Pinia:
npm install pinia
在你的 main.js (或其他入口文件) 中引入 Pinia 并创建 Pinia 实例:
import { createApp } from 'vue'
import { createPinia } from 'pinia'
const app = createApp(...)
const pinia = createPinia()
app.use(pinia)
创建你的状态模块(option传参):
import { defineStore } from 'pinia'
export const useCounterStore = defineStore('counter', {
state: () => ({
count: 0,
}),
getters: {
doubleCount: (state) => state.count * 2,
},
actions: {
increment() {
this.count++
},
},
})
在这个示例中,我们创建了一个名为 counter
的状态模块,它包含一个名为 count
的状态和一个名为 doubleCount
的 getter,以及一个名为 increment
的 action。
在你的组件中使用状态:
<template>
<div>
<p>Count: {{ counter.count }}</p>
<p>Double Count: {{ counter.doubleCount }}</p>
<button @click="counter.increment()">Increment</button>
</div>
</template>
<script>
import { useCounterStore } from './store'
export default {
setup() {
const counter = useCounterStore()
return {
counter,
}
},
}
</script>
在这个示例中,我们使用 useCounterStore
函数来创建一个与 counter
状态模块关联的实例。然后,在模板中可以直接访问状态和调用 action。
创建你的状态模块(setup传参):
import { defineStore } from "pinia";
import{ref ,computed} from 'vue'
export const useStockStore=defineStore('stock',()=>{
const stock=ref(20)
function setStock(val){
stock.value=val
}
function addStock(){
stock.value++
}
const doubleStock=computed(()=>{
return stock.value*2
})
function subStock(){
stock.value--
}
return{
stock,
setStock,
addStock,
subStock,
doubleStock
}
})
<template>
<div class="add">
<h3>Add组件</h3>
<p>已知库存数:{{ stockStore.stock }}</p>
<button @click="stockStore.addStock()">库存+1</button>
</div>
</template>
<script setup>
import {useStockStore} from '@/stores/counter'
const stockStore=useStockStore()
</script>
<style scoped>
</style>
<template>
<div>
库存总数:<input type="number" v-model.number="stockStore.stock">
<p>stock的翻倍值={{ stockStore.doubleStock }}</p>
<hr />
<Add />
<hr />
<Sub />
</div>
</template>
<script setup>
import Add from './components/Add.vue';
import Sub from './components/Sub.vue';
import { useStockStore } from './stores/counter';
const stockStore=useStockStore()
</script>
<style>
#app {
width: 350px;
margin: 100px auto;
padding: 5px 5px;
border: 1px solid #ccc;
}
</style>
10.ElementPlus组件
ElementPlus是一套基于Vue 3的开源UI组件库,是对Element UI的升级和重新设计。它提供了丰富的UI组件,如按钮、表单、表格、弹窗等,可以帮助开发者快速搭建美观、易用的用户界面。
ElementPlus的特点包括:
-
更好的性能:ElementPlus借助Vue 3的优秀性能,提供更快的渲染速度和更小的体积。
-
更好的可用性:ElementPlus优化了元素的默认样式,提供更加一致和易用的组件。
-
更好的可定制性:ElementPlus通过组件插槽和主题定制等功能,提供了丰富的可定制性,可以根据实际需求进行个性化定制。
-
更好的文档支持:ElementPlus提供了详细的文档和示例,方便开发者学习和使用。
1.表单组件
ElementPlus提供了多个表单相关的组件,以下是其中一些常用的表单组件:
-
<el-input>
:用于输入文本的文本框组件。 -
<el-select>
:用于选择一个或多个选项的下拉菜单组件。 -
<el-radio>
:用于选择单个选项的单选框组件。 -
<el-checkbox>
:用于选择多个选项的复选框组件。 -
<el-datepicker>
:用于选择日期的日期选择器组件。 -
<el-switch>
:用于切换开关状态的开关组件。 -
<el-form>
:表单容器组件,用于包裹并管理表单内的所有表单控件。
2.卡片组件
ElementPlus中的卡片(Card)组件用于展示一些相关信息或内容。以下是使用Card组件的示例:
<template>
<el-card>
<img src="https://via.placeholder.com/150" class="card-image" />
<div class="card-content">
<h4>Card Title</h4>
<p>Card Description</p>
</div>
</el-card>
</template>
<style>
.card-image {
width: 100%;
height: 150px;
object-fit: cover;
}
.card-content {
padding: 20px;
}
</style>
3.表格组件
在ElementPlus中,表格(Table)组件可用于展示和操作数据。以下是使用表格组件的示例:
<template>
<el-table :data="tableData" border>
<el-table-column prop="name" label="Name"></el-table-column>
<el-table-column prop="age" label="Age"></el-table-column>
<el-table-column prop="gender" label="Gender"></el-table-column>
<el-table-column prop="email" label="Email"></el-table-column>
<el-table-column label="Actions">
<template slot-scope="scope">
<el-button type="primary" size="small" @click="editItem(scope.$index)">Edit</el-button>
<el-button type="danger" size="small" @click="deleteItem(scope.$index)">Delete</el-button>
</template>
</el-table-column>
</el-table>
</template>
<script>
export default {
data() {
return {
tableData: [
{ name: 'John Doe', age: 25, gender: 'Male', email: 'john@example.com' },
{ name: 'Jane Smith', age: 30, gender: 'Female', email: 'jane@example.com' },
{ name: 'Bob Johnson', age: 35, gender: 'Male', email: 'bob@example.com' },
]
}
},
methods: {
editItem(index) {
// 编辑操作
},
deleteItem(index) {
// 删除操作
}
}
}
</script>
4.树形组件
在ElementPlus中,树形组件(Tree)可用于展示具有层级关系的数据。以下是使用树形组件的示例:
<template>
<el-tree :data="treeData" :props="treeProps" @node-click="handleNodeClick"></el-tree>
</template>
<script>
export default {
data() {
return {
treeData: [
{
label: 'Node 1',
children: [
{ label: 'Node 1-1' },
{ label: 'Node 1-2' },
{ label: 'Node 1-3' }
]
},
{
label: 'Node 2',
children: [
{ label: 'Node 2-1' },
{ label: 'Node 2-2' }
]
},
{
label: 'Node 3'
}
],
treeProps: {
children: 'children',
label: 'label'
}
}
},
methods: {
handleNodeClick(data) {
// 处理节点点击事件
}
}
}
</script>
5.对话框组件
在ElementPlus中,对话框组件(Dialog)用于创建弹窗式的交互窗口。以下是一个使用对话框组件的示例:
<template>
<div>
<el-button type="primary" @click="showDialog">打开对话框</el-button>
<el-dialog v-model="dialogVisible" title="对话框标题" @close="handleClose">
<p>对话框内容</p>
<span slot="footer" class="dialog-footer">
<el-button @click="dialogVisible = false">取消</el-button>
<el-button type="primary" @click="save">保存</el-button>
</span>
</el-dialog>
</div>
</template>
<script>
export default {
data() {
return {
dialogVisible: false
}
},
methods: {
showDialog() {
this.dialogVisible = true;
},
handleClose() {
// 处理对话框关闭事件
},
save() {
// 处理保存按钮点击事件
this.dialogVisible = false;
}
}
}
</script>
在点击"打开对话框"按钮时,将dialogVisible
设置为true
,对话框将会显示出来。点击对话框的取消按钮或者点击对话框外部空白区域,dialogVisible
将会被设置为false
,对话框将关闭。
6.菜单组件
在ElementPlus中,菜单组件(Menu)用于创建导航菜单。以下是一个使用菜单组件的示例:
<template>
<div>
<el-menu :default-active="activeMenu" mode="horizontal" @select="handleSelect">
<el-menu-item index="1">菜单项1</el-menu-item>
<el-submenu index="2">
<template #title>菜单项2</template>
<el-menu-item index="2-1">子菜单项1</el-menu-item>
<el-menu-item index="2-2">子菜单项2</el-menu-item>
</el-submenu>
<el-menu-item index="3">菜单项3</el-menu-item>
</el-menu>
</div>
</template>
<script>
export default {
data() {
return {
activeMenu: '1'
}
},
methods: {
handleSelect(index) {
this.activeMenu = index;
}
}
}
</script>
在点击菜单项时,会触发@select
事件,将选中的菜单项的index
值传递给handleSelect
方法,然后将activeMenu
设置为选中的菜单项的index
值,实现菜单项的选中状态。
11.axios
axios 是一个基于 Promise 的 HTTP 客户端,用于发起网络请求。它可以在浏览器和 Node.js 环境中使用,并提供了许多强大的功能,如请求和响应拦截、取消请求、并发请求等。
使用 axios 发起一个简单的 GET 请求的示例:
import axios from 'axios';
axios.get('/api/getData')
.then(response => {
console.log(response.data);
})
.catch(error => {
console.error(error);
});
在上述示例中,我们首先通过 import
语句引入了 axios 模块。然后使用 axios.get
方法发起了一个 GET 请求,请求的 URL 是 /api/getData
。获取到响应后,可以通过 .then
方法获取到响应数据并进行处理,也可以通过 .catch
方法捕捉错误信息。
除了发起 GET 请求,axios 还支持 POST、PUT、DELETE 等多种请求方法,可以通过不同的方法和参数来传递请求数据、设置请求头、配置请求超时等。
axios 提供了以下所有请求方法的形式:
GET 请求:
axios.get(url[, config])
POST 请求:
axios.post(url[, data[, config]])
PUT 请求:
axios.put(url[, data[, config]])
DELETE 请求:
axios.delete(url[, config])
HEAD 请求:
axios.head(url[, config])
OPTIONS 请求:
axios.options(url[, config])
除了这些基本的请求方法外,你还可以使用 axios.request
方法来发送自定义的请求。这个方法接收一个配置对象作为参数,其中包括请求的方法、URL、数据、参数、请求头等信息。例如:
axios.request({
method: 'POST',
url: '/api/create',
data: {
name: 'John',
age: 28
},
headers: {
'Content-Type': 'application/json'
}
})
12.运行服务器
运行开发服务器:
npm run serve
这将启动开发服务器,并在浏览器中打开项目的开发环境。
如果需要构建生产版本,可以运行以下命令:
npm run build
这将生成优化后的生产代码,可以在生产环境中使用。