前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >面向函数编程:关于函数式组件、dialog的api化

面向函数编程:关于函数式组件、dialog的api化

作者头像
默默的成长
发布2022-10-29 16:45:30
4360
发布2022-10-29 16:45:30
举报
文章被收录于专栏:前端记录笔记前端记录笔记

什么是函数式组件->Vue

  • 无状态
  • 无法实例化
  • 内部没有任何生命周期处理函数
  • 轻量,渲染性能高,适合只依赖于外部数据传递而变化的组件(展示组件,无逻辑和状态修改)
  • 在template标签里标明functional
  • 只接受props值
  • 不需要script标签 需要提供一个render方法, 接受一个参数(createElement函数), 方法内根据业务逻辑,通过createElement创建vnodes,最后return vnodes

createElement函数, 三个参数, 第一个参数是html标签或自定义组件,第二个参数一个obj(包含props, on...等等), 第三个参数children(通过createElement构建, 或者字符串)

官方文档

因为函数式组件没有状态,所以他们不需要像vue的响应式系统一样需要经过额外的初始化。 函数式组件仍然会对相应的变化做出响应式改变,比如新传入props,但是在组件本身中,它无法知道数据何时发生了更改,因为它不维护自己的状态。 对于大型应用程序,在使用函数式组件之后,你会看到Dom的渲染,更新会有重大改进

我们为什么要做dialog的api化这件事

dialog的api化等于是基于面向函数式编程的思维方式写代码,但是api化不等于实现函数式组件,这个一定要弄清楚!

首先是解决组件之前的依赖问题,组件间肯定是不能相互依赖的,因为不管是react还是vue,都应该遵循组件化的思想,那么在组件化思想中,非常重要的一点就是委托调用

  • 为什么要委托调用 即开发者A负责开发组件a,开发者B负责开发组件b,组件a与b之间在业务上构成父子关系,但是我们再设计组件的时候,需要把a,b设计成平行关系,即实现数据和业务的解绑和松耦合, 只有在这个前提下,我们才能够实现最小化组件和造轮子组汽车的目标。
  • 委托事件 即a组件与b组件通信时,开发者A不需要关注开发者B具体所实现的业务逻辑,两者间只要和前后端协同一样,约定好入参和回调, 开发者A委托开发者B开发组件b,并完成相应的业务后,通过callback回调事件回传开发者A,开发者A在callback中获取他想要 的response继续自己的业务开发。

弄清楚委托调用这一思想概念后,我们解决掉了组件的依赖问题,把两组件以松耦合的方式拆开,并且实施状态隔离。

那如何进行数据交互就是一个问题了;比如用户组件和其他组件,其他组件如何在不依赖用户组件的情况下获取到用户信息;

props传值

通过props传值进行组件间的数据交互

代码语言:javascript
复制
showModal({
          prams:{ // param即传入组件的props,可传function、object、Nomal
            abc:this.abc,
            item:'xxxxxxxxxxxxs',
          },
          callback:(rsp)=>{
            console.log(rsp);
            if(rsp.ok) console.log('这是成功的回调')
          },
          onClose:(rsp)=>{
            console.log('关闭了弹窗')
          }
        })

实现原理

在document对象里,以body节点为父节点,创建一个div容器,modal弹窗动态渲染在该容器内,modal关闭的同时销毁div容器

代码语言:javascript
复制
import Vue from 'vue';
import { uuid } from '../index';
export function showDialog(elementOrClass, props, isUnique = false, destroyDelay = 0) {

  //现在生成一个具备唯一表示id的divElement by Mothpro
  let dialogContainer = document.createElement('div');
  let id = elementOrClass.name
    ? elementOrClass.name
    : elementOrClass.type && elementOrClass.type.name + '_wrapper';

  if (!isUnique) {
    id += '$' + uuid(8, 16);
  }
  // id = 'test';
  // let t = new Vue(document.getElementById(id));
  // t.$destroy();
  // console.log("----------------------------",t);
  // console.log(t.$delete);
  let removeNodeIfExist = (id) => {
    let domElement = document.getElementById(id);
    if (domElement) {
      //这个地方vue不需要销毁vNode节点,组件会自己销毁,勇辉告诉我的。。。。自动挡真牛逼!! by Mothrpro
      // ReactDom.unmountComponentAtNode(document.getElementById(id));
      domElement.parentNode.removeChild(domElement);

      //这里element-ui的dialog会建立一个叫做v-modal的蒙层,我要在关闭组件的同时销毁他 by Mothpro
      let vModals = document.getElementsByClassName('v-modal')[0];
      if(vModals) vModals.parentNode.removeChild(vModals);
    }
  };
  removeNodeIfExist(id);
  dialogContainer.id = id;
  function handleClose() {
    if (destroyDelay == 0) {
      removeNodeIfExist(id);
    } else {
      setTimeout(() => {
        removeNodeIfExist(id);
      }, destroyDelay);
    }
  }

  let handleClosePropName = 'onClose';
  document.body.appendChild(dialogContainer);
  let com = document.getElementById(id);

  dialogContainer = document.createElement('div');
  let elementId = id + '_';
  dialogContainer.id = elementId;
  com.append(dialogContainer);


  let element = undefined;
  if (typeof elementOrClass == 'function') {
    //FIXME 这是showMoadl传入Class的特殊情况,在我以前有遇到,目前项目里面还没遇到,我也懒得做处理了,但是这里是个坑,留个mark By Mothpro
    //如果是传入了类名 那用props实例化这个类

    // if (props.afterClose) {
    //   //这边请看上面的跟afterClose有关的章节
    //   element = React.createElement(elementOrClass, {
    //     ...props,
    //     afterClose: handleClose,
    //   });
    // } else {
    //   element = React.createElement(elementOrClass, {
    //     ...props,
    //     onClose: handleClose,
    //   });
    // }
  } else {
    //如果传入了一个react element 那就给这个element加上onClose属性并显示
    element = elementOrClass;
  }
  // props = element.props; //这个props可能是传进来的props 也可能是传进来的已经实例化的对象的props 反正就是props
  // UserOnClose=props.onClose; //这个UserOnClose一定是外面定义的onClose来负责关闭后刷新页面等操作

  // element.props[handleClosePropName] = handleClose;
  // console.log(handleClosePropName);
  // ReactDom.render(element, document.getElementById(id));


  new Vue({
    render: (h) => h(element,{
      props:{
        ...props,
        onClose:()=>{
          props.onClose();
          handleClose();
        },

      },
    })
  }).$mount(document.getElementById(elementId));
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-08-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 什么是函数式组件->Vue
  • 我们为什么要做dialog的api化这件事
  • props传值
    • 实现原理
    相关产品与服务
    容器服务
    腾讯云容器服务(Tencent Kubernetes Engine, TKE)基于原生 kubernetes 提供以容器为核心的、高度可扩展的高性能容器管理服务,覆盖 Serverless、边缘计算、分布式云等多种业务部署场景,业内首创单个集群兼容多种计算节点的容器资源管理模式。同时产品作为云原生 Finops 领先布道者,主导开源项目Crane,全面助力客户实现资源优化、成本控制。
    领券
    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档