Vue3 登录注册模态框

源码: 地址

前段时间写下的Vue.extend 登录注册模态框是基于 Vue 2.x 中 Vue.extend 版本来做

而这段时间内都是在学习 Vue 3.0 且也完全重构了该项目,记录学习下重构的过程与思考。

组件

组件还是那几个组件,需要改动的地方不是很多,只是把其改成 Vue 3 的形式
image.png
sigin.vueregister.vue 组件分别修改

// sigin.vue




// register.vue



index.vue 组件




子类

由于 Vue.extend 被废弃,Vue 3 这里使用 hrender 两个函数,我们来看下这两个函数介绍,具体使用情况,可以查看文档

  • h 函数参数:

    • type 它的类型可以是HTML 标签名、组件或异步组件
    • props 是一个对象,与我们模板组件内的 attributeprop、事件相对应
  • render 渲染函数接收一个组件和容器

修改 index.js

import { render, h } from "vue";
import ModalCops from "./index.vue"; 

let instance;

const ModalBox = ({type, ok}) => {
  if (instance) {
    instance.component.proxy.doClose();
  }

  // 组件接收的 props
  let _opt = {
    visible: true,
    type,
    close: () => {
      return new Promise(resolve => {
        const before = ok ? ok() : false;

        if (before && before.then) {
          before.then(
            () => resolve(true),
            () => {
              console.log("reject");
            }
          );
        } else if (typeof before === "boolean" && before !== false) {
          resolve(true);
        }
      });
    }
  };

  instance = h(ModalCops, _opt); // 组件

  const container = document.createElement('div');

  // 组件销毁时
  instance.props.onDestroy = () => {
    render(null, container);
  }

  // 渲染组件
  render(instance, container);
  
  // 将模态框添加至 body
  document.body.appendChild(container.firstElementChild);

};

ModalBox.sigin = ok => {
  return ModalBox({
    type: "sigin",
    ok
  });
};

ModalBox.register = ok => {
  return ModalBox({
    type: "register",
    ok
  });
};

ModalBox.close = () => {
  instance.component.proxy.doClose();
  instance.component.proxy.show = false;
};

export default {
  install(app) {
    app.config.globalProperties.$loginer = ModalBox;
  }
};

最后在全局挂载

import { createApp } from 'vue'
import Login from './Login.vue'
import LoginModal from "./LoginModal/index.js";
createApp(Login).use(LoginModal).mount('#app')

Login.vue 组件中使用

import { ref, getCurrentInstance } from "vue";
export default {
  setup(props) {
    const { proxy } = getCurrentInstance();

    const isOk = ref(true);

    const onLogin = (type) => {
      const funcs = {
        sigin: () => {
          console.log("登录请求");
        },
        register: () => {
          console.log("注册请求");
        },
      };
      proxy.$loginer({
        type,
        ok: () => {
          return new Promise((resolve, reject) => {
            if (isOk.value) {
              funcs[type]();
              resolve();
            } else {
              reject();
            }
          });
        },
      });
    };

    return {
      isOk,
      onLogin,
    };
  },
};

最后还是放一下效果

logo.gif

注意

在修改其中的部分代码时,我们需要注意的几个点

  • 全局挂载

Vue 3 还是提供 use 函数,来使用我们的插件,不过需要挂载的属性变了,不在是直接挂载在 Vue.prototype 上,而是需要添加到全局实例的 config.globalProperties 对象上

  install(app) {
    app.config.globalProperties.$loginer = ModalBox;
  }
  • 组件销毁时的 onDestroy 事件

这个事件对应了 index.vue 模板组件中 emit 出的 destroy 事件,这是由于 Vue 源码中 packages\runtime-core\src\componentEmits.tsemit 函数给我们事件自动加上了 on 前缀
image.png

总结

学了就要用。本次是在学习 Vue3 后就在项目中全面使用,其中也碰到不少需要规避的坑,也尝试着阅读部分源码,收获满满

欢迎关注【前端学啥】一起交流
image

你可能感兴趣的:(前端vue.js)