您的位置:首页 > Web前端 > React

React框架解释及组件间通信

2017-03-14 16:12 477 查看

生命周期hooks lifecycle hooks

组件生命周期: 三个 状态 Mounting Updating Unmouting



把GetInitialState 换成 constructor

Mounting:当一个组件的实例被创建和插入的DOM的时候被调用

constructor()

//componentWillMount()

render()

componentDidMount()

Updating: 当组件被重新渲染(re-rendered) 的时候,导致原因可能是props 或 state的变化

componentWillReceiveRrops()

shouldComponentUpdate()

componentWillUpdate()

render()

componentDidUpdate()

Unmounting: 当一个组件从DOM中被移除的时候被调用

compoentWillUnmount()

Mounting

Render()

A.调用的时候会检查 this.props 和 this.state 然后返回一个React element

这个元素可能是一个Native DOM 元素例如
也可能是你自定义的compoent

B. return null or false 表示你不需要渲染任何东西。

C. render方法是pure的,它不修改组件的状态, 不直接与浏览器交互。

你应该在 componentDidMount() 或者 其他 生命周期方法中 与浏览器进行交互。

Note :如果

shouldComponentUpdate()

返回false, render()不会被调用。

constructor()

A这个构造器被调用,如果React组件被mounted。 这个构造器是用来初始化状态的。 如果你不初始化状态,你不需要这个方法,你也不需要实现一个构造器。

B 但是如果你要实现这个构造器: 你应该调用super(props) 先。

因为你的组件都是extends React.Component的!! 否则,this.props会是undefined!!

constructor(props){

super(props);

this.state={

color:props.initialColor

};

}

可以用props初始化state

componentWillMount()

在mounting之前被立即调用。 是在render之前! 因此 在这个方法里面设置state不会导致re-rendering, 避免引入任何side-effects 在这个方法中。

一般来说我们更加推荐使用 constructor()

componentDidMount()

组件被mounted后马上调用。 在这个方法里,如果你需要从远端载入数据,实例化网络请求的好地方,在这个方法里就很适合。 DOM节点的初始化应该在这里处理。

Updating:

componentWillReceiveRrops()

A.当一个mouted的组件接收一个新的props时会被调用。 如果你需要更新状态来响应prop的改变,你需要比较 this.props 和 nextProps 来 执行状态转换,当然是使用setState()。

B. 即使props没有改变, React 也会调用这个方法。 所以要确保比较了 当前和 下一个值。

当父组件导致你的组件重新渲染的时候会发生。

C. React不会在mouting的时候这个方法。 只会在组件的props可能更新的时候触发。调用this.state()也不会触发这个方法!!!

shouldComponentUpdate

A. 使用这个方法让React知道这个组件的输出是否不被当前state或prop的改变所影响!默认行为是每次state改变都re-render. 绝大多数情况你应该依赖默认行为。

B. 当state 或 props being received的时候都会触发这个方法。 初始render或者 forceUpdate()不会触发这个方法。默认就是true

C. 返回false ,不会触发 componentWillUpdate(), render(), and componentDidUpdate()

D. If you determine a specific component is slow after profiling, you may change it to inherit from React.PureComponent which implements shouldComponentUpdate() with a shallow prop and state comparison. If you are confident you want to write it by hand, you may compare this.props with nextProps and this.state with nextState and return false to tell React the update can be skipped.

使用PureComponent?

componentWillUpdate

A. 当接收到新的props或state 会被立即执行。 使用此方法作为在更新发生之前 做准备的方法。 初始渲染不调用这个方法

B. Note, 你不能在这个方法调用setState() 方法! 如果要根据prop更新state,应该在componentWillReceiveRrops中。

componentDidUpdate

A. 会在更新发生的时候被立即调用。 同样初次渲染不触发。

一个操作DOM的机会,当这个组件被更新。

B. 也是一个比较当前props和previous props 是否变化,如果变化就进行网络请求,否则不进行。

Props VS State

props

this.props包含的属性,是这个组件的父组件定义的! 特别的: this.props.children 是一个特别的prop, typically defined by the child tags in the JSX expression rather than in the tag itself.

state

state 包含的数据是这个组件自身的,而且会随着时间改变。 是用户定义,必须是一个普通的JS 对象。

一个原则: 如果你不在render()中使用,这就不应该在state里。

除了构造器之外的 其他地方,只有this.setState() 可以修改这个属性。

The only place where you can assign this.state is the constructor.

React尽量让组件是无状态的。 大多数我们的组件自身是没有状态state的,只是从父组件那里接受一些属性,然后根据这些属性进行渲染, 父组件自身维护了一些状态通过props传递给子组件,从而使UI变化。

对于DropDown组件,下拉框的文字是需要父组件在调用的时候指定的,如果把它作为自己的状态,那么这里的提示文字就需要同时通过属性和状态来确定的这就非常复杂了!!

React中样式更新的方法

className 或者 style 两种方式修改 CSS样式

但是如果是className修改,你就必须把这个CSS类写的足够小,不然为了更新一个小button的样式而修改了整个组件的样式就得不偿失了!

用style修改是可以,但是一旦用style修改很多个样式就显得很麻烦,写成这样:

style={{display:aa,opacity:bb,width:300,height:200 }}; 等等

所谓的Virtual DOM

可不可以把浏览器里的DOM tree克隆一份完整的镜像到内存,也就是所谓的“virtual DOM”,当页面的state发生变化以后,根据最新的state重新生成一份virtual DOM

(相当于在内存里“刷新”整个页面),

将它和之前的virtual DOM做比对(diff),然后在浏览器里只渲染被改变的那部分内容,这样浏览器的性能损耗和用户体验不就都不成问题了吗!

所谓的Flux

核心思想和代码其实 就是一个 event dispatcher 事件分发器(Java MVC里面也有)

flux说明:

flux与react没有直接关系,二者完全独立的概念

flux不是一个js库,而是一种前端代码的组织思想,redux库是flux思想的一种实现

flux的核心思想和代码很简单, 但是在”state-view”开发模式中,却是非常重要的一个环节!

REACT组件间通信

React 组件间通信

lifting shate up!!!!!!!!

当几个组件之间需要 reflect 一个相同的改变的数据。 我们推荐这个 lifting the shared state up to their closest common ancestor 提升他们的状态到最近的公共祖先!

问题就是:你要去修改别人的state~

不同组件,的最近公共祖先,那就只能是 App这个组件了

要在这个组件把 几个组件相互会影响的state提取出来!

父组件向下传递给子组件:

通过this.props ,这个是简单的。

React中父组件的attribute,属性例如:

<Child text={this.props.text} /> 这个text就是子组件,this.props的属性!

子组件中:



依赖props来传递事件的应用,并通过回调的方式实现,callback里面传递了newState,然后这个newState又传递回给父组件的 事件,然后改变了这个state。

如果组件有多层嵌套的情况,你必须要一次传入回调函数给props来实现子组件向父组件传值或者操作。

var Child = React.createClass({
render: function () {
return (
<span>{this.props.text}</span>
);
}
});


子组件向父组件通信传值

这时就需要 事件。

[子组件] 控制自己的state然后告诉[父组件]的点击状态,然后在 [父组件]展示出来



// 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
checked: false
};
},
onChildChanged: function (newState) {
this.setState({
checked: newState
});
},
render: function() {
var isChecked = this.state.checked ? 'yes' : 'no';
return (
<div>
<div>Are you checked: {isChecked}</div>
<ToggleButton text="Toggle me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
</div>
);
}
});


// 子组件
var ToggleButton = React.createClass({
getInitialState: function () {
return {
checked: this.props.initialChecked
};
},
onTextChange: function () {
var newState = !this.state.checked;
this.setState({
checked: newState
});
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
},
render: function () {
// 从【父组件】获取的值
var text = this.props.text;
// 组件自身的状态数据
var checked = this.state.checked;
return (
<label>{text}: <input type="checkbox" checked={checked}                 onChange={this.onTextChange} /></label>
);
}
});


React Event System

在 onChange 事件或者其他 React 事件中,你能够获取以下东西:

【this】:指向你的组件

【一个参数】:这个参数是一个 React 合成事件 ,SyntheticEvent。

React 对所有事件的管理都是自己实现的,与我们之前使用的 onclick、onchange 事件不一样。从根本上来说,他们都是绑定到 body 上。

如果我没有猜错的话,React 真正处理一个事件的代码如下:

var listenTo = ReactBrowserEventEmitter.listenTo;
...
function putListener(id, registrationName, listener, transaction) {
...
var container = ReactMount.findReactContainerForID(id);
if (container) {
var doc = container.nodeType === ELEMENT_NODE_TYPE ? container.ownerDocument : container;
listenTo(registrationName, doc);
}
...
}
// 在监听事件的内部,我们能发现如下:
target.addEventListener(eventType, callback, false);


多个子组件使用同一个回调的情况

/ 父组件
var MyContainer = React.createClass({
getInitialState: function () {
return {
totalChecked: 0
};
},
onChildChanged: function (newState) {
var newToral = this.state.totalChecked
+ (newState ? 1 : -1);
this.setState({
totalChecked: newToral
});
},
render: function() {
var totalChecked = this.state.totalChecked;
return (
<div>
<div>How many are checked: {totalChecked}</div>
<ToggleButton text="Toggle me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
<ToggleButton text="Toggle me too"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
<ToggleButton text="And me"
initialChecked={this.state.checked}
callbackParent={this.onChildChanged}
/>
</div>
);
}
});
// 子组件
var ToggleButton = React.createClass({
getInitialState: function () {
return {
checked: this.props.initialChecked
};
},
onTextChange: function () {
var newState = !this.state.checked;
this.setState({
checked: newState
});
// 这里要注意:setState 是一个异步方法,所以需要操作缓存的当前值
this.props.callbackParent(newState);
},
render: function () {
// 从【父组件】获取的值
var text = this.props.text;
// 组件自身的状态数据
var checked = this.state.checked;
return (
<label>{text}: <input type="checkbox" checked={checked} onChange={this.onTextChange} /></label>
);
}
});


父子之间要通信的, 尤其是子组件要更新state给父组件的,最好不要把setState写到你的业务里面,而是应该返回 state的值,然后再在事件或者组件生命周期那里获得这个新的state来更新组件!!!!!!!

Event in React

所有组件都是有关系的,一个组件要和另一个组件通信就是通过最近公共父组件

使用React事件的时候,必须关注:

componentDidMount

componentWillUnmount

setState是异步的!!!!!!!!!!!!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  框架 React