美文网首页
【组件2】对话框 - Dialog

【组件2】对话框 - Dialog

作者: darkTi | 来源:发表于2022-03-31 18:14 被阅读0次

确定API

  • 要确保你的API和同行的API没有太大不同,否则用户学习成本变高,不利于我们的UI使用;所以我们就可以去copy下同行的API;
  • 提供两种风格:一是标签风格,二是API风格
  • 创建dialog目录;

搭建Dialog 基本架子

  • <Fragment></Fragment>用于把多个div包起来,但是在页面中却不会渲染出来(有点像<template>),所以经常使用<Fragment></Fragment>来代替<div></div>
  • 我们需要在每个className上都写一遍dui-dialog-,岂不是很麻烦?!所以我们写个函数来统一它吧~
  • 返回函数的函数叫做高阶函数;

添加CSS

  • 这里一个小问题,index.scss要引入到example.tsx中样式才有效!!!!只引入到index.tsx中在预览例子的时候样式不起作用!!!!(应该跟生产开发环境文件设置的入口有关)
  • 想要svg受外面字体颜色的控制,加上fill: currentColor;
  • 跟字体相关可以用px、em,跟布局宽度相关可以用min-width结合em;
  • 属性选择器[class^=xx]代表所有以xx开头的类;

添加事件

1、可以自定义按钮
  • 给dialog一个buttons Props,它是个数组;
  • 所以这时又有个小警告了,因为是个数组,需要给每一项设置key,就用到了React.cloneElement
  • 为什么用React.cloneElement,而不是直接button['key'] = index这样添加属性呢,因为报错啊!!!说不能给只读属性key赋值啊!!!
2、给组件的props设置默认值
Dialog.defaultProps = {
  closeonClickMask: false
}
  • 一般设置过默认值后,这个props就是可选的,interface属性那里加上?
3、ReactDOM.createPortal
  • ReactDOM.createPortal,这是由于层级问题引起的,给dialog的层级越小越好,这样也方便用户自己去改;
  • 一般网站架构师会设定好层级
  • 可以在文档中告诉开发者,你如何写可以覆盖我的层级;


    image.png

注意:为了禁止遮罩层来回滑动,在对话框出现的时候document.body.style.overflow='hidden'document.body.style.paddingRight = '17px',关闭的时候恢复document.body.style.overflow='auto'document.body.style.paddingRight = '0'

给Dialog提供便利的API——alert

  • 动态创建组件,即用ReactDOM.render()把组件渲染进div;
  • 关闭组件呢,即还是用ReactDOM.render()渲染组件,只不过是把组件的visible属性变成false;
  • ReactDOM.unmountComponentAtNode()文档
//创建组件和节点
 const div = document.createElement("div");
  document.body.appendChild(div);
  document.body.style.overflow = 'hidden'
  ReactDOM.render(component, div);
//消除组件和节点
//第一句:把这个组件的visible改成false
ReactDOM.render(React.cloneElement(component, {visible: false}), div)
//第二句:把这个组件从div上卸载下来
ReactDOM.unmountComponentAtNode(div)
 document.body.style.overflow = 'auto'
//第三句:清除这个div
div.remove()

comfirm

modal

  • ReactElement和ReactNode区别:ReactElement只能是标签元素,ReactNode还可以是字符串;
  • modal return一个函数出来,有点类似于闭包的形式;
  • 下面代码中button调用函数的形式,要写一个箭头函数去调用close(这个close函数是modal()return出来的函数),直接onClick={close}的话是不可以的,因为解析器是从右往左执行的,这样直接写,它找不到你声明的close在哪里,放在箭头函数中就可以的原因是,函数是延迟执行的,只有点击按钮时才调用函数; 所以在声明函数的时候不要直接去调用它本身!!!
const openModal = () => {
    const close = modal(
      <div>
        <h1>你好</h1>
        <button style={{ color: "purple" }} onClick={() => close()}>
          close
        </button>
      </div>
    );
  };

三者之前的区别

1、是否有按钮
  • alert只有一个【确认】按钮,按钮没有回调函数;
  • comfirm有【取消】、【确认】按钮,且按钮有各自的回调函数;
  • modal没有按钮;
2、传的内容
  • alert和comfirm传的内容仅仅是字符串;
  • modal不仅可以传字符串,还可以传元素,但要保证只有一个根元素;

重构

image.png
  • 写完代码请立即重构,消除重复的代码;
  • 看上图,抽出每个API中的part,可以看出它们的组成很相近,所以可以把它们写成一个公共的函数;

总结

  • scopedClass 高阶函数;
  • React.Fragment
  • 使用&&或者三元表达式来做条件判断,一般不用if...else...来写条件判断,有点麻烦;
  • ReactDOM.createPortal传送门,可以使元素脱离当前位置到达你指定的节点位置;
  • 如何动态去生成一个组件;
  • 闭包传API;

相关文章

网友评论

      本文标题:【组件2】对话框 - Dialog

      本文链接:https://www.haomeiwen.com/subject/tzszfrtx.html