react怎么引用兄弟组件并react 触发render其render

中国领先的IT技术网站
51CTO旗下网站
不止是UI:React的使用场景探索
React不仅是一个强大的交互式UI渲染类库,而且还提供了一个用于处理数据和用户输入的绝佳方法。它倡导可重用并且易于测试的轻量级组件。不仅在Web应用中,这些重要的特性同样适用于其他的技术场景。
作者:Tom Hallett等来源:| 09:28
React不仅是一个强大的交互式UI渲染类库,而且还提供了一个用于处理数据和用户输入的绝佳方法。它倡导可重用并且易于测试的轻量级组件。不仅在Web应用中,这些重要的特性同样适用于其他的技术场景。
在这一部分内容中,我们将会看到如何在下面的场景中使用React:
借助 atom-shell 或者 node-webkit 这类项目,我们可以在桌面上运行一个 Web应用。来自 Github 的 Atom Editor 就是使用 atom-shell 以及 React创建的。
下面将 atom-shell 应用于我们的。
首先,从下载并且安装 atom-shell。使用下面的 desktop 脚本运行 atom-shell,就可以在窗口中打开该应用。
&var&app&=&require('app');&var&BrowserWindow&=&require('browser-window');&&var&server&=&require('./server/server');&server.listen('8080');&&require('crash-reporter').start();&&&var&mainWindow&=&null;&&app.on('window-all-closed',&function()&{&&&if&(process.platform&!=&'darwin')&&&&&app.quit();&});&&app.on('ready',&function()&{&&&&&&mainWindow&=&new&BrowserWindow({&&&&&width:&800,&&&&&height:&600&&&});&&&&&&&&&mainWindow.loadUrl('http://localhost:8080/');&&&&&&mainWindow.on('closed',&function()&{&&&&&&&&&&&&&&&mainWindow&=&null;&&&});&});&
借助 atom-shell 或者 node-webkit 这类项目,我们可以将创建 web的技术应用于创建桌面应用。就像开发 web 应用一样,React同样可以帮助你构建强大的交互式桌面应用。
通常,游戏对用户交互有很高的要求,玩家需要及时地对游戏状态的改变做出响应。相比之下,在绝大多数web应用中,用户不是在消费资源就是在产生资源。本质上,游戏就是一个状态机,包括两个基本要素:
在本书概览部分,你应该已经注意到:React关注的范畴比较窄,仅仅包括两件事:
React 和游戏之间的相似点远不止这些。React 的虚拟 DOM 架构成就了高性能的3D 游戏引擎,对于每一个想要达到的视图状态,渲染引擎都保证了对视图或者DOM 的一次有效更新。
2048这个游戏的实现就是将 React 应用于游戏中的一个示例。这个游戏的目的是把桌面上相匹配的数字结合在一起,直到2048。
下面,深入地看一下。源码被分为两部分。第一部分是用于实现游戏逻辑的全局函数,第二部分是React 组件。你马上会看到游戏桌面的初始数据结构。
var&initial_board&=&{&&&a1:null,&a2:null,&a3:null,&a4:null,&&&b1:null,&b2:null,&b3:null,&b4:null,&&&c1:null,&c2:null,&c3:null,&c4:null,&&&d1:null,&d2:null,&d3:null,&d4:null&};&
桌面的数据结构是一个对象,它的 key 与 CSS中定义的虚拟网格位置直接相关。继初始化数据结构后,你将会看到一系列的函数对该给定数据结构进行操作。这些函数都按照固定的方式执行,返回一个新的桌面并且不会改变输入值。这使得游戏逻辑更清晰,因为可以将在数字方块移动前后的桌面数据结构进行比较,并且在不改变游戏状态的情况下推测出下一步。
关于数据结构,另一个有趣的属性是数字方块之间在结构上共享。所有的桌面共享了对桌面上未改变过的数字方块的引用。这使得创建一个新桌面非常快,并且可以通过判断引用是否相同来比较桌面。
这个游戏由两个 React 组件构成,GameBoard 和Tiles。
Tiles是一个简单的 React 组件。每当给它的 props 指定一个board,它总会渲染出完整的 Tiles。这给了我们利用 CSS3 transition实现动画的机会。
var&Tiles&=&React.createClass({&&&render:&function(){&&&&&var&board&=&this.props.&&&&&&&&&&var&tiles&=&used_spaces(board).sort(function(a,&b)&{&&&&&&&return&board[a].id&-&board[b].&&&&&});&&&&&return&(&&&&&&&&div&className=&board&&&&&&&&&&&{tiles.map(function(key){&&&&&&&&&&&var&tile&=&board[key];&&&&&&&&&&&var&val&=&tile_value(tile);&&&&&&&&&&&return&(&&&&&&&&&&&&&&span&key={tile.id}&className={key&+&&&value&&+&val}&&&&&&&&&&&&&&&&{val}&&&&&&&&&&&&&&/span&&&&&&&&&&&&);&&&&&&&&&})}&&&&&&&&/div&&&&&&);&&&}&});&&!--&渲染数字方块后的输出示例&--&&&div&class=&board&&data-reactid=&.0.1&&&&&&span&class=&d2&value64&&data-reactid=&.0.1.$2&&64&/span&&&&&span&class=&d1&value8&&data-reactid=&.0.1.$27&&8&/span&&&&&span&class=&c1&value8&&data-reactid=&.0.1.$28&&8&/span&&&&&span&class=&d3&value8&&data-reactid=&.0.1.$32&&8&/span&&&/div&&&.board&span{&&&&&&transition:&all&100ms&&}&
GameBoard是一个状态机,用于响应按下方向键这一用户事件,并与游戏的逻辑功能进行交互,然后用一个新的桌面来更新状态。
var&GameBoard&=&React.createClass({&&&getInitialState:&function()&{&&&&&return&this.addTile(this.addTile(initial_board));&&&},&&&keyHandler:&function(e)&{&&&&&var&directions&=&{&&&&&&&37&:&left,&&&&&&&38&:&up,&&&&&&&39&:&right,&&&&&&&40&:&down&&&&&};&&&&&if&(directions[e.keyCode]&&&&&&&&this.setBoard(fold_board(this.state,&directions[e.keyCode]))&&&&&&&&Math.floor(Math.random()&*&30,&0)&&&0)&{&&&&&&&setTimeout(function()&{&&&&&&&&&this.setBoard(this.addTile(this.state));&&&&&&&}.bind(this),&100);&&&&&}&&&},&&&setBoard:&function(new_board)&{&&&&&if&(!same_board(this.state,&new_board))&{&&&&&&&this.setState(new_board);&&&&&&&return&true;&&&&&}&&&&&return&false;&&&},&&&addTile:&function(board)&{&&&&&var&location&=&available_spaces(board).sort(function()&{&&&&&&&return.5&-&Math.random();&&&&&}).pop();&&&&&if&(location)&{&&&&&&&var&two_or_four&=&Math.floor(Math.random()&*&2,&0)&?&2&:&4;&&&&&&&return&set_tile(board,&location,&new_tile(two_or_four));&&&&&}&&&&&return&&&&},&&&newGame:&function()&{&&&&&this.setState(this.getInitialState());&&&},&&&componentDidMount:&function()&{&&&&&window.addEventListener(&keydown&,&this.keyHandler,&false);&&&},&&&render:&function()&{&&&&&var&status&=&!can_move(this.state)&?&&&-&Game&Over!&:&&&;&&&&&return&(&&&&&&&&div&className&=&&app&&&&&&&&&&&&&span&className&=&&score&&&&&&&&&&&&&&Score:&{score_board(this.state)}&{status}&&&&&&&&&&/span&&&&&&&&&&&Tiles&board={this.state}/&&&&&&&&&&&&button&onClick={this.newGame}&&New&Game&&/button&&&&&&&&&/div&&&&&&&);&&&}&});&
在 GameBoard组件中,我们初始化了用于和桌面交互的键盘监听器。每一次按下方向键,我们都会去调用setBoard,该方法的参数是游戏逻辑中新创建的桌面。如果新桌面和原来的不同,我们会更新GameBoard 组件的状态。这避免了不必要的函数执行,同时提升了性能。
在 render 方法中,我们渲染了当前桌面上的所有 Tile组件。通过计算游戏逻辑中的桌面并渲染出得分。
每当我们按下方向键时,addTile方法会保证在桌面上添加新的数字方块。直到桌面已经满了,没有新的数字可以结合时,游戏结束。
基于以上的实现,为这个游戏添加一个撤销功能就很容易了。我们可以把所有桌面的变化历史保存在GameBoard 组件的状态中,并且在当前桌面上新增一个撤销按钮()。
这个游戏实现起来非常简单。借助React,开发者仅聚焦在游戏逻辑和用户交互上即可,不必去关心如何保证视图上的同步。
尽管 React 在创建 web 交互式 UI 上做了优化,但它的核心还是渲染HTML。这意味着,我们在编写 React应用时的诸多优势,同样可以用来编写令人头疼的 HTML 电子邮件。
创建 HTML 电子邮件需要将许多的 table在每个客户端上进行精准地渲染。想要编写电子邮件,你可能要回溯到几年以前,就像是回到1999 年编写 HTML 一样。
在多终端下成功地渲染邮件并不是一件简单的事。在我们使用 React来完成设计的过程中,可能会碰到若干挑战,不过这些挑战与是否使用React 无关。
用 React 为电子邮件渲染 HTML 的核心是React.renderToStaticMarkup。这个函数返回了一个包含了完整组件树的HTML 字符串,指定了最外层的组件。React.renderToStaticMarkup 和React.renderToString 之间唯一的区别就是前者不会创建额外的 DOM属性,比如 React 用于在客户端索引 DOM 的 data-react-id属性。因为电子邮件客户端并不在浏览器中运行&&我们也就不需要那些属性了。
使用 React 创建一个电子邮件,下图中的设计应该分别应用于 PC 端和移动端:
为了渲染出电子邮件,我写了一小段脚本,输出用于发送电子邮件的 HTML 结构:
&var&React&=&require('react');&var&SurveyEmail&=&require('survey_email');&var&survey&=&{};&console.log(&&&React.renderToStaticMarkup(&SurveyEmail&survey={survey}/&)&);&
我们看一下 SurveyEmail 的核心结构。首先,创建一个 Email 组件:
var&Email&=&React.createClass({&&&render:&function&()&{&&&&&return&(&&&&&&&&html&&&&&&&&&&&body&&&&&&&&&&&&{this.prop.children}&&&&&&&&&&/body&&&&&&&&&/html&&&&&&);&&&}&});&
&SurveyEmail/&组件中嵌套了&Email/&。
var&SurveyEmail&=&React.createClass({&&&propTypes:&{&&&&&survey:&React.PropTypes.object.isRequired&&&},&&&render:&function&()&{&&&&&var&survey&=&this.props.&&&&&return&(&&&&&&&&Email&&&&&&&&&&&h2&{survey.title}&/h2&&&&&&&&&/Email&&&&&&);&&&}&});&
接下来,按照给定的两种设计分别渲染出这两个KPI,在 PC 端上左右相邻排版,在移动设备中上下堆放排版。每一个 KPI在结构上相似,所以他们可以共享同一个组件:
var&SurveyEmail&=&React.createClass({&&&render:&function&()&{&&&&&return&(&&&&&&&&table&className='kpi'&&&&&&&&&&&tr&&&&&&&&&&&&&td&{this.props.kpi}&/td&&&&&&&&&&&/tr&&&&&&&&&&&tr&&&&&&&&&&&&&td&{this.props.label}&/td&&&&&&&&&&&/tr&&&&&&&&&/table&&&&&&);&&&}&});&
把它们添加到 &SurveryEmail/&组件中:
var&SurveyEmail&=&React.createClass({&&&propTypes:&{&&&&&survey:&React.PropTypes.object.isRequired&&&},&&&render:&function&()&{&&&&&var&survey&=&this.props.&&&&&var&completions&=&survey.activity.reduce(function&(memo,ac){&&&&&&&return&memo&+&a;&&&&&},&0);&&&&&var&daysRunning&=&survey.activity.&&&&&return&(&&&&&&&&Email&&&&&&&&&&&h2&{survey.title}&/h2&&&&&&&&&&&KPI&kpi={completions}&label='Completions'/&&&&&&&&&&&KPI&kpi={daysRunning}&label='Days&running'/&&&&&&&&&/Email&&&&&&);&&&}&});&
这里实现了将 KPI上下堆放的排版,但是在 PC 端我们的设计是左右相邻排版。现在的挑战是,让它既能在 PC 又能在移动设备上工作。首先我们应解决下面几个问题。
通过添加 CSS 文件的方式美化 &Email/&:
var&fs&=&require('fs');&var&Email&=&React.createClass({&&&propTypes:&{&&&&&responsiveCSSFile:&React.PropTypes.string&&&},&&&render:&function&()&{&&&&&var&responsiveCSSFile&=&this.props.responsiveCSSF&&&&&var&&&&&&&&if&(responsiveCSSFile)&{&&&&&&&&&styles&=&&style&{fs.readFileSync(responsiveCSSFile)}&/style&;&&&&&&&}&&&&&&&return&(&&&&&&&&&&html&&&&&&&&&&&&&body&&&&&&&&&&&&&&{styles}&&&&&&&&&&&&&{this.prop.children}&&&&&&&&&&&&/body&&&&&&&&&&&/html&&&&&&&&);&&&}&});&
完成后的 &SurveyEmail/& 如下:
var&SurveyEmail&=&React.createClass({&&&propTypes:&{&&&&&survey:&React.PropTypes.object.isRequired&&&},&&&render:&function&()&{&&&&&var&survey&=&this.props.&&&&&var&completions&=&survey.activity.reduce(function&(memo,&ac)&{&&&&&&&return&memo&+&a;&&&&&},&0);&&&&&var&daysRunning&=&survey.activity.&&&&&return&(&&&&&&&&Email&responsiveCSS='path/to/mobile.css'&&&&&&&&&&&h2&{survey.title}&/h2&&&&&&&&&&&table&className='for-desktop'&&&&&&&&&&&&&tr&&&&&&&&&&&&&&&td&&&&&&&&&&&&&&&&&KPI&kpi={completions}&label='Completions'/&&&&&&&&&&&&&&&/td&&&&&&&&&&&&&&&td&&&&&&&&&&&&&&&&&KPI&kpi={daysRunning}&label='Days&running'/&&&&&&&&&&&&&&&/td&&&&&&&&&&&&&/tr&&&&&&&&&&&/table&&&&&&&&&&&div&className='for-mobile'&&&&&&&&&&&&&KPI&kpi={completions}&label='Completions'/&&&&&&&&&&&&&KPI&kpi={daysRunning}&label='Days&running'/&&&&&&&&&&&/div&&&&&&&&&/Email&&&&&&);&&&}&});&
我们把电子邮件按照 PC 端和移动端进行了分组。不幸的是,在电子邮件中我们无法使用float: left,因为大多数的浏览器并不支持它。还有 HTML标签中的 align 和 valign 属性已经被废弃,因而 React也不支持这些属性。不过,他们已经提供了一个类似的实现可用于浮动两个div。而事实上,我们使用了两个分组,通过响应式的样式表,依据屏幕尺寸的大小来控制显示或隐藏。
尽管我们使用了表格,但有一点很明确,使用 React渲染电子邮件和编写浏览器端的响应式 UI有着同样的优势:组件的重用性、可组合性以及可测试性。
在我们的 Survey Builder示例应用中,我们想要绘制出在公共关系活动日当天,某次调查的完成数量的图表。我们想把完成数量在我们的调查表中表现成一个简单的走势图,一眼就可以看出调查的完成情况。
React 支持 SVG 标签,因而制作简单的 SVG 就变得很容易。
为了渲染出走势图,我们还需要一个带有一组指令的&Path/&。
完成后的示例如下:
var&Sparkline&=&React.createClass({&&&propTypes:&{&&&&&points:&React.PropTypes.arrayOf(React.PropTypes.number).isRequired&&&},&&&render:&function&()&{&&&&&var&width&=&200;&&&&&var&height&=&20;&&&&&var&path&=&this.generatePath(width,&height,&this.props.points);&&&&&return&(&&&&&&&&svg&width={width}&height={height}&&&&&&&&&&&path&d={path}&stroke='#7ED321'&strokeWidth='2'&fill='none'/&&&&&&&&&/svg&&&&&&);&&&},&&&generatePath:&function&(width,&height,&points){&&&&&var&maxHeight&=&arrMax(points);&&&&&var&maxWidth&=&points.&&&&&return&points.map(function&(p,&i)&{&&&&&&&var&xPct&=&i&/&maxWidth&*&100;&&&&&&&var&x&=&(width&/&100)&*&xP&&&&&&&var&yPct&=&100&-&(p&/&maxHeight&*&100);&&&&&&&var&y&=&(height&/&100)&*&yP&&&&&&&if&(i&===&0)&{&&&&&&&&&return&'M0,'&+&y;&&&&&&&}&else&{&&&&&&&&&return&'L'&+&x&+&','&+&y;&&&&&&&}&&&&&}).join('&');&&&}&});&
上面的 Sparkline 组件需要一组表示坐标的数字。然后,使用 path创建一个简单的 SVG。
有趣的部分是,在 generatePath函数中计算每个坐标应该在哪里渲染并返回一个 SVG 路径的描述。
它返回了一个像&M0,30 L10,20 L20,50&一样的字符串。 SVG路径将它翻译为绘制指令。指令间通过空格分开。&M0,30&意味着将指针移动到x0 和 y30。同理,&L10,20&意味着从当前指针位置画一条指向 x10 和 y20的线,以此类推。
以同样的方式为大型的图表编写 scale 函数可能有一点枯燥。但是,如果使用 D3这样的类库编写就会变得非常简单,并且 D3 提供的 scale函数可用于取代手动地创建路径,就像这样:
var&Sparkline&=&React.createClass({&&&propTypes:&{&&&&&points:&React.PropTypes.arrayOf(React.PropTypes.number).isRequired&&&},&&&render:&function&()&{&&&&&var&width&=&200;&&&&&var&height&=&20;&&&&&var&points&=&this.props.points.map(function&(p,&i)&{&&&&&&&return&{&y:&p,&x:&i&};&&&&&});&&&&&var&xScale&=&d3.scale.linear()&&&&&&&.domain([0,&points.length])&&&&&&&.range([0,&width]);&&&&&var&yScale&=&d3.scale.linear()&&&&&&&.domain([0,&arrMax(this.props.points)])&&&&&&&.range([height,&0]);&&&&&var&line&=&d3.svg.line()&&&&&&&.x(function&(d)&{&return&xScale(d.x)&})&&&&&&&.y(function&(d)&{&return&yScale(d.y)&})&&&&&&&.interpolate('linear');&&&&&return&(&&&&&&&&svg&width={width}&height={height}&&&&&&&&&&&path&d={line(points)}&stroke='#7ED321'&strokeWidth='2'&fill='none'/&&&&&&&&&/svg&&&&&&);&&&}&});&
在这一章里我们学到了:
React 不只局限于浏览器,还可被用于创建桌面应用以及电子邮件。
React 如何辅助游戏开发。
使用 React 创建图表是一个非常可行的方式,配合 D3这样的类库会表现得更出色。
【编辑推荐】【责任编辑: TEL:(010)】
大家都在看猜你喜欢
头条头条头条热点头条
24H热文一周话题本月最赞
讲师:5人学习过
讲师:29人学习过
讲师:5人学习过
精选博文论坛热帖下载排行
公钥基础设施PKI(Public Key Infrastructure)是利用公钥概念和加密技术为网上通信提供的符合标准的一整套安全基础平台。公钥基础设施能为...
订阅51CTO邮刊『 不要让任何事情成为你不去学习的理由!』
【REACT NATIVE 系列教程之四】刷新组件Render(重新渲染)的三种方式详解
【REACT NATIVE 系列教程之四】刷新组件Render(重新渲染)的三种方式详解
本站文章均为
原创,转载务必在明显处注明:
转载自【黑米GameDev街区】 原文链接:
开发过游戏的都应该很清楚,“刷屏”是多么的重要。其实开发应用也如此,当组件的数据被修改后,如何及时更新组件呈现出最新的数据与效果一样至关重要。
那么这里Himi大概讲三种常用的方式:
this.setState()
【最为常用】
这是在事件处理函数中和请求回调函数中触发 UI 更新的主要方法。
一般情况下setState() 总是触发一次重绘,除非在 shouldComponentUpdate() 中实现了条件渲染逻辑。如果使用可变的对象,但是又不能在 shouldComponentUpdate() 中实现这种逻辑,仅在新 state 和之前的 state 存在差异的时候调用 setState() 可以避免不必要的重新渲染。
举例、代码段如下:
JavaScript
constructor(props) {
super(props);
this.state = {
myName:'I am MyName!',
testFun(){
this.setState({myName:'组件被刷新了'});
render() {
&TouchableHighlight
underlayColor='#4169e1'
onPress={this.testFun.bind(this)}
source={require('./res/himi.png')}
style={{width: 70, height: 70}}
&/TouchableHighlight&
1234567891011121314151617181920212223242526
constructor(props) { super(props); this.state = {&&&&&&&&&&&&&&&&myName:'I am MyName!', };&}&testFun(){&&&&this.setState({myName:'组件被刷新了'});}&&render() {&&&&&&&&......&&&&&&&&&TouchableHighlight &&&&&&&&&&underlayColor='#4169e1'&&&&&&&&&&onPress={this.testFun.bind(this)}&&&&&&&&&&&&& &&&&&&&&&&&&&Image &&&&&&&&&&&&source={require('./res/himi.png')} &&&&&&&&&&&&style={{width: 70, height: 70}} &&&&&&&&&&&&/&&&&&&&&&&/TouchableHighlight&&&&&&&&&......&&)}
1. 在this.state中添加了一个 字符串变量 myName 用于Text 组件的文字显示
2. 自定义了一个 testFun 函数,用于 Touchable的回调处理,其中调用了this.setState 函数并修改了myName的数据
3. 在render中添加了一个高亮触摸组件,用于演示效果。
【注】假如有 a、b、c三个组件,b 是 a 的子组件,c是 b 的子组件,那么 b 中 setState 之后,b 和 c 会 rerender,而 a 不会。 因此建议大家可以把每个组件提供一个重绘接口,然后提供给其他组件调用。
效果如下:(点击查看动态效果)
this.forceUpdate() 【较为常用,但是不推荐】
如果 render() 方法从 this.props 或者 this.state 之外的地方读取数据,你需要通过调用 forceUpdate() 告诉 React 什么时候需要再次运行 render()。如果直接改变了 this.state,也需要调用 forceUpdate()。
调用 forceUpdate() 将会导致 render() 方法在相应的组件上被调用,并且子级组件也会调用自己的 render(),但是如果标记改变了,那么 React 仅会更新 DOM。通常情况下,应该尽量避免所有使用 forceUpdate() 的情况,在 render() 中仅从 this.props 和 this.state 中读取数据。这会使应用大大简化,并且更加高效。
举例、在上面的示例代码基础上修改,如下:
testFun(){
this.state.myName='组件被刷新了';
testForceFun(){
this.forceUpdate();
render() {
&TouchableHighlight
underlayColor='#4169e1'
onPress={this.testFun.bind(this)}
source={require('./res/himi.png')}
style={{width: 70, height: 70}}
&/TouchableHighlight&
&TouchableHighlight
underlayColor='#4169e1'
onPress={this.testForceFun.bind(this)}
source={require('./res/himi.png')}
style={{width: 40, height: 40}}
&/TouchableHighlight&
123456789101112131415161718192021222324252627282930
&&testFun(){&&&&this.state.myName='组件被刷新了';&&}&&testForceFun(){&&&&this.forceUpdate();&&}&render() {&&&&&&&& ......&&&&&&&& &TouchableHighlight &&&&&&&&&&underlayColor='#4169e1'&&&&&&&&&&onPress={this.testFun.bind(this)}&&&&&&&&&&&&& &&&&&&&&&&&&&Image &&&&&&&&&&&&source={require('./res/himi.png')} &&&&&&&&&&&&style={{width: 70, height: 70}} &&&&&&&&&&&&/&&&&&&&&&&/TouchableHighlight&&&&&&&&&&&&&&&&&&TouchableHighlight &&&&&&&&&&underlayColor='#4169e1'&&&&&&&&&&onPress={this.testForceFun.bind(this)}&&&&&&&&&&&&& &&&&&&&&&&&&&Image &&&&&&&&&&&&source={require('./res/himi.png')} &&&&&&&&&&&&style={{width: 40, height: 40}} &&&&&&&&&&&&/&&&&&&&&&&/TouchableHighlight&&&&&&& ......}
改动说明:
修改 testFun 函数,让其作用只是修改了 myName 的值,并没有setState!所以不重绘
添加 testForceFun 函数,作用是调用强制重绘函数。
c) render中多加了一个按钮,来触发 testForceFun函数。
运行效果图如下:(注意
testForceFun 函数对应的是图片较小的那个哦~ )
通过示意图可以知道,Himi 调用了 testFun、接着调用testForceFun ,才能看到刷新。
3. this.setProps()
【不常用】
同一个节点上再次调用 React.render() 来更新根组件是首选的方式,也可以调用 setProps() 来改变组件的属性,触发一次重新渲染。
但是!此方法仅在根组件上面调用。也就是说,仅在直接传给 React.render() 的组件上可用,在它的子级组件上不可用。如果你倾向于在子组件上使用 setProps(),不要利用响应式更新,而是当子组件在 render() 中创建的时候传入新的 prop 到子组件中。
说的通俗一点:父组件不能直接修改 prop属性,只能父类在使用传入的时候进行设置。
? 【Unreal Engine 】 ? 【React Native】 ? 【Cocos Creator】? 【Cocos2dx】? 【C2dx-Lua】
Himi’s Book
小广告先森
小广告先森11:48:43 UTC
最近看react文档发现一个问题,因为是英文一直搞不明白确切的意思,求大神解惑!
第一种情况:setState会触发组件重新渲染,但是如果2者相同,在不使用pureRender的情况下会发现componentDidUpdate被执行,说明组件render函数有执行过。但是通过chrome审查元素会发现,组件div根本没有重新生成,如果渲染会有一个红色跳动。2.第二种情况:如果setState改变了组件的className,style,children等属性。render执行,组件div在审查元素查看并不跳动而是,class 或者内容跳动。说明divDOM并没有重新生成,而是渲染内部部分内容。3.第三种情况:改变包裹组件的dom节点类型,比如由span改为div,render后,会生成新的div。也就是说每次组件render后形成一个虚拟dom,然后拿这个dom和已经mount的dom去比较。然后再根据上面的三种情况去决定是否重新生成,还是渲染部分内容。
我发现的问题是:比如我有一个&ul&{list.map(item=&&li&{item.content}&/li&)}&/ul&,在list中添加新的item时,只有新生成的li在chrome审查元素中跳动,也就是说ul组件更新,但是ul实际的DOM节点还是原来的,但是如果我delete一个item时,ul会跳动,也就是ul实际dom节点重新生成了。如何避免减少的时候不重新渲染这个dom呢?不知道我理解有没有错?求大神解惑啊。
15:09:14 UTC
你可以详细的看一下react的diff在关于DOM更新那一块的东西,网上有好多,diff会在计算之后做出最少的改动来更新DOM,就比如说你只更改了style中的一个属性,diff通过对比发现和之前的元素只是style中一个样式不对,它就会只改这一个样式,而不会去重新渲染整个DOM元素,还有就是删除增加元素什么的,网上都有很好的解释。
17:00:07 UTC
我的问题其实就是增删元素啊。增加不变,删除改变了啊。能给个你说的链接?
02:42:27 UTC
React中最神奇的部分莫过于虚拟DOM,以及其高效的Diff算法。这让我们可以无需担心性能问题而”毫无顾忌”的随时“刷新”整个页面,由虚拟DOM来确保只对界面上真正变化的部分进行实际的DOM操作。React在这一部分已经做到足够透明,在实际开发中我们基本无需关心虚拟DOM是如何运作的。然而,作为有态度的程序员,我们总是对技术背后的原理充满着好奇。理解其运行机制不仅有助于更好的理解React组件的生命周期,而且对于进一步优化React程序也会有很大帮助。
15:29:11 UTC
render负责在服务器断渲染虚拟DOM树 并将此DOM树推到前段浏览器中,每次修改DOM树都会在服务器端渲染之后在显示
12:26:23 UTC
根本就没用到服务器端,完全前端啊。}

我要回帖

更多关于 react 触发render 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信