1、Mock方法post传参
2、响应式变量ref、reactive、toRef、 toRefs
3、状态管理工具pinia的使用
4、状态管理工具pinia的订阅
5、插槽slot及作用域
6、父传子通过provide、inject
7、父传子非props属性集合 useAttrs
8、父传子props
9、父传子事件defineEmits
10、父调用子的变量或方法defineExpose
11、事件总线mitt
12、导出excel文件
13、源码下载
vue3学习做的Demo
1、Mock方法post传参
get方法之前文档已有记录,这里主要是post传过去的参数,如何在Mock方法中取得,看代码QueryParam是查询是参数对像,有属性OrderNum和Status。
// 调用
axios.post("/api/queryshops", QueryParam).then((res) => {
DataObj.Shops = res.data.Shops;
});
......
// 在mock方法文件中
{
url: '/api/queryshops',
method: 'post',
response: ({ body }) => {
const OrderNum = body['OrderNum']
const Status = body['Status']
......
return {
Shops,
}
},
}
2、响应式变量ref、reactive、toRef、 toRefs
创建响应式变量reactive主要用于数组和对象,ref用于简单变量字符串、数字等;toRef响应式对象上的某个属性新创建一个ref。并保持对源属性的响应式连接。 toRefs将响应式对象的每个属性都创建一个ref。 特别注意ref类型的变量在模板中直接使用,在script中需要加.value访问
let person = reactive({
name: '张三',
age: 28,
sex: '男',
job: {
name: 'UI开发',
salary: '20K'
}
})
const name = toRef(person, 'name')
const { sex, job } = toRefs(person)
const TestClick = () => {
name.value = '张三四'
job.value.salary = '30k'
job.value.name = '后端开发'
}
3、状态管理工具pinia的使用
// cmd命令行模式下 安装包
npm install pinia
// main.ts引入
import { createPinia } from 'pinia'
......
const pinia = createPinia()
app.use(pinia)
// 建文件src/store/index.ts
import { defineStore } from 'pinia'
/*
state:数据仓库,用来存数据的。
getters:获取数据的。
actions: 同步异步都支持
*/
export const mainstore = defineStore('mainstore', {
state: () => {
return {
subTitle: '订单',
author: '',
name: '王二',
age: 13,
sex: '男',
socre: [87, 98, 100, 100, 86],
book: <Book>{}
}
},
// 取数据
getters: {
// 普通函数可以用this
getSubTitle(): string {
return this.subTitle + '!'
},
// 箭头函数 不能用this,直接用state
getName: (state): string => {
return state.name
},
// 带参数,返回一个新函数
getAge(state) {
return (num: number) => state.age + num
},
getSex(state) {
return state.sex
},
getScoreSum(state) {
return state.socre.reduce(function (prev, curr) {
return prev + curr
})
},
},
// 同步异步都可
actions: {
changeSubTitle(data: string) {
this.subTitle = data
},
changeScore(data: number) {
this.socre.push(data)
},
changeAge(data: number) {
this.age = this.age + data
},
setAuthor(msg: string) {
// 模拟ajax请求
setTimeout(() => {
this.author = msg
}, 1000)
},
}
})
// 页面中使用
import { mainstore } from '@/store/index'
// pinia的使用
const store = mainstore()
// 直接调用action
store.changeSubTitle('订单查询')
store.setAuthor('作者:Sun')
// 和toRefs类似 得到的都是响应式的变量
const { getSubTitle } = storeToRefs(store)
4、状态管理工具pinia的订阅
修改state、调用action都会给你回调的机会
import { mainstore } from '../store/index'
const store = mainstore()
store.$subscribe((mutation, state) => {
/*
* mutation主要包含三个属性值:
* events:state改变的具体数据,包括改变前的值和改变后的值
* storeId:是当前store的id
* type:用于记录这次数据变化是通过什么途径,主要有三个分别是
* “direct” :通过 action 变化的
”patch object“ :通过 $patch 传递对象的方式改变的
“patch function” :通过 $patch 传递函数的方式改变的
*
* */
console.log(mutation)
console.log(state)
})
store.$onAction(
({
name, //action 函数的名称
store, //store 实例,这里是 mainStore
args, //action 函数参数数组
after, //钩子函数,在action函数执行完成返回或者resolves后执行
onError, // 钩子函数,在action函数报错或者rejects后执行
}) => {
console.log('name===>', name)
console.log('args===>', args)
console.log('store===>', store)
// result是action最后return的内容
after((result) => {
console.log('after result===>', result)
})
onError((error) => {
console.log('onError error===>', error)
})
},
false, // 默认是false,设置为true的时候,组件卸载时,订阅依然有效
)
5、插槽slot及作用域
<!--这是在子组件中 btn是插槽名称listquery是要传的参数 -->
<slot name="btn" :listquery="listQuery"></slot>
<!--这是在父组件中 btn是插槽名称,通过slots.listquery可以访问传过来的参数 -->
<child>
<template #btn="slots">
<el-form-item label="">
<el-button @click="exportExcel(slots.listquery)" icon="Check" type="primary">导出</el-button>
</el-form-item>
</template>
</child>
6、父传子通过provide、inject
父传子,可跨代包括子的子的子......
// 父组件中 他可以直达任意子组件 包括子的子 ...
provide('subTitle', getSubTitle)
// 子组件中 完成标题内容
// 接收父组件传过来的值 包括 父组件 父的父 ...
const subTitle = ref(inject('subTitle') as string)
7、父传子非props属性集合 useAttrs
<!-- 父组件中 -->
<child ref="datatable" @initlistquery="initquery" :options="options" title="Demo" sytle="width:100%" class="item"
id="1:"></child>
// 子组件中
// useAttrs: 非props属性集合 包含父作用的class、style id 等等 模板中可以直接用$attrs绑定
const attr = useAttrs()
const title = ref(attr.title)
8、父传子props
// 在父组件中
<child ref="datatable" :options="options"></child>
// 子组件中 取props 父组件传过来的
interface option {
value: number,
label: string
}
// 接收父组件传过来的值
defineProps({
options: {
type: Array<option>,
default: () => []
},
})
9、父传子事件defineEmits
子组件接收父传过来的事件,在子组件中调用。
<!--父组件中-->
<child ref="datatable" @initlistquery="initquery"></child>
// 子组件中
// 接收父组件传过来的事件。方便子组件调用父组件定义的事件
const emits = defineEmits(['initlistquery'])
// 生命周期的钩子函数。挂载完毕调用
onMounted(() => {
emits('initlistquery', listQuery)
QueryData(listQuery);
});
10、父调用子的变量或方法defineExpose
在子组件中通过defineExpose暴露变量或方法以供父组件调用
// 子组件中
// defineExpose直接使用 用它来暴露变量和方法
defineExpose({
Statusfilter,
CalMoney,
DataObj,
QueryData
});
<!--父组件中-->
<child ref="datatable"></child>
// 注意子组件上 ref='datatable' 取到子组件,调用他暴露出来的变量和方法
const datatable = ref()
// 调用子组件暴露出来的变量和方法 子组件中defineExpose暴露
const modify = () => {
var Shops = datatable.value.DataObj.Shops
......
}
11、事件总线mitt
// 安装
npm install mitt
// src/utils/eventBus.ts
import mitt from 'mitt'
const emitter = mitt()
export default emitter
// 在vue页面中
import mitter from '@/utils/eventBus'
const TestStore = () => {
mitter.emit('nameChange', { name: 'sun', age: 26 })
}
// 在vue另一页面中
mitter.on('nameChange', (data) => {
console.log(data)
})
onBeforeUnmount(() => {
mitter.off('nameChange')
})
12、导出excel文件
// cmd命令行安装这两个包
npm install xlsx
npm install -S file-saver
// vue文件中代码
const formatJson = (
filterVal: string[],
jsonData: { ShopName: string; OrderNum: string; Status: string }[],
) => {
return jsonData.map((v) =>
filterVal.map((j) => {
if (j === 'OrderMoney') {
return datatable.value.CalMoney(v)
} else if (j === 'Status') {
return datatable.value.Statusfilter(v[j])
} else {
return v[j]
}
}),
)
}
// 导出excel
const exportExcel = (param: { OrderNum: string }) => {
if (param.OrderNum) {
console.log(param.OrderNum)
}
import('../vendor/useExportExcel').then((excel) => {
const table = datatable.value.DataObj.Shops
const tHeader = ['商店名称', '订单编号', '金额', '状态'] //自定义列名
const filterVal = ['ShopName', 'OrderNum', 'OrderMoney', 'Status'] //对应自段
const data = formatJson(filterVal, table)
console.log(data)
excel.exportJsonToExcel({
multiHeader: [],
merges: [],
header: tHeader,
data,
filename: 'test',
autoWidth: true,
bookType: 'xlsx',
})
})
}
评论 (0)