React Native 中如何实现根据state控制组件的显示与隐藏
render() {
return(
{
this.state.abc == null ? (
null
) : (
<View>
//部位空时想要显示的内容
<View>
)
}
)
}
React-Native 之 redux 与 react-redux
React Native - Redux 入门
React Native redux使用指南
React-Redux 中文文档
React依赖注入说明(mapStateToProps/mapDispatchToProp)
Redux三要素: action 就是描述一件事情发生的对象, reducer 就是个纯函数, 接受旧的 state 和一个 action, 返回一个新的 state 到 store, store 就是全局唯一的一个仓库,存储着应用所有的 state
Redux运行顺序
(1) store 接收到 action 之后,会把之前的 state 连同发送的 action 一起传递给 reducer,然后 reducer 会根据我们定义好的处理方式去处理 action (增删改 state),然后返回新的 state 让 store 去更新全局 state 树;
(2) 最终 store 会把新的 state 返回给发送 action 的地方好让 React 组件更新 UI。
// mapDispatchToProps()函数的bindActionCreators、action需要引入
import * as action from '../action';
import { bindActionCreators } from 'redux';
function mapDispatchToProps(dispatch){
return {
...bindActionCreators(action, dispatch)
}
}
// 多个action 引入
import * as action from '../action';
import * as action2 from '../../index/action';
function mapDispatchToProps(dispatch){
return {
...bindActionCreators(action, dispatch),
...bindActionCreators(action2, dispatch)
}
}
// 引入一个action里面的多个方法
import { function1, function2, function3 } from '../webs/action'
function mapDispatchToProps(dispatch) {
return {
...bindActionCreators({ afunction1, function2, function3 }, dispatch)
}
}
React 避免不必要的渲染
redux探索:rematch
重新思考Redux:rematch-官方文档
基于 React 与 Ant Design 的管理系统框架 React-Admin
定制化你的ReactNative底部导航栏 - 凸起的BottomTabNavigator
解决ReactNative Webview加载时候白屏问题
需要使用一个View包裹Webview,并设置 overflow:'hidden'
<View style={{ height: 150, width: 150 ,overflow:'hidden'}}>
<WebView
source={{ uri: 'https://github.com/facebook/react-native' }}
scalesPageToFit={true}
/>
</View>
margin和padding的区别
margin是盒子的外边距,即盒子与盒子之间的距离,而padding是内边距,是盒子的边与盒子内部元素的距离。(margin是用来隔开元素与元素的间距;padding是用来隔开元素与内容的间隔。margin用于布局分开元素使元素与元素互不相干;padding用于元素与内容之间的间隔,让内容(文字)与(包裹)元素之间有一段“呼吸距离”。)
React-Native Navigator 过渡动画卡顿的解决方案
React-navigation学习
//路由跳转
this.props.navigation.navigate('DedailView', {
navigation: this.props.navigation,
number:1
callBack: () => { this.CallBack(); },
});
//获取路由参数
const {numbere,callBack} = this.props.navigation.state.params;
//获取 routeName key
console.log('路由列表 this.props.navigation-->', JSON.stringify(this.props.navigation));
const{routeName,key} = this.props.navigation.state;
//返回到指定的页面
this.props.navigation.goBack(key)
React 中 refs 干嘛用的?
Refs 提供了一种访问在render方法中创建的 DOM 节点或者 React 元素的方法。
ref={(input) => this.input = input}
无状态组件
没有state的叫做无状态组件,有state的叫做有状态组件;
当调用setState时,React render 是如何工作的?
咱们可以将"render"分为两个步骤:
1.虚拟 DOM 渲染:当render方法被调用时,它返回一个新的组件的虚拟 DOM 结构。当调用setState()时,render会被再次调用,因为默认情况下shouldComponentUpdate总是返回true,所以默认情况下 React 是没有优化的。
2.原生 DOM 渲染:React 只会在虚拟DOM中修改真实DOM节点,而且修改的次数非常少——这是很棒的React特性,它优化了真实DOM的变化,使React变得更快。
什么是纯函数
1、函数的返回结果只依赖于它的参数。
2、函数执行过程里面没有副作用。
const a = 1
const foo = (x, b) => x + b
foo(1, 2) // => 3
现在 foo 的返回结果只依赖于它的参数 x 和 b,foo(1, 2) 永远是 3。今天是 3,明天也是 3,在服务器跑是 3,在客户端跑也 3,不管你外部发生了什么变化,foo(1, 2) 永远是 3。只要 foo 代码不改变,你传入的参数是确定的,那么 foo(1, 2) 的值永远是可预料的。
React中setState几个现象
constructor() {
super();
this.state = {
val: 0
};
}
componentDidMount() {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 1 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 2 次 log
setTimeout(() => {
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 3 次 log
this.setState({val: this.state.val + 1});
console.log(this.state.val); // 第 4 次 log
}, 0);
}
render() {
return null;
}
};
问上述代码中 4 次 console.log 打印出来的 val 分别是多少?
输出: 0, 0 ,2,3
1.在同一个方法中多次setState是会被合并的,并且对相同属性的设置只保留最后一次的设置;
2.定时器中的setState,每次都会引起新的render,即使是同一个定时器中的多次setState
3. ①: 在按钮原生事件中定义的setState,和定时器效果一样,每次setState都会引起新的render
②: react事件是合并的成一次render的。
4.其实在回调函数中,setState是不会触发批量更新机制的,无论是promise,ajax,setTimeout回调等等,同时设置多次setState,每个setState都会单独执行并render,因为上下文发生了变化。
当你调用 setState 的时候,发生了什么事?
当调用 setState 时,React会做的第一件事情是将传递给 setState 的对象合并到组件的当前状态。这将启动一个称为和解(reconciliation)的过程。和解(reconciliation)的最终目标是以最有效的方式,根据这个新的状态来更新UI。 为此,React将构建一个新的 React 元素树(您可以将其视为 UI 的对象表示)。
一旦有了这个树,为了弄清 UI 如何响应新的状态而改变,React 会将这个新树与上一个元素树相比较(diff)。
通过这样做, React 将会知道发生的确切变化,并且通过了解发生什么变化,只需在绝对必要的情况下进行更新即可最小化 UI 的占用空间。
18 .reactJS的props.children.map函数来遍历会收到异常提示,为什么?应该如何遍历?
this.props.children 的值有三种可能:如果当前组件没有子节点,它就是 undefined;如果有一个子节点,数据类型是 object ;如果有多个子节点,数据类型就是 array 。系统提供React.Children.map()方法安全的遍历子节点对象
19.props和state相同点和不同点
1.不管是props还是state的改变,都会引发render的重新渲染。2.都能由自身组件的相应初始化函数设定初始值。
不同点1.初始值来源:state的初始值来自于自身的getInitalState(constructor)函数;props来自于父组件或者自身getDefaultProps(若key相同前者可覆盖后者)。
2.修改方式:state只能在自身组件中setState,不能由父组件修改;props只能由父组件修改,不能在自身组件修改。
3.对子组件:props是一个父组件传递给子组件的数据流,这个数据流可以一直传递到子孙组件;state代表的是一个组件内部自身的状态,只能在自身组件中存在。
20.Redux中同步 action 与异步 action 最大的区别是什么
同步只返回一个普通 action 对象。而异步操作中途会返回一个 promise 函数。当然在 promise 函数处理完毕后也会返回一个普通 action 对象。thunk 中间件就是判断如果返回的是函数,则不传导给 reducer,直到检测到是普通 action 对象,才交由 reducer 处理。
传入 setState 函数的第二个参数的作用是什么?
该函数会在setState函数调用完成并且组件开始重渲染的时候被调用,我们可以用该函数来监听渲染是否完成:
this.setState(
{ username: 'tylermcginnis33' },
() => console.log('setState has finished and the component has re-rendered.')
)
虚拟DOM
虚拟DOM的本质:用JS对象来模拟DOM数
虚拟DOM的目的:为了实现DOM节点的高效更新
在使用redux过程中,如何防止定义的action-type的常量重复。
ES6引入了一种新的原始数据类型Symbol,表示独一无二的值。 Symbol函数前不能使用new命令,否则会报错。这是因为生成的Symbol是一个原始类型的值,不是对象 Symbol函数可以接受一个字符串作为参数,表示对Symbol实例的描述,主要是为了在控制台显示,或者转为字符串时,比较容易区分。
PureComponent 为什么比Component高效?
追查:这两个组件的实现在ReactBaseClasses.js中间,除掉注释后如下
function ReactComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
ReactComponent.prototype.isReactComponent = {};
ReactComponent.prototype.setState = function (partialState, callback) {
!(typeof partialState === 'object' || typeof partialState === 'function' || partialState == null) ? process.env.NODE_ENV !== 'production' ? invariant(false, 'setState(...): takes an object of state variables to update or a function which returns an object of state variables.') : _prodInvariant('85') : void 0;
this.updater.enqueueSetState(this, partialState, callback, 'setState');
};
ReactComponent.prototype.forceUpdate = function (callback) {
this.updater.enqueueForceUpdate(this, callback, 'forceUpdate');
};
function ReactPureComponent(props, context, updater) {
this.props = props;
this.context = context;
this.refs = emptyObject;
this.updater = updater || ReactNoopUpdateQueue;
}
function ComponentDummy() {}
ComponentDummy.prototype = ReactComponent.prototype;
ReactPureComponent.prototype = new ComponentDummy();
ReactPureComponent.prototype.constructor = ReactPureComponent;
_assign(ReactPureComponent.prototype, ReactComponent.prototype);
ReactPureComponent.prototype.isPureReactComponent = true;
module.exports = {
Component: ReactComponent,
PureComponent: ReactPureComponent
};
发现Component就只实现了构造方法,定义了setState方法就完了。而ReactPureComponent更狠,就只是用js原型模拟继承的方法继承了Component,然后定义属性isPureReactComponent为true。全局搜索isPureReactComponent属性,发现在ReactCompositeComponent.js中有使用,这个类就是管理组件的更新、加载等的。关键代码在updateComponent方法中,如下
var shouldUpdate = true; // 这个变量决定是否需要重新渲染组件
if (!this._pendingForceUpdate) {
var prevState = inst.state;
shouldUpdate = willReceive || nextState !== prevState;
// inst代表组件实例,这个判断条件就是组件是否自己实现了shouldComponentUpdate方法
if (inst.shouldComponentUpdate) {
if (__DEV__) {
shouldUpdate = measureLifeCyclePerf(
() => inst.shouldComponentUpdate(nextProps, nextState, nextContext),
this._debugID,
'shouldComponentUpdate',
);
} else {
shouldUpdate = inst.shouldComponentUpdate(
nextProps,
nextState,
nextContext,
);
}
} else {// 组件没有实现shouldComponentUpdate方法,且是PureComponent,采用shallowEqual浅比较
if (this._compositeType === ReactCompositeComponentTypes.PureClass) {
shouldUpdate = !shallowEqual(prevProps, nextProps) ||
!shallowEqual(inst.state, nextState);
}
}
}
shallowEqual的实现在shallowEqual.js中,大意就是作浅比较,也就是对象数组等只比较对象所处的地址是否相等,而不比较具体的内容,因为深层次递归比较对象内容是否一致很耗费性能。
结论
PureComponent是Component的子类,当PureComponent手动实现了shouldComponentUpdate方法时两个组件没有区别,但若没有手动实现该方法,则PureComponent采用默认的shallowEqual比较对象是否相等性能更佳。由此可能引发的页面不刷新现象可以采用别的办法解决,如重新生成新的对象、采用immutable.js对象等
react循环中key的作用
key值的作用是:
- 更精准–>在虚拟dom节点中赋予key值,会更加快速的拿到需要的目标节点,不会造成就地复用的情况,对于节点的把控更加精准。
- 类型相同的兄弟节点可以被唯一标识
reactNative的生命周期
//构造函数,在创建组件的时候调用一次 不能调用setState();
1.constructor(props, context)
//在组件挂载之前调用一次 可以调用setState();
2.void componentWillMount()
//在组件挂载之后调用一次。这个时候,子组件也都挂载好了,可以在这里使用refs,请求接口 可以调用setState();
3.void componentDidMount()
// 父组件发生render的时候子组件就会调用 可以调用setState();
4.void componentWillReceiveProps(nextProps)
//组件挂载之后,每次调用setState后都会调用shouldComponentUpdate判断是否需要重新渲染组件。默认返回true,需要重新render。在比较复杂的应用里,有一些数据的改变并不影响界面展示,可以在这里做判断,优化渲染效率。 不能调用setState();
5.bool shouldComponentUpdate(nextProps, nextState)
//shouldComponentUpdate返回true或者调用forceUpdate之后,componentWillUpdate会被调用。 不能调用setState();
6.void componentWillUpdate(nextProps, nextState)
//首次render之后调用componentDidMount,其它render结束之后都是调用componentDidUpdate。不能调用setState();
7.void componentDidUpdate()
//组件被卸载的时候调用. 取消监听,定时器,网络请求 不能调用setState();
8.void componentWillUnmount()
yarn.lock
npm ^
- ~ 会匹配最近的小版本依赖包,比如~1.2.3会匹配所有1.2.x版本,但是不包括1.3.0
- ^ 会匹配最新的大版本依赖包,比如^1.2.3会匹配所有1.x.x的包,包括1.3.0,但是不包括2.0.0
- *这意味着安装最新版本的依赖包