组件经过Context是能够访问到其父组件链上全部节点组件提供的Context的属性。css
因此,我借鉴了JS做用域链的思路,把Context当成是组件的做用域来使用。html
对于同一个类型的项目,采用开发模式,使用的基本框架都是一致的。前端
前端技术选型:vue
(1)外部用户的PC站;react
(2)外部用户的mobile站;jquery
(3)外部用户的Native App开发;android
(4)内部员工的管理后台webpack
一、外部用户的PC站es6
须要有SEO,有加载体验,采用的是先后端分离开发模式,页面直接渲染,基于jquery。web
为何使用jquery?
(1)主要是为了兼容IE8;
(2)是外部用户,视觉体验高,权重高。适合先有行,再有行。就是说视觉和行为要尽量分离,会牺牲一点开发成本,可是用户更重要。
(3)绝大多数页面交互轻量用不上数据驱动。
二、外部用户的Mobile站
这里说的Mobile站主要是浏览器访问为主的,所以,页面切换都是传统链接跳转,属于传统web应用,先后端分离开发模式,页面直接渲染,采用react。大体缘由:使用react 是为了 和APP端的react native保持同步。
三、外部用户的Native App开发
前端组有直接参与 Native APP 开发的项目,使用的是 React Native 进行开发。
为啥选择RN,以前Hybrid模式开发有性能优化瓶颈,采用React Native性能能够突破这个瓶颈,有原生的性能,且支持热更新,上手不算太难,跨平台,IOS和android代码复用率90%。适合交互和动画不太复杂的项目,最终要根据项目来。特别适合快速迭代的项目或者前期须要大量试错的项目。
(1)不要随意使用第三方库,后期修改维护不方便,尽可能本身写仍是本身写;
(2)前期仍是须要客户端帮忙配合,项目搭建。
四、内部员工的管理后台
先后端分离开发,页面侧重异步渲染,使用vuejs。
大体内容是:后台管理系统有大量的增删改查操做,适合具备双向绑定的类库或者框架进行渲染。同时没有兼容性的要求(SEO,首屏渲染),所以单页面是合适的。能够选择vue,react,angular。由于vue对api,文档对开发者更友好。选用好的UI组件,规范贯彻,拆分和按需加载,自动化测试有待增强。
对于比较正式的项目,前端技术选型策略必定是产品收益最大化,用户在首位
react 生命周期函数 初始化阶段:
getDefaultProps:获取实例的默认属性
getInitialState:获取每一个实例的初始化状态
componentWillMount:组件即将被装载、渲染到页面上
render:组件在这里生成虚拟的 DOM 节点
componentDidMount:组件真正在被装载以后 运行中状态:
componentWillReceiveProps:组件将要接收到属性的时候调用
shouldComponentUpdate:组件接受到新属性或者新状态的时候(能够返回 false,接收数据后不更新,阻止 render 调用,后面的函数不会被继续执行了)
componentWillUpdate:组件即将更新不能修改属性和状态
render:组件从新描绘
componentDidUpdate:组件已经更新
销毁阶段: componentWillUnmount:组件即将销毁
首先说说为何要使用Virturl DOM,由于操做真实DOM的耗费的性能代价过高,因此react内部使用js实现了一套dom结构,在每次操做在和真实dom以前,使用实现好的diff算法,对虚拟dom进行比较,递归找出有变化的dom节点,而后对其进行更新操做。为了实现虚拟DOM,咱们须要把每一种节点类型抽象成对象,每一种节点类型有本身的属性,也就是prop,每次进行diff的时候,react会先比较该节点类型,假如节点类型不同,那么react会直接删除该节点,而后直接建立新的节点插入到其中,假如节点类型同样,那么会比较prop是否有更新,假若有prop不同,那么react会断定该节点有更新,那么重渲染该节点,而后在对其子节点进行比较,一层一层往下,直到没有子节点。
diff算法实现
把树形结构按照层级分解,只比较同级元素。
给列表结构的每一个单元添加惟一的 key 属性,方便比较。
React 只会匹配相同 class 的 component(这里面的 class 指的是组件的名字)
合并操做,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每个事件循环结束, React 检查全部标记 dirty 的 component 从新绘制. 选择性子树渲染。开发人员能够重写 shouldComponentUpdate 提升 diff 的性能。
Refs 是 React 提供给咱们的安全访问 DOM 元素或者某个组件实例的句柄。咱们能够为元素添加 ref 属性而后在回调函数中接受该元素在 DOM 树中的句柄,该值会做为回调函数的第一个参数返回
React.createClass()、ES6 class 和无状态函数。
根据组件的职责一般把组件分为 UI 组件和容器组件。
UI 组件负责 UI 的呈现,容器组件负责管理数据和逻辑。
二者经过 React-Redux 提供 connect 方法联系起来。
在 React 组件中,应该在 componentDidMount 中发起网络请求。这个方法会在组件第一次“挂载”(被添加到 DOM)时执行,在组件的生命周期中仅会执行一次。更重要的是,你不能保证在组件挂载以前 Ajax 请求已经完成,若是是这样,也就意味着你将尝试在一个未挂载的组件上调用 setState,这将不起做用。在 componentDidMount 中发起网络请求将保证这有一个组件能够更新了
为了解决跨浏览器兼容性问题,您的 React 中的事件处理程序将传递 SyntheticEvent 的实例,它是 React 的浏览器本机事件的跨浏览器包装器。
这些 SyntheticEvent 与您习惯的原生事件具备相同的接口,除了它们在全部浏览器中都兼容。有趣的是,React 实际上并无将事件附加到子节点自己。React 将使用单个事件监听器监听顶层的全部事件。这对于性能是有好处的,这也意味着在更新 DOM 时,React 不须要担忧跟踪事件监听器。
一般咱们输出节点的时候都是map一个数组而后返回一个ReactNode,为了方便react内部进行优化,咱们必须给每个reactNode添加key,这个key prop在设计值处不是给开发者用的,而是给react用的,大概的做用就是给每个reactNode添加一个身份标识,方便react进行识别,在重渲染过程当中,若是key同样,若组件属性有所变化,则react只更新组件对应的属性;没有变化则不更新,若是key不同,则react先销毁该组件,而后从新建立该组件。
开发过程当中,咱们须要保证某个元素的 key 在其同级元素中具备惟一性。在 React Diff 算法中 React 会借助元素的 Key 值来判断该元素是新近建立的仍是被移动而来的元素,从而减小没必要要的元素重渲染。此外,React 还须要借助 Key 值来判断元素与本地状态的关联关系,所以咱们毫不可忽视转换函数中 Key 的重要性。
在代码中调用 setState 函数以后,React 会将传入的参数对象与组件当前的状态合并,而后触发所谓的调和过程(Reconciliation)。通过调和过程,React 会以相对高效的方式根据新的状态构建 React 元素树而且着手从新渲染整个 UI 界面。在 React 获得元素树以后,React 会自动计算出新的树与老树的节点差别,而后根据差别对界面进行最小化重渲染。在差别计算算法中,React 可以相对精确地知道哪些位置发生了改变以及应该如何改变,这就保证了按需更新,而不是所有从新渲染。
shouldComponentUpdate 这个方法用来判断是否须要调用 render 方法从新描绘 dom。由于 dom 的描绘很是消耗性能,若是咱们能在 shouldComponentUpdate 方法中可以写出更优化的 dom diff 算法,能够极大的提升性能。
虚拟 dom 至关于在 js 和真实 dom 中间加了一个缓存,利用 dom diff 算法避免了没有必要的 dom 操做,从而提升性能。
用 JavaScript 对象结构表示 DOM 树的结构;而后用这个树构建一个真正的 DOM 树,插到文档当中当状态变动的时候,从新构造一棵新的对象树。而后用新的树和旧的树进行比较,记录两棵树差别把 2 所记录的差别应用到步骤 1 所构建的真正的 DOM 树上,视图就更新了。
Refs 是 React 提供给咱们的安全访问 DOM 元素或者某个组件实例的句柄。咱们能够为元素添加 ref 属性而后在回调函数中接受该元素在 DOM 树中的句柄,该值会做为回调函数的第一个参数返回:
展现组件关心组件看起来是什么。展现专门经过 props 接受数据和回调,而且几乎不会有自身的状态,但当展现组件拥有自身的状态时,一般也只关心 UI 状态而不是数据的状态。
容器组件则更关心组件是如何运做的。容器组件会为展现组件或者其它容器组件提供数据和行为(behavior),它们会调用 Flux actions,并将其做为回调提供给展现组件。容器组件常常是有状态的,由于它们是(其它组件的)数据源。
类组件不只容许你使用更多额外的功能,如组件自身的状态和生命周期钩子,也能使组件直接访问 store 并维持状态
当组件仅是接收 props,并将组件自身渲染到页面时,该组件就是一个 '无状态组件(stateless component)',可使用一个纯函数来建立这样的组件。这种组件也被称为哑组件(dumb components)或展现组件
State 是一种数据结构,用于组件挂载时所需数据的默认值。State 可能会随着时间的推移而发生突变,但多数时候是做为用户事件行为的结果。
Props(properties 的简写)则是组件的配置。props 由父组件传递给子组件,而且就子组件而言,props 是不可变的(immutable)。组件不能改变自身的 props,可是能够把其子组件的 props 放在一块儿(统一管理)。Props 也不只仅是数据--回调函数也能够经过 props 传递。
在 HTML 中,相似 input, textarea 和 select> 这样的表单元素会维护自身的状态,并基于用户的输入来更新。当用户提交表单时,前面提到的元素的值将随表单一块儿被发送。但在 React 中会有些不一样,包含表单元素的组件将会在 state 中追踪输入的值,而且每次调用回调函数时,如 onChange 会更新 state,从新渲染组件。一个输入表单元素,它的值经过 React 的这种方式来控制,这样的元素就被称为"受控元素"。
高阶组件是一个以组件为参数并返回一个新组件的函数。HOC 运行你重用代码、逻辑和引导抽象。最多见的多是 Redux 的 connect 函数。除了简单分享工具库和简单的组合,HOC 最好的方式是共享 React 组件之间的行为。若是你发现你在不一样的地方写了大量代码来作同一件事时,就应该考虑将代码重构为可重用的 HOC。
由于 this.props 和 this.state 的更新多是异步的,不能依赖它们的值去计算下一个 state。
你可使用属性初始值设定项(property initializers)来正确绑定回调,create-react-app 也是默认支持的。在回调中你可使用箭头函数,但问题是每次组件渲染时都会建立一个新的回调。
在 super() 被调用以前,子类是不能使用 this 的,在 ES2015 中,子类必须在 constructor 中调用 super()。传递 props 给 super() 的缘由则是便于(在子类中)能在 constructor 访问 this.props。
React.createElement():JSX 语法就是用 React.createElement()来构建 React 元素的。它接受三个参数,第一个参数能够是一个标签名。如 div、span,或者 React 组件。第二个参数为传入的属性。第三个以及以后的参数,皆做为组件的子组件。
React.cloneElement()与 React.createElement()类似,不一样的是它传入的第一个参数是一个 React 元素,而不是标签名或组件。新添加的属性会并入原有的属性,传入到返回的新元素中,而就的子元素奖杯替换。
Flux 的最大特色,就是数据的"单向流动"。
用户访问 View
View 发出用户的 Action
Dispatcher 收到 Action,要求 Store 进行相应的更新
Store 更新后,发出一个"change"事件
View 收到"change"事件后,更新页面
creat-react-app
redux 是一个应用数据流框架,主要是解决了组件间状态共享的问题,原理是集中式管理,主要有三个核心方法,action,store,reducer,工做流程是 view 调用 store 的 dispatch 接收 action 传入 store,reducer 进行 state 操做,view 经过 store 提供的 getState 获取最新的数据,flux 也是用来进行数据操做的,有四个组成部分 action,dispatch,view,store,工做流程是 view 发出一个 action,派发器接收 action,让 store 进行数据更新,更新完成之后 store 发出 change,view 接受 change 更新视图。Redux 和 Flux 很像。主要区别在于 Flux 有多个能够改变应用状态的 store,在 Flux 中 dispatcher 被用来传递数据到注册的回调事件,可是在 redux 中只能定义一个可更新状态的 store,redux 把 store 和 Dispatcher 合并,结构更加简单清晰
新增 state,对状态的管理更加明确,经过 redux,流程更加规范了,减小手动编码量,提升了编码效率,同时缺点时当数据更新时有时候组件不须要,可是也要从新绘制,有些影响效率。通常状况下,咱们在构建多交互,多数据流的复杂项目应用时才会使用它们
一个组件所须要的数据,必须由父组件传过来,而不能像 flux 中直接从 store 取。
当一个组件相关数据更新时,即便父组件不须要用到这个组件,父组件仍是会从新 render,可能会有效率影响,或者须要写复杂的 shouldComponentUpdate 进行判断。
将每个数组拆除俩个小数组进行求它的全排列,而后获得的结果互相之间又进行全排列,而后把最后的结果链接起来
构建优化 一、减小编译体积 ContextReplacementPugin、IgnorePlugin、babel-plugin-import、babel-plugin-transform-runtime。
二、并行编译 happypack、thread-loader、uglifyjsWebpackPlugin开启并行
三、缓存 cache-loader、hard-source-webpack-plugin、uglifyjsWebpackPlugin开启缓存、babel-loader开启缓存
四、预编译 dllWebpackPlugin && DllReferencePlugin、auto-dll-webapck-plugin
性能优化 一、减小编译体积 Tree-shaking、Scope Hositing。
二、hash缓存 webpack-md5-plugin
三、拆包 splitChunksPlugin、import()、require.ensure
一、首先浏览器主进程接管,开了一个下载线程。
二、而后进行HTTP请求(DNS查询、IP寻址等等),中间会有三次捂手,等待响应,开始下载响应报文。
三、将下载完的内容转交给Renderer进程管理。
四、Renderer进程开始解析css rule tree和dom tree,这两个过程是并行的,因此通常我会把link标签放在页面顶部。
五、解析绘制过程当中,当浏览器遇到link标签或者script、img等标签,浏览器会去下载这些内容,遇到时候缓存的使用缓存,不适用缓存的从新下载资源。
六、css rule tree和dom tree生成完了以后,开始合成render
七、tree,这个时候浏览器会进行layout,开始计算每个节点的位置,而后进行绘制。 绘制结束后,关闭TCP链接,过程有四次挥手
(1)第一次握手:Client将标志位SYN置为1,随机产生一个值seq=J,并将该数据包发送给Server,Client进入SYN_SENT状态,等待Server确认。 (2)第二次握手:Server收到数据包后由标志位SYN=1知道Client请求创建链接,Server将标志位SYN和ACK都置为1,ack=J+1,随机产生一个值seq=K,并将该数据包发送给Client以确认链接请求,Server进入SYN_RCVD状态。 (3)第三次握手:Client收到确认后,检查ack是否为J+1,ACK是否为1,若是正确则将标志位ACK置为1,ack=K+1,并将该数据包发送给Server,Server检查ack是否为K+1,ACK是否为1,若是正确则链接创建成功,Client和Server进入ESTABLISHED状态,完成三次握手,随后Client与Server之间能够开始传输数据了。
1)第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。 (2)第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。 (3)第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。 (4)第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。
一、绝对定位+margin:auto
二、绝对定位+margin反向偏移
三、绝对定位+transform反向偏移
四、display:tabel
五、display: flex
请求头(Request):
Accept:text/html application/xml 告诉服务器客户端浏览器这边能够出里什么数据;
Accept-Encodeing:gzip 告诉服务器我能支持什么样的压缩格式
accept-language:告诉服务器浏览器支持的语言
Cache-control:告诉服务器是否缓存
Connection:keep-alive 告诉服务器当前保持活跃(与服务器处于连接状态)
Host:远程服务器的域名
User-agent:客户端的一些信息,浏览器信息 版本
referer:当前页面上一个页面地址。通常用于服务器判断是否为同一个域名下的请求
返回头(response-header):
cache-control:private/no-cache; 私有的不须要缓存/no-cache也不须要缓存
connection:keep-live; 服务器赞成保持链接
content-Enconding:gzip;除去头的剩余部分压缩返回格式
content-length:内容长度
content-type:text/css;返回内容支持格式
Date: 时间
server:ngnix 服务器类型
set-Cookie:服务器向客户端设置cookie 第一次访问服务器会下发cookie看成身份认证信息,第二次访问服务器再把cookie送给服务器,能够看成认证信息
last-modified: 时间戳 文档的最后改动时间。客户能够经过If-Modified-Since请求头提供一个日期,该请求将被视为一个条件GET,只有改动时间迟于指定时间的文档才会返回,不然返回一个304(Not Modified)状态。Last-Modified也可用setDateHeader方法来设置。
expires 告诉浏览器把回送的资源缓存多长时间 -1或0则是不缓存
etag:版本专有的加密指纹。(有的网站不用,并不是必须)优先检查etag再检查last-modif
ied的时间戳。向服务器请求带if-none-match,服务器判断是否过时未过时返回304,过时返回200
// 注释:第一次请求出来的数据先进行缓存协商,是否缓存expires,cache-control 缓存时间,etag,last-modified等 //注释:屡次访问的时候,浏览器先判断是否有缓存,是否过时 //未过时:直接从缓存中读取。
//http状态码
//1.指示信息–表示请求已经接受,继续处理 //2.成功–表示请求已经被成功接受,理解 //3.重定向–表示完成请求必须进行更进一步操做 //4.客户端错误–请求有语法错误或者请求没法实现 //5.服务器端错误–服务器未能实现合法的请求
1.2 打包原理
识别入口文件
经过逐层识别模块依赖。(Commonjs、amd或者es6的import,webpack都会对其进行分析。来获取代码的依赖)
webpack作的就是分析代码。转换代码,编译代码,输出代码 最终造成打包后的代码
loader是文件加载器,可以加载资源文件,并对这些文件进行一些处理,诸如编译、压缩等,最终一块儿打包到指定的文件中
在 Webpack 运行的生命周期中会广播出许多事件,Plugin 能够监听这些事件,在合适的时机经过 Webpack 提供的 API 改变输出结果
客户端渲染和服务器端渲染的最重要的区别就是到底是谁来完成html文件的完整拼接,若是是在服务器端完成的,而后返回给客户端,就是服务器端渲染,而若是是前端作了更多的工做完成了html的拼接,则就是客户端渲染。
服务器端渲染的优缺点是?
优势:
前端耗时少。由于后端拼接完了html,浏览器只须要直接渲染出来。 有利于SEO。由于在后端有完整的html页面,因此爬虫更容易爬取得到信息,更有利于seo。 无需占用客户端资源。即解析模板的工做彻底交由后端来作,客户端只要解析标准的html页面便可,这样对于客户端的资源占用更少,尤为是移动端,也能够更省电。 后端生成静态化文件。即生成缓存片断,这样就能够减小数据库查询浪费的时间了,且对于数据变化不大的页面很是高效 。 缺点:
不利于先后端分离,开发效率低。使用服务器端渲染,则没法进行分工合做,则对于前端复杂度高的项目,不利于项目高效开发。另外,若是是服务器端渲染,则前端通常就是写一个静态html文件,而后后端再修改成模板,这样是很是低效的,而且还经常须要先后端共同完成修改的动做; 或者是前端直接完成html模板,而后交由后端。另外,若是后端改了模板,前端还须要根据改动的模板再调节css,这样使得先后端联调的时间增长。 占用服务器端资源。即服务器端完成html模板的解析,若是请求较多,会对服务器形成必定的访问压力。而若是使用前端渲染,就是把这些解析的压力分摊了前端,而这里确实彻底交给了一个服务器。
客户端渲染的优缺点是? 优势:
先后端分离。前端专一于前端UI,后端专一于api开发,且前端有更多的选择性,而不须要遵循后端特定的模板。 体验更好。好比,咱们将网站作成SPA或者部份内容作成SPA,这样,尤为是移动端,可使体验更接近于原生app。 缺点:
前端响应较慢。若是是客户端渲染,前端还要进行拼接字符串的过程,须要耗费额外的时间,不如服务器端渲染速度快。 不利于SEO。目前好比百度、谷歌的爬虫对于SPA都是不认的,只是记录了一个页面,因此SEO不好。由于服务器端可能没有保存完整的html,而是前端经过js进行dom的拼接,那么爬虫没法爬取信息。 除非搜索引擎的seo能够增长对于JavaScript的爬取能力,这才能保证seo。
。
原理是,先按定高宽设计出来页面,而后转换为rem单位,
配合js查询屏幕大小来改变html的font-size,
最终作出所谓的完美自适应。
rem+js是宽度自适应,没法作到高度自适应,因此那些对高度要求很高的rem+js没法实现。
改变浏览器宽度,你会发现,页面全部元素的高宽都等比例缩放,
也就是大屏幕下导航是横的,小屏幕下仍是横的只不过变小了。。
优势:理想状态是全部屏幕的高宽比和最初的设计高宽比同样,或者相差很少,完美适应。
缺点:碰到重视高度的设计,或者重视元素间间距的设计,那就玩不开了。