海纳企业网站管理系统源码汽车便宜网站建设
海纳企业网站管理系统源码,汽车便宜网站建设,上海崇明林业建设有限公司 网站,做营利网站的风险第12章 服务端渲染 想让搜索引擎抓取到你的站点#xff0c;服务端渲染这一步不可或缺#xff0c;服务端渲染还可以提升站点的性能#xff0c;因为在加载JavaScript脚本的同时#xff0c;浏览器就可以进行页面渲染。 React的虚拟DOM是其可被用于服务端渲染的关键。首先每个R… 第12章 服务端渲染 想让搜索引擎抓取到你的站点服务端渲染这一步不可或缺服务端渲染还可以提升站点的性能因为在加载JavaScript脚本的同时浏览器就可以进行页面渲染。 React的虚拟DOM是其可被用于服务端渲染的关键。首先每个React Component 在虚拟DOM中完成渲染然后React通过虚拟DOM来更新浏览器DOM中产生变化的那一部分虚拟DOM作为内存中的DOM表现为React在Node.js这类非浏览器环境下的运行提供了可能React可以从虚拟DOM中生成一个字符串。而不是更新真正的DOM这使得我们可以在客户端和服务端使用同一个React Component。 React 提供了两个可用于服务端渲染组件的函数React.renderToString 和React.renderToStaticMarkup。 在设计用于服务端渲染的ReactComponent时需要有预见性考虑以下方面。 选取最优的渲染函数。 如何支持组件的异步状态。 如何将应用的初始化状态传递到客户端。 哪些生命周期函数可以用于服务端的渲染。 如何为应用提供同构路由支持。 单例、实例以及上下文的用法。 渲染函数 在服务端渲染React Component时无法使用标准的React.render方法因为服务端不存在DOM。React提供了两个渲染的函数它们支持标准的React Component生命周期的一个子集。因而能够实现服务端渲染。 React.renderToString React.renderToString是两个服务端渲染函数中的一个也是开发主要使用的一个函数和React.render不同该函数去掉了用于表示渲染位置的参数。取而代之该函数只返回一个字符串这是一个快速的同步阻塞式函数非常快。
var MyComponent React.createClass({render:fucniton(){return div Hello World!/div;}
});
var world React.renderToString (MyComponent/);//这个示例返回一个单行并且格式化的输出
divdata-reactid.fgvrzhg2yodata-ract-checksum-1663559667Hello World!
/div 你会注意到React为这个div元素添加了两个data前缀的属性。在浏览器环境下React使用data-reactid区分DOM节点。这也是每当组件的state及props发生变化时React都可以精准的跟新制定DOM节点的原因。 data-react-checksum仅仅存在于服务端。顾名思义它是已创建DOM和校验和。这准许React在客户端服用与服务端结构上相同点的DOM结构。该属性只会添加到根元素上。 React.renderToStaticMarkup React.renderToStaticMarkup是第二个服务端渲染函数除了不会包含React的data属性外它和React.renderToString没有区别。
varMyComponentReact.createClass({renderfunction{returndivHello World!/div;}
});
varworld React.renderToStaticMarkup(MyCompoent/);//单行输出
divHelloWorld!/div 用React.renderToString还是React.renderToStaticMarkup 每个渲染函数都有自己的用途所以你必须明确自己的需求再去决定使用哪个渲染函数。当且仅当你不打算在客户端渲染这个React Component时才应该选择使用React.renderToStaticMarkup函数。 下面有一些示例: 生成HTML电子邮件 通过HTML到PDF的转化来生成PDF。 组件测试。 大多数情况下我们都会选择使用React.renderToString。这将准许React使用data-react-checksum在客户端更迅速的初始化同一个React Component。因为React可以重用服务端提供的 DOM所以它可以跳过生成DOM节点以及把他们挂载到文档中这两个昂贵的进程。对于复杂些的站点这样做就会显著的减少加载时间用户可以更快的与站点进行交互。 确保React Component能够在服务端和客户端准确的渲染出一致的结构是很重要的。如果data-react-checksum不匹配React会舍弃服务端提供的DOM然后生成新的DOM节点并且将它们更新到文档中。此时React也不再拥有服务端渲染带来的各种性能上的优势。 服务端组件生命周期 一旦渲染为字符串组件就会只调用位于render之前的组件生命周期方法需要指出componentDidMount和componentWillUnmount不会在服务端渲染过程中被调用而componentWillMount在两种渲染方式下均有效。 当新建一个组件时你需要考虑到它可能即在服务端又在客户端进行渲染。这一点在创建事件监听器时尤为重要因为并不存在一个生命周期方法会通知我们React Component是否已经走完了整个生命周期。 在componentWillMount内注册的所有事件监听器及定时器都可能潜在的导致服务端内存泄漏。 最佳做法是只在componentDidMount内部创建事件监听器及定时器然后在componentWilUnmount内清除这两者。 设计组件 服务端渲染时请务必慎重考虑如何将组件的state传递到客户端以充分利用服务端渲染的优势。在设计服务端渲染组件时要时刻记得这一点。 在设计React Component时需要保证同一个props传递到组件中总会输出相同的初始渲染结果。坚持这样做将会提升组件的可测试性并且可以保证组件在服务端和客户端渲染结果的一致性。充分利用服务端渲染的性能优势十分重要。 我们假设现在需要一个组件它可以打印一个随机数。一个棘手问题是组件每次输出的结果总是不一致。如果组件在服务端而不是客户端进行渲染checksum将会失效。
var MyComponent React.createClass({render:dunction(){return div{Math.random()}/div;}
});
var result React.renderToStaticmarkup(MyComponent/);
var result2 REact.renderToStaticMarkup(MyComponent/);//result
div0.5820949131157249/div//result2
div0.420401582631672/div 如果你打算重构它组件将会通过props来接收一个随机数。然后将props传递到客户端用于渲染。
var MyComponent React.createClass({render :function(){retrundiv{this.props.number}/div}
});var numMath.random();
//服务端
React.renderToString(MyComponentnumber{num}/);//将num传递到客户端
React.render(MyComponentnumber {num}/,document.body); 有多种方式可以将服务端的props传递到客户端。 最简单的方式之一是通过JavaScript对象将初始的props值传递到客户端。
!DOCTYPEhtml
htmlheadtitleExample/title!--bundle 包括MyComponent、React等--script type “text/javascriptsrcbundle.js/script/headbody!--服务端渲染MyComponent的结果--div data-reactid.fgvrzhg2yo data-react-checksum-16635596670.5820949131157249/div!--注入初始props供服务端使用--script typetext/javascriptvar initialProps {num:0.5820949131157249};/script!--使用服务端初始props--script type-text/javasriptvar num initialProps.num;React.render(MyComponent number{num}/, document.body);/script/body/html 异步状态 很多应用需要从数据库或者网络服务这类远程数据源中读取数据在客户端这不是问题在等待异步数据返回的时候React Component可以展示一个加载图标。在服务端React 无法直接复制该方案因为render函数是同步的。为了使用异步数据首先需要抓取数据然后再渲染时将数据传递到组件中。 示例 1、你可能需要从异步的store中转区用户记录2、抓取到用户记录后考虑到SEO以及性能等因素需要在服务端渲染组件的状态3、你需要让组件监听在客户端的变化然后重新渲染 问题React.renderToString是同步的所以没有办法使用组件的任何一个生命周期方法来抓区异步的数据 解决方案使用statics函数来抓取异步数据然后把数据传递到组件中用于渲染。将initialState作为props值传递到客户端。使用组件生命周期方法来监听变化然后使用同一个statics函数更新状态。
var Username React.createClass({statics:{getAsyncState:function()(props,setState){User.findById(props.userId).then(function(user){setState({user:user});}).catch(function(error{setState({error:error});});}},//客户端和服务器componentWillMount:function(){if(this.props.initialState){this.setState(this.props.initialState);}},//仅客户端componentDidMountfunction(){//如果props中没有则获取一部stateifthis.props.initialState){this.updateAsynState();}//监听change事件User.on(change,this.updateAsyncState);},//仅客户端componentWillUnmount:funtion(){//停止监听change事件User.off‘change’this.undateAsyncState);},updateAsyncState:function(){//访问示例中的静态函数this.constructor.getAsyncState(this.props,this.setstate;},render:funciton(){if(this.state.error){return div{this.state.error.message}/div;}if(!this.state.usr){retrundivLoading.../div}return div{this.state.user.username}/div;}
});//在服务器端渲染
var props{userId123//也可以通过路由传递
};
Username.getAsyncState(props,funciton(initialState){props[initialState]initialState;var result React.renderToString(Username(props));//使用initialState将结果传递到客户端
}); 上述解决方案中预先抓取到异步数据这一步仅在服务端是必须的。在客户端只有初次渲染时需要查找服务端所传递的initialState。后续客户端上的路由变化比如HTML5pushState或者fragment change都会忽略掉服务端所有的initialState。同时在抓取数据时最好加载文案信息。 同构路由 对于任意一个完整的应用来说路由都至关重要。为了在服务端渲染出拥有路由的React应用你必须确保路由系统支持无DOM渲染。 抓取异步数据是路由系统及其控制器的职责。我们假设一个深度嵌套的组件需要一些异步的数据。如果SEO需要这些数据那么抓取数据的职责应该被提升至路由控制器并且这些数据应该被传递到嵌套组件的最内层。如果不用考虑SEO那么在客户端的componentDidMount方法内抓取数据是没问题的。这与传统的Ajax加载数据方式类似。 考虑一个React同构路由解决方案时需确保它具有异步状态支持或者可以轻易地更改以支持异步状态。理想情况下你也会倾向于使用路由系统来控制将initialState传递到客户端。 单例、实例及上下文 在浏览器端你的应用如同包裹在独立的气泡中一样。每个实例之间的状态不会混在一起因为每个实例通常存在于不同的计算机或者同一台计算机的不同沙箱之中。这使得我们可以在应用架构中轻松地使用单例模式。 当你开始迁移代码并在服务端运行时你必须要小心因为可能存在同一应用的多个实例在相同的作用域内同时运行的情况。有可能出现应用的两个实例都去更改单例状态的情况这会导致异常的行为发生。 React渲染是同步的所以你可以重置之前使用过的所有单例而后在服务端渲染你的应用。如果异步状态需要使用单例则又会遇到问题。同样在渲染过程中使用抓取到的异步状态时也需要考虑到这一点。 尽管可以在渲染前重置之前使用过的单例但是在隔离的环境下运行你的应用总是有好处的。Contextify之类的包准许你在服务端彼此隔离地运行代码。这与客户端使用webworkers类似。Contextify通过将应用代码运行在一个隔离的Node.js V8实例中来工作。一旦加载完代码你就可以调用环境中的所有函数。这种方法可以让你随意地使用单例模式而不用考虑性能上的花销因为每次请求都对应一个全新的Node.js V8实例。 React的核心开发小组不鼓励在组件树中传递上下文和实例。这种做法会降低组件的可移植性并且应用内组件依赖的更改会对层级上的所有组件产生连动式的影响。这转而增加了应用的复杂性而随着应用的增长应用的可维护性也会降低。 当决定使用单例或者实例来控制你的上下文时需要对两者权衡舍去。在选择一个方法之前你需要估算出详细的需求还需要考虑你所使用的第三方类库是如何架构的。 总结 服务端渲染是构建搜索引擎优化的Web站点和Web应用时的重要部分。React支持在服务端和客户端浏览器中渲染相同的React component。要有效地做到这一点你需要保证整个应用都使用这一架构方式以支持服务端渲染。 第13章 周边类库 围绕着Ractfacebook还开发了一系列的前端工具。在你的React项目中这些工具不是非用不可的不过它们确实可以和React一起完美的工作。例如 Jest Immutable.js Flux Jest Jest是Factbook开发的一个测试运行工具。它基于Jasmine测试框架提供相近的方式使用大家熟悉的类似于expect(value).to(other)的断言。它提供了默认的模拟行为会自动模拟require()返回的CommonJS模块。让现有的代码变成可测试的。它使用了模拟的DOM API 同时通过小巧的Node.js命令行工具进行运行缩短每次测试运行的时间。 page 108~112 Immutable.js 不可以变数据结构Immutable Data Structures中的数据是不允许修改的。相反如果数据需要改变它们会返回原始数据的一个经过修改的拷贝。React跟Flux可以很好的结合不可变数据结构带来代码的简洁和性能的提升。 Immutable.js提供了多个数据结构可以有原生的JavaScript数据结构构造而成在需要的时候也可以转会原生的JavaSctipt数据结构。 immutable.Map Immutable.Map可作为常规JavaScript对象的替代者来使用
var question Immutable.Map({desctiption:who is your favorite superhero?}//使用.get从Map中取值
question.get(desctiption);//通过.set更新值时返回一个新的对象
//原始对象保持不变
question2 question.set(desctiption, Who is your favorite comicbook hero?);//使用.merge合并两个对象得到第三个对象
//同样原来的对象没有任何变化
var title {title : Question #1};
var question3 question.merge(question2,title);
question3.toObject();//{title: Question #1,desctiption:who is your favorite comicbook hero} Immutable.Vector 可以使用Immutable.Vector代替数组
var options Immutable.Vector(Superman, Batman);
var option2 options.push(Spiderman);
option2.toArray(); //[Superman,Batman,Spiderman] 你还可以对这些数据结构进行嵌套
var options Immutable.Vector(Superman, Batman);
var question Immutable.Map{description : who is your favorite superhero?,options : options
} Immutable.js还有更丰富的特性你可以到immutable-js上获取更多的相关信息。 Flux Flux是Facebook在发布React时发布的一种模式。它显著的特性是严格的单向数据流。 Facebook在GitHub发布了一份关于实习那Flux的参考可以通过flux访问到。 Flux包含了三个重要的组件 Dispatcher Store View 下图清晰地展示了如何将这些部件组合到一起 Flux没有强制的依赖你可以任意选取自己需要的模块。 关于Flux更详细的讨论见第16章。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/86475.shtml
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!