vue3-Mock-pinia-组件通信-导出excel

Admin
2022-08-02 / 0 评论 / 79 阅读 / 正在检测是否收录...

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
QQ图片20220802144207.png

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',
    })
  })
}

13、源码下载

0

评论 (0)

取消