写点什么

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

作者:默默的成长
  • 2022-10-17
    山东
  • 本文字数:2674 字

    阅读完需:约 1 分钟

什么是函数式组件->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 传值进行组件间的数据交互


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 容器


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-10-11 加入

还未添加个人简介

评论

发布
暂无评论
面向函数编程:关于函数式组件、dialog的api化_前端_默默的成长_InfoQ写作社区