文章目录
- 前言
- 一、页面传值
- 1.1 [props](https://cn.vuejs.org/guide/components/props.html)
- 1.2 [emit](https://cn.vuejs.org/guide/components/events.html)
- 1.3 [store](https://pinia.vuejs.org/zh/getting-started.html)
- 二、实时计算
- 2.1 [watch](https://cn.vuejs.org/guide/essentials/watchers.html)
- 2.2 [computed](https://cn.vuejs.org/guide/essentials/computed.html)
- 2.3 [nextTick](https://cn.vuejs.org/api/general.html#nexttick)
- 三、数据处理
- 3.1 foreach
- 3.2 map
- 四、[el-form校验](https://element-plus.org/zh-CN/component/form.html)
- 总结
前言
基于ts vue 应用梳理
一、页面传值
父子组件相互传值调用相关
1.1 props
<script setup lang="ts" name="taskDelivery">
interface PropsType {eventData: { [key: string] };tableDisplay?: boolean;
}const props = withDefaults(defineProps<PropsType>(), { tableDisplay: true });
</script>
- 定义子组件需要的参数,并默认tableDisplay为true
- props在子组件中不可以被修改
tableDisplay?: boolean;
表示父组件引用时改参数非必须- 参数定义的是驼峰格式,但是父组件引用传参需要用
-
的形式传入:event-data="eventData"
1.2 emit
自定义事件,类似自定义一个click
- 父组件直接触发子组件定义事件。如A(父)组件要实现B(子)组件定义的按钮触发方法
<!-- 子组件事件定义 -->
<button @click="$emit('someEvent')">click me</button>
<!-- 父组件实现 -->
<MyComponent @some-event="callback" />
- 父组件实现事件响应,子组件自定义事件并使用
<!-- 子组件事件定义 -->
<script setup lang="ts">
const emit = defineEmits(['inFocus', 'submit'])function buttonClick() {emit('submit')
}
</script>
<!-- 父组件实现 -->
<MyComponent @submit="impl-submit(params)" />
1.3 store
persist.ts
import { PersistedStateOptions } from "pinia-plugin-persistedstate";/*** @description pinia 持久化参数配置* @param {String} key 存储到持久化的 name* @param {Array} paths 需要持久化的 state name* @return persist* */
const piniaPersistConfig = (key: string, paths?: string[], params?: {}) => {const persist: PersistedStateOptions = {key,// storage: localStorage,storage: sessionStorage,paths,...params};return persist;
};export default piniaPersistConfig;
import { defineStore } from "pinia";
import piniaPersistConfig from "@/stores/helper/persist";
import { getEventDetail } from "@/api/modules/eventServer";export const EventDataStore = defineStore({id: "eventData",state: () => ({eventData: {eventId: "",longitude: 0,latitude: 0,districtCode: ""}}),getters: {// 获取事件IDgetEventId: state => state.eventData.eventId},actions: {setEventData(info) {this.eventData = info;},async updateEventData() {const { data } = await getEventDetail(this.eventData.eventId);this.eventData = data;},async setEventDataByEventId(eventId) {const { data } = await getEventDetail(eventId);this.eventData = data;}},persist: piniaPersistConfig("eventData")
});
const eventDataStore = EventDataStore();function reportCreate() {analysisReportCreate(eventDataStore.eventData.eventId, "20").then(res => {if (res.status == 200) {ElMessage.info("报告生成成功");}});
}
将事件数据eventData保存到store中,供全局调用,并支持任何场景更新store
二、实时计算
2.1 watch
监听器,使用 watch 函数在每次响应式状态发生变化时触发回调函数
export interface ProTableProps {initParam?: any; // 初始化请求参数 ==> 非必传(默认为{})noWatchParam?: boolean; // 更改了initParam数据不请求接口
}// 接受父组件参数,配置默认值
const props = withDefaults(defineProps<ProTableProps>(), {initParam: {}
});
// 监听页面 initParam 改化,重新获取表格数据
watch(() => props.initParam,() => {if (props.noWatchParam) return;getTableList();},{ deep: true }
);
2.2 computed
计算属性描述依赖响应式状态的复杂逻辑,简单的计算逻辑<span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span>
<script setup>
import { reactive, computed } from 'vue'const author = reactive({name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']
})// 一个计算属性 ref
const publishedBooksMessage = computed(() => {return author.books.length > 0 ? 'Yes' : 'No'
})
</script><template><p>Has published books:</p><span>{{ publishedBooksMessage }}</span>
</template>
Vue 的计算属性会自动追踪响应式依赖。它会检测到 publishedBooksMessage 依赖于 author.books,所以当 author.books 改变时,任何依赖于 publishedBooksMessage 的绑定都会同时更新。
2.3 nextTick
当你在 Vue 中更改响应式状态时,最终的 DOM 更新并不是同步生效的,而是由 Vue 将它们缓存在一个队列中,直到下一个“tick”才一起执行。这样是为了确保每个组件无论发生多少状态改变,都仅执行一次更新。
nextTick() 可以在状态改变后立即使用,以等待 DOM 更新完成。你可以传递一个回调函数作为参数,或者 await 返回的 Promise。
三、数据处理
3.1 foreach
const topData = ref([{label: "点对点叫应",value: 38,img: chat,class: "team-traffic"},{label: "语音叫应",value: 29,img: audio,class: "expert-traffic"},{label: "视频叫应",value: 55,img: video,class: "resource-traffic"},{label: "短信通知",value: 12,img: msg,class: "equip-traffic"}
]);
function getStatistic() {demandStatistic(searchParam.value).then(res => {if (res.status === 200) {res.data.forEach((item, index) => {if (topData.value[index]) {topData.value[index].value = item.number;}});}});
}
foreach更新数据value
3.2 map
const initData = () => {postEventBaseList(param).then(res => {if (res.status === 200) {const { list } = res.data;const gradeMap = {"1": { grade: "grade-red", gradeLabel: "特" },"2": { grade: "grade-orange", gradeLabel: "重" },"3": { grade: "grade-yellow", gradeLabel: "较" },"4": { grade: "grade-blue", gradeLabel: "般" },"5": { grade: "grade-gray", gradeLabel: "其" }};data.value = list.map(l => {const { grade, gradeLabel } = gradeMap[l.eventLevelCode];return {...l,title: l.eventTitle,time: l.occurTime,tag: l.eventTypeCodeName,grade: grade,gradeLabel: gradeLabel,place: l.infoAddress};});}});
};
...l
合并map
四、el-form校验
校验救援装备是否被选择,任务内容必填
<el-form ref="ruleFormRef" :model="taskForm" label-width="auto" class="demo-ruleForm" status-icon><el-divider content-position="left">事件信息</el-divider><div>{{ eventData.eventTitle }}</div><div>{{ eventData.infoDescription }}</div><el-divider content-position="left">队伍信息</el-divider><el-descriptions><el-descriptions-item label="救援装备"><el-link type="primary" @click="showEquList">选择队伍装备</el-link><el-form-item prop="equList" :rules="[{ required: true, message: '请选择队伍装备', trigger: ['change', 'blur'] }]"><span style="margin: 0px 10px" v-for="item in taskForm.equList" :key="item.id">{{ item.name }}:{{ item.num }}</span></el-form-item></el-descriptions-item></el-descriptions><el-divider content-position="left">任务内容</el-divider><el-form-item prop="taskContent" :rules="[{ required: true, message: '请输入任务内容', trigger: ['change', 'blur'] }]"><el-inputv-model="taskForm.taskContent"style="width: 100%":rows="2"type="textarea"placeholder="请输入任务内容"required/></el-form-item><div style="display: flex; flex-direction: row-reverse; margin: 15px"><el-button type="primary" size="small" @click="sendTask(data)">任务下发</el-button></div></el-form>
const ruleFormRef = ref();
function sendTask(data) {const params = {list: [{eventId: props.eventData.eventId,equList: taskForm.equList,taskContent: taskForm.taskContent}]};ruleFormRef.value.validate((valid, fields) => {if (valid) {sendTasks(params).then(res => {if (res.status == 200) {ElMessage.success("任务下发成功");//todo 刷新当前列表 点击返回要刷新调度记录dialogVisible.value = false;emits("submit");}});}});
}
总结
vue的应用的api和业务写法总体感觉杂而乱,各种组件拼接到一起的缝合怪,让人总感觉难以入手。
本文主要总结小白近期项目中遇到的一些基础写法,方便后面查找,不具有指导性意义