vue3时代别再写mixin,快来试试hooks

一、先来了解下什么是mixin

mixin是一种思想,一种混入的思想。混入的内容就是可以在被混入的地方使用,他会自动的将混入的东西准确的分配到指定的组件中。在vue中,mixin相当于指定混入的变量&函数放入他不混入时候该放的地方。可以认为,vue中的mixin就是相当于组件中的组件。

1.1 mixin解决了什么问题?

mixin解决了两种复用:

  1. 逻辑函数的复用
  2. vue 组件配置复用

1.2 使用

在vue中,mixin定义的就是一个对象,对象中放置的vue组件相应的选项式API和对应的生命周期钩子

export const mixins = {
  data() {
    return {};
  },
  computed: {},
  created() {},
  mounted() {},
  methods: {
  	 clickMe() {
      console.log("我是mixin中的点击事件");
    },
  },
};

mixin中除了不能把组件中的template模版抽出来,其他任何options-API都可以抽出来放在mixin中(vue2中的所有逻辑无非就是放在data、methods、computed、watch中,这些都可以原封不动放在mixin中)

vue中使用导出的mixin

<template>
  <div id="app">
    <img alt="Vue logo" src="./assets/logo.png" />
    <button @click="clickMe">点击我</button>
  </div>
</template>

<script>
import { mixins } from "./mixin/index";
export default {
  name: "App",
  mixins: [mixins], // 注册mixin,这样mixin中所有的钩子函数等同于组件中钩子
  components: {},
  created(){
    console.log("组件调用minxi数据",this.msg);
  },
  mounted(){
    console.log("我是组件的mounted生命周期函数")
  }
};
</script>

1.3 注意

mixin中和vue组件中相同的钩子的优先级:

mixin中的生命周期函数会和组件的生命周期函数一起合并执行。
mixin中的data数据在组件中也可以使用。
mixin中的方法在组件内部可以直接调用。
生命周期函数合并后执行顺序:先执行mixin中的,后执行组件的。

1.4 存在的优缺点

优点:
组件中钩子函数的注册复用
缺点:
相同钩子中注册的函数名相同会发生冲突(vue中冲突的解决方案是本组件中优先级高于mixin)
定位错误需要花费时间
滥用会造成维护问题

二、hooks

我们开发中会自动抽象出逻辑函数放在utils中,utils中放的纯逻辑,不存在属于组件的东西,例如methods中定义的纯函数等。而hooks就是在utils的基础上再包一层组件级别的东西(钩子函数等)。例如:我们每次点击button都会弹出一个弹窗,自动显示当前日期。但是我将函数放在util中,每次复用都需要click=handleClick 函数放入日期函数,通过handleClick函数管理utils,那么我不如直接将handleClick也封装起来,下次直接调用,复用了methods注册的环节

2.1 hooks和utils的区别:

hooks中如果涉及到ref,reactive,computed这些api的数据,那这些数据是具有响应式的,而utils只是单纯提取公共方法就不具备响应式,因此可以把hook理解为加入vue3 api的共通方法

2.2 使用例子:

使用hooks入门的例子:
hooks文件一般是都出一个函数,例如:我需要hooks导出一个公用的name变量和setName函数

import {ref} from 'vue'
// 导出1个 name_hooks.ts文件
// hooks中不用写在setup中
export const name_hooks = function(value: string) {
   const name = ref('')
   const setName = (value: string) => {
       name.value = value
   }
   return {
      name, setName
   }
}

vue 引入hooks文件

<template>
    <div>{{ name }}</div>
    <select @change="setName"></select> // 这里select组件的change事件会自动传value值
    // 然后value值作为传参传递给setName
</template>
import { name_hooks } from './name_hooks'
export default defineComponent({
    setup() {
       const { name, setName } = name_hooks() // 注意: 通常需要通过解构赋值将需要的属性方法添加进组件中
       return {
          name, setName
       }
    }
})

以上hooks使用方法,常见的操作:
1.导出的hooks是一个函数,函数中可以使用ref,reactive,这样hooks定义的变量和方法如同在组件中一样
2.hooks函数通常返回一个对象,对象中是双向绑定的变量,在vue中间引用的时候第一件事就是解构

2.3 自定义hook

举例:表单弹框业务,属于很常见的业务场景,新增打开弹框,表单校验,编辑打开弹框进行数据回显等

import { ref, nextTick, Ref, unref } from 'vue'
import { setFormValues } from "@/utils/setFormValue.ts";
// 补充setFormValues 代码如下
/**  表单对象的赋值操作
const setFormValues=(form:any,data:any):void=>{
  Object.keys(form).forEach(key=>{
    if(Reflect.has(data,key)){
      form[key]=data[key];
    }
  })
}
export{
  setFormValues
}
*/ 


export default function useFormModal(formData: object, formRef: Ref) {
    const visible = ref(false);
    const itemInfo = ref({});
    const validStatus = ref<boolean>(false);
    //校验表单
    const validForm = async () => {
        if (!formRef) return
        await unref(formRef).validate((valid => {
            validStatus.value = valid;
        }))
        return validStatus.value;
    };

    // 打开弹框
    const openModal = (item: object = {}) => {
        itemInfo.value = item;
        // 打开弹框
        visible.value = true;
        nextTick(() => {
            if (!formRef) return;
            // 情况表单
            formRef.value.resetFields();
            // 表单赋值
            setFormValues(formData, item);
        })

    };

    return {
        visible,
        validForm,
        openModal,
        itemInfo
    }
}

使用
子组件表单

import type { ElForm } from "element-plus";
import useFormModal from "hooks/useFormModal";

type FormInstance = InstanceType<typeof ElForm>;
const ruleFormRef = ref<FormInstance>();
const { visible, validForm, itemInfo, openModal } = useFormModal(
  form,
  ruleFormRef
);

// 提交表单
const submitHandle = async () => {
  console.log("kjjnkjk", form, itemInfo.value);
  const { submitForm } = useSubmit({
    ...form,
  });
  const valid = await validForm();
  if (!valid) return;
  await submitForm();
  visible.value = false;
  emits("success");
};

defineExpose({
  //向父组件暴露方法
  openModal,
});

父组件触发表单

<DialogModel ref="modalDom" @success="getData" />



const modalDom = ref(null) as Ref;

// 新增可以传{}, 编辑传整个数据
const openModel = (item: object) => {
  modalDom.value.openModal({
    ...item,
  });
};

// 添加编辑成功后
const getData = () => {}
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值