目录
Pinia
Pinia的概念
是什么
Pinia是一个状态管理工具,vue的专属状态管理库,它可以让我们实现跨组件(多个组件)或页面共享状态。
使用目的
- 多个组件数据保持同步。
- 数据的变化是可追踪的。
Pinia中存什么
多个组件共享的数据,才存储在pinia中,某个组件的私有数据,依旧存储在组件自身内部。
比如:登录的用户名,在各个页面中都需要使用,则用户名存储在pinia中。
Pinia的使用
下载pinia包
npm install pinia
或
yarn add pinia
创建pinia实例并注册
//main.js
//导入
import { createPinia } from 'pinia'
//创建pinia实例
const pinia = createPinia()
//注册pinia实例
app.use(pinia)
定义仓库
在/src/store/xxx.js文件下,定义仓库。
store是用defineStore()定义的,它的第一个参数要求是独一无二的名字,这个名字也被用作id,是必须传入的,pinia将用它来连接store和devtools,我们将返回的函数命名为use..Store,这样符合组合式函数风格的约定。
当组件需要获取这个共享仓库时,导入我们通过defineStore()定义的仓库,使用方法通过如下示例会更好理解。
使用示例
stock.js (组合式定义store)
//导入定义仓库函数
import { defineStore } from 'pinia'
import { ref } from 'vue'
//定义仓库
//defineStore(仓库id,函数或对象)
//函数传参
export const useStockStore=defineStore('stock',()=>{
//提供共享数据
const stock=ref(20)
//提供修改数据的方法
//增加stock数据
function addStock(){
stock.value++
}
//减少stock数据
function subStock(){
stock.value--
}
//返回数据和方法
return{
stock,
addStock,
subStock
}
})
或者 stock.js(选项式定义store)
export const useStockStore=defineStore('stock',{
//state:存放共享数据,类似于 setup传参时的ref或reactive,这里的数据是响应式的
state:()=>({
stock:0
}),
//getters:存放计算属性
getters:{
double:(state)=> state.stock*2
},
//actions:存放修改数据的函数
actions:{
addStock(){
//this指向当前state对象
this.stock++
},
subStock(){
this.stock--
}
}
})
Add.vue 获取共享数据
<template>
<div class="add">
<h3>Add组件</h3>
<p>已知库存数:{{ stockStore.stock }}</p>
<button @click="stockStore.addStock()">库存+1</button>
</div>
</template>
<script setup>
//导入useStockStore函数
import { useStockStore } from '@/store/stock.js'
//调用函数,获取pinia仓库
const stockStore = useStockStore()
</script>
<style scoped>
</style>
Sub.vue
<template>
<div class="sub">
<h3>Sub组件</h3>
<p>已知库存数:{{stockStore.stock}}</p>
<button @click="stockStore.subStock()">库存-1</button>
</div>
</template>
<script setup>
//导入useStockStore函数
import { useStockStore } from '@/store/stock.js'
//调用函数,获取pinia仓库
const stockStore = useStockStore()
</script>
<style scoped>
</style>
App.vue
<template>
<h2>根组件</h2>
库存总数:<input type="number" v-model.number="stockStore.stock" />
<hr />
<Add />
<hr />
<Sub />
</template>
<script setup>
import Add from './components/Add.vue'
import Sub from './components/Sub.vue'
import { useStockStore } from './store/stock'
const stockStore = useStockStore()
</script>
<style>
#app{
width: 350px;
margin: 100px auto;
padding: 5px 10px;
border: 1px solid #ccc;
}
</style>
ElementPlus组件库
以下是通过ElementPlus官方文档的学习笔记,官方文档链接如下:
ElementPlus组件库是什么
由饿了吗团队开发的,是一个基于vue3的PC端免费的组件库,目的就是为开发者提供一套灵活而优雅的组件,里面包含很多常见组件:比如按钮、表单、表格、字体图标等,还有一些高级组件,比如日期选择器、对话框。
ElementPlus组件库的安装
安装
第一种方法
npm install element-plus
第二种方法
yarn add element-plus
第三种方法
pnpm install element-plus
这三种按照个人喜好选择一种即可。
引入
如果对打包后的文件大小不是很在乎,可以使用完整引入,一般而言PC端不太在意这个,所以这里我们使用完整引入。
在main.js中导入并注册
// main.js
import { createApp } from 'vue'//导入ElementPlus组件库
import ElementPlus from 'element-plus'//导入样式
import 'element-plus/dist/index.css'
import App from './App.vue'const app = createApp(App)
//注册,这里是全局注册,一旦注册了,可以在任意vue文件中使用ElementPlus提供的组件
app.use(ElementPlus)
app.mount('#app')
测试
我们进入官方文档
一个 Vue 3 UI 框架 | Element Plushttps://element-plus.org/zh-CN/选择组件
查看组件库中提供的组件源代码,将其拷贝到我们的vue文件中,如果能正常显示,就代表安装成功了
如下:
常用组件
Form表单组件
多选框分组
const form = reactive({
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: '',
})
这里 el-checkbox-group v-model="form.type",form.type如上所示是一个数组,这里多个选项我们需要定义一个数组来接收。
el-checkbox value="Online activities";这里的value属性是给type属性收集勾选选项的值使用的
<el-checkbox-group v-model="form.type">
<el-checkbox value="Online activities" name="type">
Online activities
</el-checkbox>
<el-checkbox value="Promotion activities" name="type">
Promotion activities
</el-checkbox>
<el-checkbox value="Offline activities" name="type">
Offline activities
</el-checkbox>
<el-checkbox value="Simple brand exposure" name="type">
Simple brand exposure
</el-checkbox>
</el-checkbox-group>
单选框分组
这里的resource由上面form对象的定义可以看出,他不是一个数组,因此只能那个接收一个。
<el-radio-group v-model="form.resource">
<el-radio value="Sponsor">Sponsor</el-radio>
<el-radio value="Venue">Venue</el-radio>
</el-radio-group>
单个表单项校验
单个表单项的校验,需要做3处绑定
1、el-form
:model="表单对象"
:rules="校验规则对象"
2、el-form-item:
prop="要校验的字段名称"
3、表单控件:
v-model="数据"
如下:
<el-form :model="form" :rules="rules" label-width="auto" style="max-width: 600px">
<el-form-item label="Activity name" prop="name">
<el-input v-model="form.name" />
</el-form-item>
这里的form就是我们创建好的,用来接收表单数据的对象
const form = reactive({
name: '',
region: '',
date1: '',
date2: '',
delivery: false,
type: [],
resource: '',
desc: '',
})
rules是我们定义好的表单规则,要校验的属性名:[{},{}],一个属性可以绑定多个校验规则
const rules = {
name:[
{
//必填项
required: true,
//不满足条件的错误提示信息
message: 'Please input activity name',
//检验的触发时机:blur是在失去焦点的时候
trigger: 'blur'
},
{
//type:'date' 'array' 限制输入的类型
//长度限制
min: 3,
max: 50,
message: 'Length should be 3 to 50',
trigger: 'blur'
}
]
}
这里prop的值是我们要校验的属性名,与form对象中定义的名字要保持一致。
表单组件整体校验
进行整体校验前,应要先给每个表单项绑定检验方法,也就是表单项校验方法
整体校验步骤如下:
- 通过ref属性,获取form表单组件实例
- 在form表单组件绑定ref属性,在js中通过对应的ref属性.value获取表单组件实例,在调用form提供的validate函数进行校验。
<template>
<el-form ref="formRef" :model="form" :rules="rules" label-width="auto" style="max-width: 600px" >
//……
</template>
import { ref } from 'vue'
const formRef = ref(null)
const onSubmit=()=>{
formRef.value.validate((valid) => {
if (valid) {
console.log('验证通过')
} else {
console.log('验证失败')
}
})
}
重置表单组件内容
const onCancel = () => {
formRef.value.resetFields()
}
form表单组件关于验证的函数
名称 | 说明 |
---|---|
validate((valid)=>{ }) | 表单整体校验,全部通过valid为true,否则为false |
resetFields() | 重置表单(把表单的值恢复成默认值,另一个会移除红色的错误校验结果) |
组件库提供的图标
使用组件库提供的图标,我们先下载对应的包
npm install @element-plus/icons-vue
组件库提供类似于下面这种的图标
在main.js中导入我们需要使用的图标,如下导入User和Lock
//main.js
import {User,Lock} from '@element-plus/icons-vue'
app.component(User.name,User)
app.component(Lock.name,Lock)
导入后,我们这里通过输入框的prefix-icon和suffix-icon属性来添加图标
<el-input v-model="username" placeholder="请输入用户名" prefix-icon="User"></el-input>
效果如下
Table表格组件
el-table:表格组件
data:数据源,也就是我们创建的数据数组名
border:添加列之间的线
stripe:设置表格斑马纹样式
style:行内样式
el-table-colum:表示一列
label:类名
prop:要填充的数据属性名称,与数据源数组里的数据对象名保持一致
对表格的列进行自定义
通过对表格的列进行自定义,我们可以添加样式
要对列进行自定义,el-table-colum中就不传prop属性,我们通过作用域插槽定义我们想要的结构。
<el-table-column label="Date" width="180">
<template #default="obj">
<el-icon :size="14">
<Timer />
</el-icon>
<span>{{ obj.row.date }}</span>
</template>
</el-table-column>
通过slot可以获取到row、column、$index和store,我们将这些属性传递给obj(只是一个变量名字)对象,在通过这个对象访问这些属性,也可以直接对要获取的属性进行解构。
通过el-icon标签设置图标的大小。
效果如下:
Tree树形组件
示例效果如下:
如下代码:
<template>
<el-tree
style="max-width: 600px"
:data="data"
:props="defaultProps"
@node-click="handleNodeClick" />
</template>
<script lang="ts" setup>
interface Tree {
label: string
children?: Tree[]
}
const handleNodeClick = (data: Tree) => {
console.log(data)
}
const data: Tree[] = [
{
label: 'Level one 1',
children: [
{
label: 'Level two 1-1',
children: [
{
label: 'Level three 1-1-1',
},
],
},
],
},
{
label: 'Level one 2',
children: [
{
label: 'Level two 2-1',
children: [
{
label: 'Level three 2-1-1',
},
],
},
{
label: 'Level two 2-2',
children: [
{
label: 'Level three 2-2-1',
},
],
},
],
},
{
label: 'Level one 3',
children: [
{
label: 'Level two 3-1',
children: [
{
label: 'Level three 3-1-1',
},
],
},
{
label: 'Level two 3-2',
children: [
{
label: 'Level three 3-2-1',
},
],
},
],
},
]
const defaultProps = {
children: 'children',
label: 'label',
}
</script>
1、el-tree标签的data属性绑定数据源数组,这个数组通过children来体现层级结构,可以不断嵌套,l数组内label标签树形为展示内容。
2、el-tree标签的props属性,指明渲染的属性名,默认渲染的是children和label,如果后台返回树形数据源里不叫label和children,那么可以通过props进行配置,指明children和label在数据源数组中对应属性名。
3、@node-click="handleNodeClick"节点点击事件,这里data是当前节点对象
const handleNodeClick = (data: Tree) => {
console.log(data)
}
4、给树形组件添加选择框,给el-tree标签添加 show-checkbox 属性
5、设置每次只有一个节点可以展开,给el-tree标签添加 accordion 属性
6、设置默认所有节点都展开,给el-tree标签添加 default-expand-all 属性
自定义节点内容
节点的内容支持自定义,我们可以在节点区添加按钮或者图标等,对树节点内容进行自定义有两种方法:render-content 和 scoped slot,这里使用 scoped slot,scoped slot会传入两个参数node和data,分别表示当前节点的Node对象和当前节点的数据,本质还是使用作用域插槽的方式。
<el-tree>
<template #default="{node,data}">
//自定义结构
</template>
</el-tree>
Dialog对话框组件
1、这里el-dialog使用v-model绑定一个属性值,为true则对话框显示,false不显示,默认为false,当点击按钮时,属性值变为true。
<template>
<el-button plain @click="dialogVisible = true">
Click to open the Dialog
</el-button>
<el-dialog
v-model="dialogVisible"
title="Tips"
width="500"
:before-close="handleClose"
>
<span>This is a message</span>
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="dialogVisible = false">
Confirm
</el-button>
</div>
</template>
</el-dialog>
</template>
<script lang="ts" setup>
import { ref } from 'vue'
import { ElMessageBox } from 'element-plus'
const dialogVisible = ref(false)
const handleClose = (done: () => void) => {
ElMessageBox.confirm('Are you sure to close this dialog?')
.then(() => {
done()
})
.catch(() => {
// catch error
})
}
</script>
2、el-dialog的title属性表示对话框标题显示的内容
3、:before-close="handleClose"表示对话框关闭前的回调函数 ,每次点击❌图标,或取消的时候,会触发绑定的回调函数
4、自定义对话框内容,使用默认插槽
<template #default>
<el-form>
<el-form-item label="账号">
<el-input></el-input>
</el-form-item>
<el-form-item label="密码">
<el-input></el-input>
</el-form-item>
</el-form>
</template>
5、具名插槽footer,自定义底部操作内容,具名插槽header自定义头部内容。
<template #footer>
<div class="dialog-footer">
<el-button @click="dialogVisible = false">Cancel</el-button>
<el-button type="primary" @click="dialogVisible = false">
Confirm
</el-button>
</div>
</template>
Menu菜单组件
为网站提供导航功能的菜单
完整代码如下:
<template>
<el-menu active-text-color="#ffd04b" background-color="#545c64" class="el-menu-vertical-demo" default-active="2"
text-color="#fff" @open="handleOpen" @close="handleClose">
<el-sub-menu index="1">
<template #title>
<el-icon>
<location />
</el-icon>
<span>Navigator One</span>
</template>
<el-menu-item-group title="Group One">
<el-menu-item index="1-1">item one</el-menu-item>
<el-menu-item index="1-2">item two</el-menu-item>
</el-menu-item-group>
<el-menu-item-group title="Group Two">
<el-menu-item index="1-3">item three</el-menu-item>
</el-menu-item-group>
<el-sub-menu index="1-4">
<template #title>item four</template>
<el-menu-item index="1-4-1">item one</el-menu-item>
</el-sub-menu>
</el-sub-menu>
<el-menu-item index="2">
<el-icon><icon-menu /></el-icon>
<span>Navigator Two</span>
</el-menu-item>
<el-menu-item index="3" disabled>
<el-icon>
<document />
</el-icon>
<span>Navigator Three</span>
</el-menu-item>
<el-menu-item index="4">
<el-icon>
<setting />
</el-icon>
<span>Navigator Four</span>
</el-menu-item>
</el-menu>
</template>
<script lang="ts" setup>
import {
Document,
Menu as IconMenu,
Location,
Setting,
} from '@element-plus/icons-vue'
const handleOpen = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
const handleClose = (key: string, keyPath: string[]) => {
console.log(key, keyPath)
}
</script>
<style>
.el-menu{
width: 350px;
}
</style>
el-menu标签属性
- active-text-color:选中文本颜色
- background-color:菜单背景颜色
- default-active:默认选中的菜单,根据el-sub-menu的index属性
- text-color:文字的默认颜色
- @open:sub-menu菜单展开触发的事件
- @close:sub-menu菜单关闭触发的事件
菜单嵌套
如果菜单项需要包含子菜单使用 el-sub-menu内包含子菜单,不需要则直接使用el-menu-item标签,通过插槽设置菜单内容
<el-sub-menu index="1-4">
//当前菜单项显示的内容
<template #title>item four</template>
//这里可以继续嵌套el-sub-menu
<el-menu-item index="1-4-1">item one</el-menu-item>
</el-sub-menu>
添加图标
菜单项添加图标可以使用如下格式:
<el-menu-item index="2">
<el-icon><icon-menu /></el-icon>
<span>Navigator Two</span>
</el-menu-item>
菜单分组
若需要将子菜单进行分组,可以通过el-menu-item-group标签来实现
<el-menu-item-group title="Group One">
<el-menu-item index="1-1">item one</el-menu-item>
<el-menu-item index="1-2">item two</el-menu-item>
</el-menu-item-group>