进公司接活这个定义是比较广泛的,不同的公司有不同的要求,比如小公司跟阿里巴巴对于前端工程师的要求就是完全不一样的。你可以根据我下面列的4点来看看自己大概可以处于一个什么样的水平
你先要看看你对react基础掌握的怎么样,setState的作用是什么,父组件如何向子组件进行传参,子组件如何跟父组件进行通信,JSX的语法,组件生命周期有没有理解透彻,如何循环遍历一个组件,这些都是react里面最基础的一些知识点。
因为react只是一个写网页的框架,所以最基本的web前端知识,肯定也要了解,比如HTML基础知识,JS基础知识,CSS,CSS3,AJAX等等
会redux,深入理解redux的action,reducer,store,中间件。在理解redux的同时,能会immutablejs那就更好了。
然后再加深,就是要知道如如何对react代码进行优化,性能进行优化。比如要理解pureComponent,reactmemo,还有react 166新出的react suspense,react lazy。
总结,如果上面的1,2满足了,基本上就是可以用react实现一些中小型项目了,这个时候去面试一些之前没用过react技术栈的公司了。如果要进大一点的公司或者正在使用react技术栈的公司,3是必须要满足的,因为稍微大型一点的项目是肯定要用redux这种状态管理工具的。如果要进大厂,1,2,3,4必须全部满足,甚至还必须非常精通。
说说React一个组件,有自己的结构,有自己的逻辑,有自己的样式,会依赖一些资源,会依赖某些其他组件。比如日常写一个组件,比较常规的方式:
- 通过前端模板引擎定义结构
- JS文件中写自己的逻辑
- CSS中写组件的样式
- 通过RequireJS、SeaJS这样的库来解决模块之间的相互依赖,
那么在React中是什么样子呢?
结构和逻辑
在React的世界里,结构和逻辑交由JSX文件组织,React将模板内嵌到逻辑内部,实现了一个JS代码和HTML混合的JSX。
结构
在JSX文件中,可以直接通过 ReactcreateClass 来定义组件:
var CustomComponent = ReactcreatClass({
render: function(){
return (<div className="custom-component"></div>);
}
});
通过这种方式可以很方便的定义一个组件,组件的结构定义在render函数中,但这并不是简单的模板引擎,我们可以通过js方便、直观的 *** 控组件结构,比如我想给组件增加几个节点:
var CustomComponent = ReactcreatClass({
render: function(){
var $nodes = ['h','e','l','l','o']map(function(str){
return (<span>{str}</span>);
});
return (<div className="custom-component">{$nodes}</div>);
}
});
通过这种方式,React使得组件拥有灵活的结构。那么React又是如何处理逻辑的呢?
逻辑
写过前端组件的人都知道,组件通常首先需要相应自身DOM事件,做一些处理。必要时候还需要暴露一些外部接口,那么React组件要怎么做到这两点呢?
事件响应
比如我有个按钮组件,点击之后需要做一些处理逻辑,那么React组件大致上长这样:
var ButtonComponent = ReactcreateClass({
render: function(){
return (<button>屠龙宝刀,点击就送</button>);
}
});
点击按钮应当触发相应地逻辑,一种比较直观的方式就是给button绑定一个 onclick 事件,里面就是需要执行的逻辑了:
function getDragonKillingSword() {
//送宝刀
}
var ButtonComponent = ReactcreateClass({
render: function(){
return (<button onclick="getDragonKillingSword()">屠龙宝刀,点击就送</button>);
}
});
但事实上 getDragonKillingSword() 的逻辑属于组件内部行为,显然应当包装在组件内部,于是在React中就可以这么写:
var ButtonComponent = ReactcreateClass({
getDragonKillingSword: function(){
//送宝刀
},
render: function(){
return (<button onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
}
});
这样就实现内部事件的响应了,那如果需要暴露接口怎么办呢?
暴露接口
事实上现在 getDragonKillingSword 已经是一个接口了,如果有一个父组件,想要调用这个接口怎么办呢?
父组件大概长这样:
var ImDaddyComponent = ReactcreateClass({
render: function(){
return (
<div>
//其他组件
<ButtonComponent />
//其他组件
</div>
);
}
});
那么如果想手动调用组件的方法,首先在ButtonComponent上设置一个 ref="" 属性来标记一下,比如这里把子组件设置成 <ButtonComponent ref="getSwordButton"/> ,那么在父组件的逻辑里,就可以在父组件自己的方法中通过这种方式来调用接口方法:
thisrefsgetSwordButtongetDragonKillingSword();
看起来屌屌哒~那么问题又来了,父组件希望自己能够按钮点击时调用的方法,那该怎么办呢?
配置参数
父组件可以直接将需要执行的函数传递给子组件:
<ButtonComponent clickCallback={thisgetSwordButtonClickCallback}/>
然后在子组件中调用父组件方法:
var ButtonComponent = ReactcreateClass({
render: function(){
return (<button onClick={thispropsclickCallback}>屠龙宝刀,点击就送</button>);
}
});
子组件通过 thisprops 能够获取在父组件创建子组件时传入的任何参数,因此 thisprops 也常被当做配置参数来使用
屠龙宝刀每个人只能领取一把,按钮点击一下就应该灰掉,应当在子组件中增加一个是否点击过的状态,这又应当处理呢?
组件状态
在React中,每个组件都有自己的状态,可以在自身的方法中通过 thisstate 取到,而初始状态则通过 getInitialState() 方法来定义,比如这个屠龙宝刀按钮组件,它的初始状态应该是没有点击过,所以 getInitialState 方法里面应当定义初始状态 clicked: false 。而在点击执行的方法中,应当修改这个状态值为 click: true :
var ButtonComponent = ReactcreateClass({
getInitialState: function(){
//确定初始状态
return {
clicked: false
};
},
getDragonKillingSword: function(){
//送宝刀
//修改点击状态
thissetState({
clicked: true
});
},
render: function(){
return (<button onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
}
});
这样点击状态的维护就完成了,那么render函数中也应当根据状态来维护节点的样式,比如这里将按钮设置为 disabled ,那么render函数就要添加相应的判断逻辑:
render: function(){
var clicked = thisstateclicked;
if(clicked)
return (<button disabled="disabled" onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
else
return (<button onClick={thisgetDragonKillingSword}>屠龙宝刀,点击就送</button>);
}
小节
这里简单介绍了通过JSX来管理组件的结构和逻辑,事实上React给组件还定义了很多方法,以及组件自身的生命周期,这些都使得组件的逻辑处理更加强大
资源加载
CSS文件定义了组件的样式,现在的模块加载器通常都能够加载CSS文件,如果不能一般也提供了相应的插件。事实上CSS、可以看做是一种资源,因为加载过来后一般不需要做什么处理。
React对这一方面并没有做特别的处理,虽然它提供了Inline
Style的方式把CSS写在JSX里面,但估计没有多少人会去尝试,毕竟现在CSS样式已经不再只是简单的CSS文件了,通常都会去用Less、
Sass等预处理,然后再用像postcss、myth、autoprefixer、cssmin等等后处理。资源加载一般也就简单粗暴地使用模块加载器
完成了
组件依赖
组件依赖的处理一般分为两个部分:组件加载和组件使用
组件加载
React没有提供相关的组件加载方法,依旧需要通过 <script> 标签引入,或者使用模块加载器加载组件的JSX和资源文件。
组件使用
如果细心,就会发现其实之前已经有使用的例子了,要想在一个组件中使用另外一个组件,比如在 ParentComponent 中使用 ChildComponent ,就只需要在 ParentComponent 的 render() 方法中写上 <ChildComponent /> 就行了,必要的时候还可以传些参数。
疑问
到这里就会发现一个问题,React除了只处理了结构和逻辑,资源也不管,依赖也不管。是的,React将近两万行代码,连个模块加载器都没有提供,更与Angularjs,jQuery等不同的是,他还不带啥脚手架…没有Ajax库,没有Promise库,要啥啥没有…
虚拟DOM
那它为啥这么大?因为它实现了一个虚拟DOM(Virtual DOM)。虚拟DOM是干什么的?这就要从浏览器本身讲起
如我们所知,在浏览器渲染网页的过程中,加载到HTML文档后,会将文档解析并构建DOM树,然后将其与解析CSS生成的CSSOM树一起结合产
生爱的结晶——RenderObject树,然后将RenderObject树渲染成页面(当然中间可能会有一些优化,比如RenderLayer树)。
这些过程都存在与渲染引擎之中,渲染引擎在浏览器中是于JavaScript引擎(JavaScriptCore也好V8也好)分离开的,但为了方便JS
*** 作DOM结构,渲染引擎会暴露一些接口供JavaScript调用。由于这两块相互分离,通信是需要付出代价的,因此JavaScript调用DOM提
供的接口性能不咋地。各种性能优化的最佳实践也都在尽可能的减少DOM *** 作次数。
而虚拟DOM干了什么?它直接用JavaScript实现了DOM树(大致上)。组件的HTML结构并不会直接生成DOM,而是映射生成虚拟的
JavaScript DOM结构,React又通过在这个虚拟DOM上实现了一个 diff
算法找出最小变更,再把这些变更写入实际的DOM中。这个虚拟DOM以JS结构的形式存在,计算性能会比较好,而且由于减少了实际DOM *** 作次数,性能会
有较大提升具体内容大致分为如下:
(1)react-navigation库属性介绍
(2)StackNavigator、TabNavigator实现界面间跳转,Tab切换
(3)StackNavigator界面间跳转、传值、取值
(4)DrawerNavigator实现抽屉导航菜单
(5)DrawerNavigator扩展功能
(6)修改源码,定制UI界面
1、StackNavigator属性介绍
navigationOptions:配置StackNavigator的一些属性。
title:标题,如果设置了这个导航栏和标签栏的title就会变成一样的,不推荐使用
header:可以设置一些导航的属性,如果隐藏顶部导航栏只要将这个属性设置为null
headerTitle:设置导航栏标题,推荐
headerBackTitle:设置跳转页面左侧返回箭头后面的文字,默认是上一个页面的标题。可以自定义,也可以设置为null
headerTruncatedBackTitle:设置当上个页面标题不符合返回箭头后的文字时,默认改成"返回"
headerRight:设置导航条右侧。可以是按钮或者其他视图控件
headerLeft:设置导航条左侧。可以是按钮或者其他视图控件段是取自童老师给小二我新书作的序,没有断章取义的意思。很清楚,H5并不是狭义的HTML5新标签和API,而是工程化的“In
App”
technology。
iOS/Android
——原生应用(都懂得,不解释)。
React
Native
——
React
&
Native
,应运而生!
一、React
Native的出现方法一:导出 store
这应该是最简单省事同时也容易想到的方法,但是有一点需要注意:
不要在服务端渲染中使用该方法
如果你在使用服务端渲染的 app 中直接导出 store,那么 app 的所有 user 都会获得一个单例的 store (包括相同的 JWT Token),这肯定不是你乐见的。
除去上述这种情况,当我们需要获取 store 中的 JWT Token 时,可以这么做:
/
storejs
/
import { createStore } from 'redux';
import reducer from '/reducer';
const store = createStore(reducer);
export default store;
1
2
3
4
5
6
7
8
9
1
2
3
4
5
6
7
8
9
创建 store 的方法还和以前一样,仅仅是导出它,以便于在其他文件中使用。
不要担心你使用的 createStore 方法可能会很复杂,放心的使用各种中间件比如 thunk, saga, devtools ,你需要做的仅仅是导出 store 而已。
紧接着,在需要用到 store 中数据的地方,引入 (import) 它。下面的例子就是我们在一个普通函数 apijs 中将 store 中的 JWT Token 通过 ajax 传递给服务端。
/
apijs
/
import store from '/store';
export function getProtectedThing() {
// grab current state
const state = storegetState();
// get the JWT token out of it
// (obviously depends on how your store is structured)
const authToken = statecurrentUsertoken;
// Pass the token to the server
return fetch('/user/thing', {
method: 'GET',
headers: {
Authorization: `Bearer ${authToken}`
}
})then(res => resjson());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
在 Redux 官网的 FAQ 中有这样一个问题 我可以在组件中直接引入 store 并使用吗 ?
其实如果需要在 React 组件中使用 store,我们有更好的选择 (译者注:也是官方提倡的):那就是使用 React-Redux 中的 connect 方法。
Mark Erikson,Redux 的维护者之一,在 Reddit 上就这个问题发表过如下看法:
通常情况下,不建议在 component 中通过 import 的方式来使用 store
在某些情况下,可以试着通过 thunk 或者其他一些 Redux 中间件来 *** 作 store 而不是直接去引用它。
但是凡事总有例外,打我自己的比方,有一个项目中 70% 的代码使用 Backbone 写的,在项目的一些模块中,我们同时需要来自 Backbone models 和 Redux store 中的数据,在这部分模块中,我们的确需要 import {store} from “store” 这种直接的引用方式,因为我们的确没有其他选择。
所以,直接引用并不是理想的方式,但是,如果有必要,也可以。
React Component 之外 dispatch action
如果你在 React Component 之外需要 dispatch action,那么同样的方法也是适用的:引入 store 然后再调用 storedispatch(),这和你在 react-redux 中通过 connect 函数获取到 dispatch 是一样的。
方法二:从 thunk 中获取 redux 的 state
如果你需要在 thunk 中获取 redux store 中的某项数据,更简单不过。你根本不需要直接引入 store,因为 thunk 的 action 中有一个 getState 的输入参数。
下面的例子就是从 thunk 的 action 创建函数中获取 JWT Token
/ actionsjs /
export function getProtectedThing() {
return (dispatch, getState) => {
// grab current state
const state = getState();
// get the JWT token out of it
// (obviously depends on how your store is structured)
const authToken = statecurrentUsertoken;
// Pass the token to the server
return fetch('/user/thing', {
method: 'GET',
headers: {
Authorization: `Bearer ${authToken}`
}
})then(res => resjson());
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
另外,如果你不想在 thunk 的 action 函数中直接使用 fetch,你可以选择将 fetch 封装到另外一个类中比如 apijs 当然你需要额外的参数将所需数据传递出去。
方法三:使用中间件(middleware)截获 action 中的数据
如果你不喜欢上述两种方法 (或是无法使用),那么也可以试试下面这种方法。
开发一个自定义的 redux 中间件,“拦截” 特定的 action 在 action 触达 store 之前获取其携带的数据,甚至在中间件中直接获取 store
我们还以 JWT Token 为例。假设应用程序在用户成功登陆后会触发一个 LOG_SUCCESS 的 action,该 action 携带的数据包含 JWT Token
/
indexjs
/
const saveAuthToken = store => next => action => {
if(actiontype === 'LOGIN_SUCCESS') {
// after a successful login, update the token in the API
apisetToken(actionpayloadauthToken);
}
// continue processing this action
return next(action);
}
const store = createStore(
reducer,
applyMiddleware(saveAuthToken)
);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
在你的 apijs 中会有一个 setToken 的方法将 token 赋值给本地变量。
/
apijs
/
let currentAuthToken = null;
export function setToken(token) {
currentAuthToken = token;
}
export function getProtectedThing() {
// Pass the token to the server
return fetch('/user/thing', {
method: 'GET',
headers: {
Authorization: `Bearer ${currentAuthToken}`
}
})then(res => resjson());
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
如果你使用的 >
做React-Native项目时,使用Realm做数据持久化,由于种种不便,所以将其删除。
由于项目依赖关系,故使用以下命令:
到此处,不能高兴太早,被坑的很惨啊!!!!
报错信息如下:
看到这些,蛋都碎了,有木有??有木有??明明什么么都没做,为啥运行出错呢??
至此xcode中编译成功
React-Native填坑之删除第三方开源组件的依赖包
React Native开发错误警告处理总结
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)