这是我进行设计React-Openlayers 框架的设计记录,也是对React学习的记录
简介 上一个笔记,达到的目的是初步学会了如何初步打包一个Openlayers和React结合的框架。下一步就是开始准备进行结构设计,因为这个是对Openlayers的一个在封装,React更倾向于一个单项数据传播流动。而React里面的思维Openlayers的结构并不是很类似(据我目前的理解。) 所以现在开始设计,首先要考虑的问题就是Map对象,Map对象是OL中的一个全局对象必须要保证他的全局存在。或者说在React组件中他是一个能够被所有组件读到的对象。这里我使用React的context对象解决问题。
React context 简介 React 的context主要是用于缩短React 的父组件到需要传递的组件之间的路径的。比如说,样式信息就没有必要一层一层传递下去,使用context对象就可以避免这样的问题。
不要因为怕麻烦所以就直接使用context对象。请坚持只有在同一个数据在多个层级多个组件使用的时候才应该使用context。
代码实现 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 import React from 'react'; import {render} from 'react-dom'; import PropTypes from 'prop-types'; class Children extends React.Component { // 如果不需要在构造函数中使用可以不写,没有影响 constructor(props, context) { super(props, context); console.log(context); } render() { return <ul> <li>{'default context is: ' + this.context.value}</li> </ul>; } } Children.contextTypes = {//contextTypes value: PropTypes.string }; class Parent extends React.Component { getChildContext() { return { value: 'parent' }; } render() { return ( <div> {this.props.children} </div> ); } } Parent.childContextTypes = { value: PropTypes.string };
以上是一个简单的代码示例在父元素设置getChildContext并在组件中设置childContextTypes进行校验。如果不设置校验那么对象会返回空。
注意 :官网文档用法有些差异可能是已经变化,但是经过测试上面的用法也没问题,另外我觉得还是上面的用法正常一些。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 // Context 使得我们能够向组件树中的任意组件传递信息并不需要逐级传递 //下面的例子是传递一个当前主题(light是当前主题值) const ThemeContext = React.createContext('light'); class App extends React.Component { render() { // 使用一个Provider来向下传递 //任何组件可以读取到这个值,无论他多深。 // In this example, we're passing "dark" as the current value. return ( <ThemeContext.Provider value="dark"> <Toolbar /> </ThemeContext.Provider> ); } } // A component in the middle doesn't have to // pass the theme down explicitly anymore. function Toolbar(props) { return ( <div> <ThemedButton /> </div> ); } function ThemedButton(props) { // Use a Consumer to read the current theme context. // React will find the closest theme Provider above and use its value. // In this example, the current theme is "dark". return ( <ThemeContext.Consumer> {theme => <Button {...props} theme={theme} />} </ThemeContext.Consumer> ); }
getChildContext 函数将会在每次state或者props改变时调用。为了更新context中的数据,使用 this.setState触发本地状态的更新。这将触发一个的context并且数据的改变可以被子元素收到。
代码实现关键点 1 构造器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 constructor(props) { super(props); console.log("BASE Olbasemap"); this.map = new ol.Map({ // target: 'map', layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], view: new ol.View({ center: ol.proj.fromLonLat([37.41, 8.82]), zoom: 4, }) }); }
2 componentDidMount 1 2 3 4 5 componentDidMount() { console.log("BASE componentDidMount"); this.map.setTarget("map") }
componentDidMount在首次render之后执行,当构造函数中确认了map对象之后在渲染完dom节点之后才可以将map对象与dom节点绑定。
3 Context对象 1 2 3 4 5 6 7 8 9 10 11 12 getChildContext() { console.log("BASE getChildContext"); return { value: 'parent', map: this.map }; } Map.childContextTypes = { value: PropTypes.string, map: PropTypes.instanceOf(ol.Map) };
Context 对象及其校验
总结 今天解决了map对象的问题为后面的组件设计打下了基础。之后将对图层的组织以及事件的组织进行设计。