React.Fragment

portals

Error Boundaries

WEB组件

React.Fragment

想象一个场景,想把td包装为组件添加到table中去,代码如下:

class MyTable extends React.PureComponent {
render() {
rejturn(
<table>
<tbody
<tr>
<MyTd></MyTd>
</tr>
</table>
</tbody>
)
}
}
class MyTd extends React.PureComponent {
render() {
return(
<React.Fragment>
<td>a</td><td>a</td>
</React.Fragment>
)
}
}
 

自定义的MyTable中插入自定义的MyTd.....,对不起直接报错,tr的子元素只能为td而实际上中间还套了一层div。。。。。

为了解决如上问题React.Fragment横空出世

class MyTd extends React.PureComponent {
render() {
return(
<React.Fragment key={1}>
<td>a</td><td>a</td>
</React.Fragment>
)
}
}

补充一下,React.Fragment暂时只支持key这一个属性,还有它可以写成<></>这样的形式,当然它也可以用来减少dom结构的嵌套,如果你不想用二外的div来包裹内容,那么可以使用改组件,其和原生的DocumentFragment相似。

render() {
return (
<>
<ChildA />
<ChildB />
<ChildC />
</>
);
}

portals

想象两个个场景:一、点击父组件中的一个按钮,弹出个弹框,弹框面积要求大于父组件。

场景一解决方案就是将弹窗挂到其他的Dom上面

class Mask extends React.PureComponent {
render() {
return (
//这里我很想知道为什么如果不加top,那么弹窗默认加到最初的div下面
<div style={{position: "absolute",top:"0", width: '400px', height: '400px', border: '1px solid red',pointerEvents:"none" }}></div>
)
}
} class Parent extends React.PureComponent {
constructor(props) {
super(props)
this.state = {
show: false
}
this.show = this.show.bind(this)
}
show() {
let show = !this.state.show
this.setState({
show
})
} render() {
return (
<div style={{ width: '100px', height: '100px', border: '1px solid black' }}>
<button onClick={this.show}>展示弹窗</button>
{this.state.show && ReactDOM.createPortal(<Mask />, document.getElementById('root'))}
</div>
) }
}

结论:对于 portal 的一个典型用例是当父组件有 overflow: hidden 或 z-index 样式,但你需要子组件能够在视觉上“跳出(break out)”其容器。例如,对话框、hovercards以及提示框。

二、组件a与b同级,要求组件b可以捕获a中的某个事件

//index.html中的代码

<html>
<body>
<div id="app-root"></div>
<div id="modal-root"></div>
</body>
</html> //reactjs
const appRoot = document.getElementById('app-root');
const modalRoot = document.getElementById('modal-root'); class Modal extends React.Component {
constructor(props) {
super(props);
this.el = document.createElement('div');
} componentDidMount() {
modalRoot.appendChild(this.el);
} componentWillUnmount() {
modalRoot.removeChild(this.el);
} render() {
return ReactDOM.createPortal(
// this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined ;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。
this.props.children,
this.el,
);
}
} class Parent extends React.Component {
constructor(props) {
super(props);
this.state = {clicks: 0};
this.handleClick = this.handleClick.bind(this);
} handleClick() {
// This will fire when the button in Child is clicked,
// updating Parent's state, even though button
// is not direct descendant in the DOM.
this.setState(prevState => ({
clicks: prevState.clicks + 1
}));
} render() {
return (
<div onClick={this.handleClick}>
<p>Number of clicks: {this.state.clicks}</p>
<p>
Open up the browser DevTools
to observe that the button
is not a child of the div
with the onClick handler.
</p>
<Modal>
<Child />
</Modal>
</div>
);
}
} function Child() {
// The click event on this button will bubble up to parent,
// because there is no 'onClick' attribute defined
return (
<div className="modal">
<button>Click</button>
</div>
);
} ReactDOM.render(<Parent />, appRoot);

尽管 portal 可以被放置在 DOM 树的任何地方,但在其他方面其行为和普通的 React 子节点行为一致。包含事件冒泡。一个从 portal 内部会触发的事件会一直冒泡至包含 React 树 的祖先。由于 portal 存在于 React 树中,而不用考虑其在 DOM 树中的位置。

Error Boundaries

解决的问题:部分 UI 的异常不应该破坏了整个应用

不适用的场景:

  • 事件处理 (了解更多)(使用try/catch)
  • 异步代码 (例如 setTimeout 或 requestAnimationFrame 回调函数)
  • 服务端渲染
  • 错误边界自身抛出来的错误 (而不是其子组件)

应用实例

为什么不用try/catch

       try/catch   用于命令式而react组件是声明式的(jsx无法识别)声明什么需要被渲染

在react16+版本中如果使用错误边界,若错误边界中的组件出现错误,只要能被捕获,那么应用不会整体崩溃,否则,应用将整体unmount。

用开发模式的时候错误边界中组件出错会有警告提示如下:

点击右上角的X之后回到页面仍会看到组件,代表组件并没有崩溃

遗留问题:不知道在生成模式中还会不会弹出这个错误提示,个人觉得不应该存在,否则太影响体验了,我也不知道如何运行生产模式的react,希望知道的可以留言

WEB组件

定义:通过一种标准化的非侵入的方式封装一个组件,每个组件能组织好它自身的 HTML 结构、CSS 样式、JavaScript 代码,并且不会干扰页面上的其他代码

下面来看一个例子,该页面名字为favorite-color.html:

<!-- WebComponent example based off element-boilerplate: https://github.com/webcomponents/element-boilerplate -->
<template>
<style>
.coloured {
color: red;
}
</style>
<p>My favorite colour is: <strong class="coloured">Red</strong></p>
</template>
<script>
(function() {
// Creates an object based in the HTML Element prototype
var element = Object.create(HTMLElement.prototype);
// Gets content from <template>
var template = document.currentScript.ownerDocument.querySelector('template').content;
// Fires when an instance of the element is created
element.createdCallback = function() {
// Creates the shadow root
var shadowRoot = this.createShadowRoot();
// Adds a template clone into shadow root
var clone = document.importNode(template, true);
shadowRoot.appendChild(clone);
};
document.registerElement('favorite-colour', {
prototype: element
});
}());
</script>

在另一个html页面中引入上面的组件:

<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title>My First WebComponent</title>
<link rel="import" href="components/favorite-colour.html" />
</head>
<body>
<favorite-colour></favorite-colour>
</body>
</html>

目前已经有三个基于 WebComponent 标准的框架:X-TagPolymerBosonic

注意:若你正在使用第三方Web组件,其最好的解决方案是编写一个 React组件,以包装该 Web组件。由Web组件触发的事件可能无法通过React渲染树来正确冒泡。

你需要手动捕获事件处理器以处理那些在React组件里的事件。

参考:https://reactjs.org/docs/fragments.html

https://doc.react-china.org/docs/error-boundaries.html

http://blog.csdn.net/meikidd/article/details/44628915

学习React系列(七)——Fragments、Portals、Error Boundaries与WEB组件的更多相关文章

  1. 7.oracle学习门户系列七---网络管理和配置

    oracle学习门户系列七 网络管理和配置 们学习了模式和用户.包含模式定义以及模式的作用. 这篇我么来看下ORACLE数据库中的网络管理和配置.只是这篇好像和上篇没有继承啊.这怎么看? Ok,事实上 ...

  2. 学习React系列(四)——受控组件与非受控组件

    受控组件:通过组件的状态与属性的改变来控制组件 不可控组件:直接通过底层的dom来控制组件(具体来说就是通过绑定再底层dom上的方法来实现的,比如说ref,onChange) 受控组件 functio ...

  3. 学习React系列(十)——Render Props

    解决问题:将行为封装,供多个组件使用(在多个组件之间分享某段代码) 组件中的props属性中包含一个"render"属性(该属性为一个返回值为元素的方法),然后在该组件的rende ...

  4. 学习React系列(九)——高阶函数

    定义:高阶组件就是一个函数,且该函数接收一个组件作为参数,并返回一个新的组件. (上一篇已经说过了高阶组件可以用来解决交叉问题) 一.不要改变原始组件,使用组合 class A extends Rea ...

  5. 学习react系列(八)—— mixins迁移

    先来介绍一下mixins(混入) 先来看一段代码: const mixin = function(obj, mixins) { const newObj = obj; newObj.prototype ...

  6. 学习React系列(六)——更新dom细节于原理

    React更新dom的依据: 1.不同类型的elements会产生不同的树 2.通过render方法中包含key属性的子元素,开发者可以示意哪些子元素可能是稳定的. 更新过程: 一.根元素类型不同:旧 ...

  7. 学习React系列(五)——使性能最优

    提高性能可分为两方面: 一.配置层面 二.代码层面 本文只从代码层面考虑: 一.避免重复渲染 这里要说一句: 当shouldComponentUpdate返回false的时候不触发render函数也就 ...

  8. 学习React系列(三)——Refs和Dom

    一.适用于以下场景: 1.控制焦点,文本选择,或者媒体控制 2.触发必要的动画 3.整合第三方dom库 二.不要过度使用ref 如果想通过ref来改变state,那么换一种方式-变量提升可能会更好. ...

  9. 学习React系列(二)——深入了解JSX

    1.JX实际上是React.createElement(component,props,...children)的语法糖 2.JSX判断是否为react组件的依据是标签首字母为大写(所以要求用户自定义 ...

随机推荐

  1. poj 2681 字符串

    http://poj.org/problem?id=2681 给你任意长度的字符串,找出两串字符中不相同的字符个数(总数) #include<string> #include<cst ...

  2. APP专业的开发公司都有这样一套开发流程,强烈建议收藏!

    下面让我们来剖析到底是如何开发App的呢? 1.App界面设计开发: 通过客户提出需求,需要头脑风暴得出合适的方案和设计理念; 确认页面风格,确定整个界面的布局.关键截面的设计.文字.及其他的设计 G ...

  3. [bzoj1565][NOI2009]植物大战僵尸_网络流_拓扑排序

    植物大战僵尸 bzoj1565 题目大意:给你一张网格图,上面种着一些植物.你从网格的最右侧开始进攻.每个植物可以对僵尸提供能量或者消耗僵尸的能量.每个植物可以保护一个特定网格内的植物,如果一个植物被 ...

  4. curl的使用基本流程,HTTP的get请求,post请求

    使用CURL的PHP扩展完成一个HTTP请求的发送一般有以下几个步骤: 1.初始化连接句柄: 2.设置CURL选项: 3.执行并获取结果: 4.释放VURL连接句柄. 下面的程序片段是使用CURL发送 ...

  5. phpcms v9 搜索结果列表页时间显示1970问题解决方案

    对于喜欢用phpcms v9 的小伙伴来说,在调用时间时,总会出现时间1970这样的问题,对于这个问题,网上的说法很多,内容页时间显示通常不会问题,搜索结果页就不行了,通过总结,发现使用{format ...

  6. 关于ORM,以及Python中SQLAlchemy的scoped_session

    orm(object relational mapping):对象关系映射. python面向对象,而数据库是关系型. orm是将数据库关系映射为Python中的对象,不用直接写SQL. 缺点是性能略 ...

  7. CSS3 box-shadow 属性

    定义和用法box-shadow 属性向框添加一个或多个阴影. 默认值: none继承性: no版本: CSS3JavaScript 语法: object.style.boxShadow="1 ...

  8. Java并发编程实战(chapter_2)(对象发布、不变性、设计线程安全类)

    一.发布与溢出 "发布(Publish)"一个对象的意思是指,使对象能够在当前作用于之外的代码中使用.这个"之外",尤为关键,各种出问题的地方,都是因为这个&q ...

  9. C语言第一次作业——输入输出格式

    题目1温度转换 本题要求编写程序,计算华氏温度150°F对应的摄氏温度.计算公式:C=5×(F−32)/9,式中:C表示摄氏温度,F表示华氏温度,输出数据要求为整型. 1.实验代码 #include& ...

  10. AWS中的Internet 网关

    nternet 网关是一种横向扩展.支持冗余且高度可用的 VPC 组件,可实现 VPC 中的实例与 Internet 之间的通信.因此它不会对网络流量造成可用性风险或带宽限制. Internet 网关 ...