• 在解决问题的过程中,也逐渐深入了解了React的一些原理,这篇文章就来分享一下我对React一些原理的理解。 注意 这篇文章并不是教程,只是我对React原理的一些个人理解,欢迎与我一起讨论。文章不对的地方,还请...

    前言

    随着项目开发的深入,不可避免了遇到了一些问题。刚开始出现问题时很懵,不知道该怎么解决,原因就是对React的原理理解的不够透彻,不知道问题出在哪。在解决问题的过程中,也逐渐深入了解了React的一些原理,这篇文章就来分享一下我对React一些原理的理解。

    注意 这篇文章并不是教程,只是我对React原理的一些个人理解,欢迎与我一起讨论。文章不对的地方,还请读者费心指出-

    概述

    本文是《使用React技术栈的一些收获》系列文章的第二篇(第一篇在这里,介绍如何开始构建React大型项目),简单介绍了React一些原理,包括React合成事件系统、组件的生命周期以及setState()

    React合成事件系统

    React快速的原因之一就是React很少直接操作DOM,浏览器事件也是一样。原因是太多的浏览器事件会占用很大内存。

    React为此自己实现了一套合成系统,在DOM事件体系基础上做了很大改进,减少了内存消耗,简化了事件逻辑,最大化解决浏览器兼容问题。

    其基本原理就是,所有在JSX声明的事件都会被委托在顶层document节点上,并根据事件名和组件名存储回调函数(listenerBank)。每次当某个组件触发事件时,在document节点上绑定的监听函数(dispatchEvent)就会找到这个组件和它的所有父组件(ancestors),对每个组件创建对应React合成事件(SyntheticEvent)并批处理(runEventQueueInBatch(events)),从而根据事件名和组件名调用(invokeGuardedCallback)回调函数。

    因此,如果你采用下面这种写法,并且这样的P标签有很多个:

    listView = list.map((item,index) => {
        return (
            <p onClick={this.handleClick} key={item.id}>{item.text}</p>
        )
    })
    

    That's OK,React帮你实现了事件委托。我之前因为不了解React合成事件系统,还显示的使用了事件委托,现在看来是多此一举的。

    由于React合成事件系统模拟事件冒泡的方法是构建一个自己及父组件队列,因此也带来一个问题,合成事件不能阻止原生事件,原生事件可以阻止合成事件。用 event.stopPropagation() 并不能停止事件传播,应该使用 event.preventDefault()

    如果你想详细了解React合成事件系统,移步http://blog.csdn.net/u013510838/article/details/61224760

    组件的生命周期(以父子组件为例)

    为了搞清楚组件生命周期,构造一个父组件包含子组件并且重写各生命周期函数的场景:

    class Child extends React.Component {
      constructor() {
        super()
        console.log('Child was created!')
      }
      componentWillMount(){
        console.log('Child componentWillMount!')
      }
      componentDidMount(){
        console.log('Child componentDidMount!')
      }
      componentWillReceiveProps(nextProps){
        console.log('Child componentWillReceiveProps:'+nextProps.data )
      }
      shouldComponentUpdate(nextProps, nextState){
        console.log('Child shouldComponentUpdate:'+ nextProps.data)
        return true
      }
      componentWillUpdate(nextProps, nextState){
        console.log('Child componentWillUpdate:'+ nextProps.data)
      }
      componentDidUpdate(){
        console.log('Child componentDidUpdate')
      }
      render() {
        console.log('render Child!')
        return (      
          <h1>Child recieve props: {this.props.data}</h1>      
        );
      }
    }
    
    class Father extends React.Component {
      // ... 前面跟子组件一样
      handleChangeState(){
        this.setState({randomData: Math.floor(Math.random()*50)})
      }
      render() {
        console.log('render Father!')
        return (
          <div>
            <Child data={this.state.randomData} />
            <h1>Father State: { this.state.randomData}</h1>      
            <button onClick={this.handleChangeState}>切换状态</button>
          </div>
        );
      }
    }
    
    React.render(
      <Father />,
      document.getElementById('root')
    );
    

    结果如下:
    刚开始

    Alt text


    调用父组件的setState后:

    Alt text


    在Jsbin上试试看
    有一张图能说明这之间的流程(图片来源):

    Alt text

     

    setState并不奇怪

    有一个能反映问题的场景:

    ...
    state = {
        count: 0
    }
    componentDidMount() {
      this.setState({count: this.state.count + 1})
      this.setState({count: this.state.count + 1})
      this.setState({count: this.state.count + 1})
    }
    ...
    

    看起来state.count被增加了三次,但结果是增加了一次。这并不奇怪:

    React快的原因之一就是,在执行this.setState()时,React没有忙着立即更新state,只是把新的state存到一个队列(batchUpdate)中。上面三次执行setState只是对传进去的对象进行了合并,然后再统一处理(批处理),触发重新渲染过程,因此只重新渲染一次,结果只增加了一次。这样做是非常明智的,因为在一个函数里调用多个setState是常见的,如果每一次调用setState都要引发重新渲染,显然不是最佳实践。React官方文档里也说了:

    Think of setState() as a request rather than an immediate command to update the component.

    setState() 看作是重新render的一次请求而不是立刻更新组件的指令。

    那么调用this.setState()后什么时候this.state才会更新?
    答案是即将要执行下一次的render函数时。

    这之间发生了什么?
    setState调用后,React会执行一个事务(Transaction),在这个事务中,React将新state放进一个队列中,当事务完成后,React就会刷新队列,然后启动另一个事务,这个事务包括执行 shouldComponentUpdate 方法来判断是否重新渲染,如果是,React就会进行state合并(state merge),生成新的state和props;如果不是,React仍然会更新this.state,只不过不会再render了。

    开发人员对setState感到奇怪的原因可能就是按照上述写法并不能产生预期效果,但幸运的是我们改动一下就可以实现上述累加效果:
    这归功于setState可以接受函数作为参数:

    setState(updater, [callback])

    ...
    state = {
        score: 0
    }
    componentDidMount() {
        this.setState( (prevState) => ({score : prevState.score + 1}) )
        this.setState( (prevState) => ({score : prevState.score + 1}) )
        this.setState( (prevState) => ({score : prevState.score + 1}) )
      }
    }
    

    这个updater可以为函数,该函数接受该组件前一刻的 state 以及当前的 props 作为参数,计算和返回下一刻的 state。

    你会发现达到增加三次的目的了: 在Jsbin上试试看

    这是因为React会把setState里传进去的函数放在一个任务队列里,React 会依次调用队列中的函数,传递给它们前一刻的 state。

    另外,不知道你在jsbin上的代码上注意到没有,调用setStateconsole.log(this.state.score)输出仍然为0,也就是this.state并未改变,并且只render了一次。

    总结

    学习一个框架或者工具,我觉得应该了解以下几点:

    1. 它是什么?能做什么?
    2. 它存在的理由是什么?解决了什么样的问题、满足了什么样的需求?
    3. 它的适用场景是什么?优缺点是什么?
    4. 它怎么用?最佳实践是什么?
    5. 它的原理是什么?
    6. ...

    通过对React一些原理的简单了解,就懂得了React为什么这么快速的原因之一,也会在问题出现时知道错在什么地方,知道合理的解决方案。



    作者:莫凡_Tcg
    链接:https://www.jianshu.com/p/12daf3731f9e
    来源:简书
    简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

    展开全文
  • react的工作原理

    2017-03-06 09:43:30
    现在最热门的前端框架有AngularJS、React、Bootstrap等。自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领略ReactJs的风采吧~~ 文章有点长,耐心读完,你会有很...

    现在最热门的前端框架有AngularJS、React、Bootstrap等。自从接触了ReactJS,ReactJs的虚拟DOM(Virtual DOM)和组件化的开发深深的吸引了我,下面来跟我一起领略ReactJs的风采吧~~ 文章有点长,耐心读完,你会有很大收获哦~

     一、ReactJS简介

      React 起源于 Facebook 的内部项目,因为该公司对市场上所有 JavaScript MVC 框架,都不满意,就决定自己写一套,用来架设 Instagram 的网站。做出来以后,发现这套东西很好用,就在2013年5月开源了。由于 React 的设计思想极其独特,属于革命性创新,性能出众,代码逻辑却非常简单。所以,越来越多的人开始关注和使用,认为它可能是将来 Web 开发的主流工具。

    ReactJS官网地址:http://facebook.github.io/react/

     

    Github地址:https://github.com/facebook/react

     

     二、对ReactJS的认识及ReactJS的优点

     首先,对于React,有一些认识误区,这里先总结一下:

    • React不是一个完整的MVC框架,最多可以认为是MVC中的V(View),甚至React并不非常认可MVC开发模式;
    • React的服务器端Render能力只能算是一个锦上添花的功能,并不是其核心出发点,事实上React官方站点几乎没有提及其在服务器端的应用;
    • 有人拿React和Web Component相提并论,但两者并不是完全的竞争关系,你完全可以用React去开发一个真正的Web Component;
    • React不是一个新的模板语言,JSX只是一个表象,没有JSX的React也能工作。

    1、ReactJS的背景和原理

      在Web开发中,我们总需要将变化的数据实时反应到UI上,这时就需要对DOM进行操作。而复杂或频繁的DOM操作通常是性能瓶颈产生的原因(如何进行高性能的复杂DOM操作通常是衡量一个前端开发人员技能的重要指标)。React为此引入了虚拟DOM(Virtual DOM)的机制:在浏览器端用Javascript实现了一套DOM API。基于React进行开发时所有的DOM构造都是通过虚拟DOM进行,每当数据变化时,React都会重新构建整个DOM树,然后React将当前整个DOM树和上一次的DOM树进行对比,得到DOM结构的区别,然后仅仅将需要变化的部分进行实际的浏览器DOM更新。而且React能够批处理虚拟DOM的刷新,在一个事件循环(Event Loop)内的两次数据变化会被合并,例如你连续的先将节点内容从A变成B,然后又从B变成A,React会认为UI不发生任何变化,而如果通过手动控制,这种逻辑通常是极其复杂的。尽管每一次都需要构造完整的虚拟DOM树,但是因为虚拟DOM是内存数据,性能是极高的,而对实际DOM进行操作的仅仅是Diff部分,因而能达到提高性能的目的。这样,在保证性能的同时,开发者将不再需要关注某个数据的变化如何更新到一个或多个具体的DOM元素,而只需要关心在任意一个数据状态下,整个界面是如何Render的。

    如果你像在90年代那样写过服务器端Render的纯Web页面那么应该知道,服务器端所要做的就是根据数据Render出HTML送到浏览器端。如果这时因为用户的一个点击需要改变某个状态文字,那么也是通过刷新整个页面来完成的。服务器端并不需要知道是哪一小段HTML发生了变化,而只需要根据数据刷新整个页面。换句话说,任何UI的变化都是通过整体刷新来完成的。而React将这种开发模式以高性能的方式带到了前端,每做一点界面的更新,你都可以认为刷新了整个页面。至于如何进行局部更新以保证性能,则是React框架要完成的事情。

      借用Facebook介绍React的视频中聊天应用的例子,当一条新的消息过来时,传统开发的思路如上图,你的开发过程需要知道哪条数据过来了,如何将新的DOM结点添加到当前DOM树上;而基于React的开发思路如下图,你永远只需要关心数据整体,两次数据之间的UI如何变化,则完全交给框架去做。可以看到,使用React大大降低了逻辑复杂性,意味着开发难度降低,可能产生Bug的机会也更少。

     

    2、组件化

      虚拟DOM(virtual-dom)不仅带来了简单的UI开发逻辑,同时也带来了组件化开发的思想,所谓组件,即封装起来的具有独立功能的UI部件。React推荐以组件的方式去重新思考UI构成,将UI上每一个功能相对独立的模块定义成组件,然后将小的组件通过组合或者嵌套的方式构成大的组件,最终完成整体UI的构建。例如,Facebook的instagram.com整站都采用了React来开发,整个页面就是一个大的组件,其中包含了嵌套的大量其它组件,大家有兴趣可以看下它背后的代码。

    如果说MVC的思想让你做到视图-数据-控制器的分离,那么组件化的思考方式则是带来了UI功能模块之间的分离。我们通过一个典型的Blog评论界面来看MVC和组件化开发思路的区别。

    对于MVC开发模式来说,开发者将三者定义成不同的类,实现了表现,数据,控制的分离。开发者更多的是从技术的角度来对UI进行拆分,实现松耦合。

    对于React而言,则完全是一个新的思路,开发者从功能的角度出发,将UI分成不同的组件,每个组件都独立封装。

    在React中,你按照界面模块自然划分的方式来组织和编写你的代码,对于评论界面而言,整个UI是一个通过小组件构成的大组件,每个组件只关心自己部分的逻辑,彼此独立。

    React认为一个组件应该具有如下特征:

    (1)可组合(Composeable):一个组件易于和其它组件一起使用,或者嵌套在另一个组件内部。如果一个组件内部创建了另一个组件,那么说父组件拥有(own)它创建的子组件,通过这个特性,一个复杂的UI可以拆分成多个简单的UI组件;

    (2)可重用(Reusable):每个组件都是具有独立功能的,它可以被使用在多个UI场景;

    (3)可维护(Maintainable):每个小的组件仅仅包含自身的逻辑,更容易被理解和维护;

     

     二、下载ReactJS,编写Hello,world

       ReactJs下载非常简单,为了方便大家下载,这里再一次给出下载地址http://facebook.github.io/react/downloads.html,下载完成后,我么看到的是一个压缩包。解压后,我们新建一个html文件,引用react.js和JSXTransformer.js这两个js文件。html模板如下(js路径改成自己的):

    复制代码
    <!DOCTYPE html>
    <html>
      <head>
        <script src="build/react.js"></script>
        <script src="build/JSXTransformer.js"></script>
      </head>
      <body>
        <div id="container"></div>
        <script type="text/jsx">
          // ** Our code goes here! **
        </script>
      </body>
    </html>
    复制代码

      这里大家可能会奇怪,为什么script的type是text/jsx,这是因为 React 独有的 JSX 语法,跟 JavaScript 不兼容。凡是使用 JSX 的地方,都要加上 type="text/jsx" 。 其次,React 提供两个库: react.js 和 JSXTransformer.js ,它们必须首先加载。其中,JSXTransformer.js 的作用是将 JSX 语法转为 JavaScript 语法。这一步很消耗时间,实际上线的时候,应该将它放到服务器完成。

    到这里我们就可以开始编写代码了,首先我们先来认识一下ReactJs里面的React.render方法:

    React.render 是 React 的最基本方法,用于将模板转为 HTML 语言,并插入指定的 DOM 节点。

    下面我们在script标签里面编写代码,来输出Hello,world,代码如下:

    React.render(
            <h1>Hello, world!</h1>,
            document.getElementById('container')
          );

    这里需要注意的是,react并不依赖jQuery,当然我们可以使用jQuery,但是render里面第二个参数必须使用JavaScript原生的getElementByID方法,不能使用jQuery来选取DOM节点。

     然后,在浏览器打开这个页面,就可以看到浏览器显示一个大大的Hello,world,因为我们用了<h1>标签。

    到这里,恭喜,你已经步入了ReactJS的大门~~下面,让我们来进一步学习ReactJs吧~~

     

     三、Jsx语法

       HTML 语言直接写在 JavaScript 语言之中,不加任何引号,这就是 JSX 的语法,它允许 HTML 与 JavaScript 的混写,了解过AngularJs的看到下面的代码一定会感觉很熟悉的,我们来看代码:

    复制代码
    var names = ['Jack', 'Tom', 'Alice'];
    
          React.render(
            <div>
            {
              names.map(function (name) {
                return <div>Hello, {name}!</div>
              })
            }
            </div>,
            document.getElementById('container')
          );
    复制代码

    这里我们声明了一个names数组,然后遍历在前面加上Hello,输出到DOM中,输出结果如下:

    JSX 允许直接在模板插入 JavaScript 变量。如果这个变量是一个数组,则会展开这个数组的所有成员,代码如下:

    复制代码
    var arr = [
            <h1>Hello world!</h1>,
            <h2>React is perfect!</h2>,
          ];
          React.render(
            <div>*{arr}*</div>,
            document.getElementById('container')
          );
    复制代码

    显示结果如下:

    这里的星号只是做标识用的,大家不要被她迷惑了~~

     你看到这里,说明你对React还是蛮感兴趣的,恭喜你,坚持下来了,那么下面,我们开始学习React里面的"真功夫"了~~ Are you ready?

     

     四、ReactJS组件

    1、组件属性 

      前面说了,ReactJS是基于组件化的开发,下面我们开始来学习ReactJS里面的组件,React 允许将代码封装成组件(component),然后像插入普通 HTML 标签一样,在网页中插入这个组件。React.createClass 方法就用于生成一个组件类。

    下面,我们来编写第一个组件Greet,有一个name属性,然后输出hello + name的值,代码如下:

    复制代码
    var Greet = React.createClass({
            render: function() {
              return <h1>Hello {this.props.name}</h1>;
            }
          });
    
          React.render(
            <Greet name="Jack" />,
            document.getElementById('container')
          );
    复制代码

    看到这段代码,接触过AngularJS的朋友们是不是有一种熟悉的感觉,不过这里有几点需要注意:

      1、获取属性的值用的是this.props.属性名

      2、创建的组件名称首字母必须大写。

      3、为元素添加css的class时,要用className.

      4、组件的style属性的设置方式也值得注意,要写成style={{width: this.state.witdh}}

     

    2、组件状态

      组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI 。下面我们来编写一个小例子,一个文本框和一个button,通过点击button可以改变文本框的编辑状态,禁止编辑和允许编辑。通过这个例子来理解ReactJS的状态机制。先看代码:

    复制代码
    var InputState = React.createClass({
            getInitialState: function() {
              return {enable: false};
            },
            handleClick: function(event) {
              this.setState({enable: !this.state.enable});
            },
            render: function() {
              
              return (
                <p>
                   <input type="text" disabled={this.state.enable} />
                   <button onClick={this.handleClick}>Change State</button>
                </p>
              );
            }
          });
    
          React.render(
            <InputState />,
            document.getElementById('container')
          );
    复制代码

    这里,我们又使用到了一个方法getInitialState,这个函数在组件初始化的时候执行,必需返回NULL或者一个对象。这里我们可以通过this.state.属性名来访问属性值,这里我们将enable这个值跟input的disabled绑定,当要修改这个属性值时,要使用setState方法。我们声明handleClick方法,来绑定到button上面,实现改变state.enable的值.效果如下:

    原理分析:

       当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。

    这里值得注意的几点如下:

      1、getInitialState函数必须有返回值,可以是NULL或者一个对象。

      2、访问state的方法是this.state.属性名。

      3、变量用{}包裹,不需要再加双引号。

     

    3、组件的生命周期  

    组件的生命周期分成三个状态:

    • Mounting:已插入真实 DOM
    • Updating:正在被重新渲染
    • Unmounting:已移出真实 DOM

    React 为每个状态都提供了两种处理函数,will 函数在进入状态之前调用,did 函数在进入状态之后调用,三种状态共计五种处理函数。

    • componentWillMount()
    • componentDidMount()
    • componentWillUpdate(object nextProps, object nextState)
    • componentDidUpdate(object prevProps, object prevState)
    • componentWillUnmount()

    此外,React 还提供两种特殊状态的处理函数。

    • componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用
    • shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用

     

    下面来看一个例子:

    复制代码
     var Hello = React.createClass({
            getInitialState: function () {
              return {
                opacity: 1.0
              };
            },
    
            componentDidMount: function () {
              this.timer = setInterval(function () {
                var opacity = this.state.opacity;
                opacity -= .05;
                if (opacity < 0.1) {
                  opacity = 1.0;
                }
                this.setState({
                  opacity: opacity
                });
              }.bind(this), 100);
            },
    
            render: function () {
              return (
                <div style={{opacity: this.state.opacity}}>
                  Hello {this.props.name}
                </div>
              );
            }
          });
    
          React.render(
            <Hello name="world"/>,
            document.body
          );
    复制代码

    上面代码在hello组件加载以后,通过 componentDidMount 方法设置一个定时器,每隔100毫秒,就重新设置组件的透明度,从而引发重新渲染。

     

    4、组件的嵌套

      React是基于组件化的开发,那么组件化开发最大的优点是什么?毫无疑问,当然是复用,下面我们来看看React中到底是如何实现组件的复用的,这里我们还写一个例子来说吧,代码如下:

    复制代码
    var Search = React.createClass({
            render: function() {
              return (
                <div>
                   {this.props.searchType}:<input type="text" />
                   <button>Search</button>
                </div>
              );
            }
          });
          var Page = React.createClass({
            render: function() {
              return (
                <div>
                   <h1>Welcome!</h1>
                   <Search searchType="Title" />
                   <Search  searchType="Content" />
                </div>
              );
            }
          });
          React.render(
            <Page />,
            document.getElementById('container')
          );
    复制代码

    这里我们创建了一个Search组件,然后又创建了一个Page组件,然后我们在Page组件中调用Search组件,并且调用了两次,这里我们通过属性searchType传入值,最终显示结果如图:

     

     五、ReactJs小结

    关于ReactJS今天就先学习到这里了,下面来总结一下,主要有以下几点:

      1、ReactJs是基于组件化的开发,所以最终你的页面应该是由若干个小组件组成的大组件。

      2、可以通过属性,将值传递到组件内部,同理也可以通过属性将内部的结果传递到父级组件(留给大家研究);要对某些值的变化做DOM操作的,要把这些值放到state中。

      3、为组件添加外部css样式时,类名应该写成className而不是class;添加内部样式时,应该是style={{opacity: this.state.opacity}}而不是style="opacity:{this.state.opacity};"。

      4、组件名称首字母必须大写。

      5、变量名用{}包裹,且不能加双引号。

     

     六、ReactJS优缺点

    优点:

    React速度很快

    与其它框架相比,React采取了一种特立独行的操作DOM的方式。
    它并不直接对DOM进行操作。
    它引入了一个叫做虚拟DOM的概念,安插在JavaScript逻辑和实际的DOM之间。
    这一概念提高了Web性能。在UI渲染过程中,React通过在虚拟DOM中的微操作来实对现实际DOM的局部更新。


    跨浏览器兼容

    虚拟DOM帮助我们解决了跨浏览器问题,它为我们提供了标准化的API,甚至在IE8中都是没问题的。


    模块化

    为你程序编写独立的模块化UI组件,这样当某个或某些组件出现问题是,可以方便地进行隔离。
    每个组件都可以进行独立的开发和测试,并且它们可以引入其它组件。这等同于提高了代码的可维护性。

    单向数据流让事情一目了然

    Flux是一个用于在JavaScript应用中创建单向数据层的架构,它随着React视图库的开发而被Facebook概念化。它只是一个概念,而非特定工具的实现。它可以被其它框架吸纳。例如,Alex Rattray有一个很好的Flux实例,在React中使用了Backbone的集合和模型。

    纯粹的JavaScript

    现代Web应用程序与传统的Web应用有着不同的工作方式。
    例如,视图层的更新需要通过用户交互而不需要请求服务器。因此视图和控制器非常依赖彼此。
    许多框架使用Handlebars或Mustache等模板引擎来处理视图层。但React相信视图和控制器应该相互依存在一起而不是使用第三方模板引擎,而且,最重要的是,它是纯粹的JavaScript程序。

    同构的JavaScript


    单页面JS应用程序的最大缺陷在于对搜索引擎的索引有很大限制。React对此有了解决方案。
    React可以在服务器上预渲染应用再发送到客户端。它可以从预渲染的静态内容中恢复一样的记录到动态应用程序中。
    因为搜索引擎的爬虫程序依赖的是服务端响应而不是JavaScript的执行,预渲染你的应用有助于搜索引擎优化。

    React与其它框架/库兼容性好

    比如使用RequireJS来加载和打包,而Browserify和Webpack适用于构建大型应用。它们使得那些艰难的任务不再让人望而生畏。

    缺点?

    React本身只是一个V而已,所以如果是大型项目想要一套完整的框架的话,也许还需要引入Flux和routing相关的东西。

    大多数坑没踩出来

      


    转载于:雲霏霏 和 月迷津渡丶

    展开全文
  • 有两种方法: 使用react-app-rewired customize-cra, 修改config-overrides.js文件 const { override, } = require("customize-cra"); const path = require("path"); module.exports = override( (config) =>...

    有两种方法:

    1. 使用react-app-rewired customize-cra, 修改config-overrides.js文件
    const {
      override,
    } = require("customize-cra");
    const path = require("path");
    module.exports = override(
      (config) => {
        config.resolve.alias = {
          "@": path.resolve(__dirname, "src"),
        };
        config.devtool = false; //去掉map文件
        return config;
      },
    );
    
    1. 配置环境变量
      在项目根目录下新建.env文件,打开文件添加 GENERATE_SOURCEMAP=false 即可
      原理: React脚手架工具默认的webpack文件,在这里检查了环境变量是否开启SourceMap
      image.png
    展开全文
  • React.js有一套自己调用Google Map的机制。 附链接:https://www.npmjs.com/package/google-maps-react 首先,你需要去申请一个API key。 具体的安装和使用方法在以上链接中都有,这里主要想记录一下标记地点的...

    React.js有一套自己调用Google Map的机制。
    附链接:https://www.npmjs.com/package/google-maps-react

    首先,你需要去申请一个API key。
    具体的安装和使用方法在以上链接中都有,这里主要想记录一下标记地点的写法。
    Google Map自带的marker可以实现标记地点的功能。

    代码如下:

    import React from 'react';
    import {Map, InfoWindow, Marker, GoogleApiWrapper} from 'google-maps-react';
    
    export class GMap extends React.Component {
      state = {
        showingInfoWindow: false,
        activeMarker: {},
        selectedPlace: {},
      };
    
      onMarkerClick = (props, marker, e) =>
        this.setState({
          selectedPlace: props,
          activeMarker: marker,
          showingInfoWindow: true
        });
    
      onMapClicked = (props) => {
        if (this.state.showingInfoWindow) {
          this.setState({
            showingInfoWindow: false,
            activeMarker: null
          })
        }
      };
    
      render() {
        return (
          <Map google={this.props.google}
               initialCenter={{
                 lat: 39.9060115,
                 lng: 116.3956187
               }}
               zoom={16.75}
               onClick={this.onMapClicked}>
            <Marker onClick={this.onMarkerClick}
                    name={'descripton'}
                    position={{lat: 39.9055688, lng: 116.39749}}/>
    
            <InfoWindow
              marker={this.state.activeMarker}
              visible={this.state.showingInfoWindow}>
              <div>
                <h3>{this.state.selectedPlace.name}</h3>
              </div>
            </InfoWindow>
          </Map>
        )
      }
    }
    
    export default GoogleApiWrapper({
      apiKey: (YOUR_GOOGLE_API_KEY_GOES_HERE)
    })(GMap)

    展示效果:
    这里写图片描述
    这是一个对天安门广场进行标记的地图。

     <Map google={this.props.google}
               initialCenter={{
                 lat: 39.9060115,
                 lng: 116.3956187
               }}
               zoom={16.75}
               onClick={this.onMapClicked}>

    initialCenter可以确定初始位置。

    <Marker onClick={this.onMarkerClick}
                    name={'descripton'}
                    position={{lat: 39.9055688, lng: 116.39749}}/>
    

    position确定的是标记位置。
    其中lat和lng代表的是一个地点的经纬度。
    那么怎么获取一个地点的经纬度呢?
    可以通过Google在线地图获取。
    在搜索框中输入想要找到的标记的名字的名字,鼠标收缩找到想要展示的页面的收缩比例。记录下经纬度和zoom值。
    这里写图片描述
    如图所示,我希望最终展示的地图的比例如图所示,只需在initialCenter中记录该地址的经纬度,以及zoom值即可。
    这里写图片描述
    图中地址中包含其经纬度及z值。

    然后是标记的经纬度。若想使位置更为准确,建议将地图放大至最大,记录下经纬度,将其写在marker的position中即可。

    marker的形状是可以更改的。
    附链接:https://www.cnblogs.com/Leo_wl/p/5797870.html

    查了好几天怎么调用地图,怎么标记地点,终于尘埃落定。
    虽然其中原理并未完全搞懂,不过想要的效果已经出来了,算是近了一大步。

    展开全文
  • 干货,无话 ...2、npm install react-amap,引入高德地图的封装; 3、编写组件index.js: import React from "react"; import ReactDOM from "react-dom"; import Map from "./Map3"; let mapDat...

    干货,无话

     

    1、react-create-app,创建新react项目;

    2、npm install react-amap,引入高德地图的封装;

    3、编写组件index.js:

    import React from "react";
    import ReactDOM from "react-dom";
    import Map from "./Map3";
    
    let mapData = {
        city: "北京",
        mapCenter:[116.418261, 39.921984],  //城市定位,经纬度定位只能选择1个
        mapZoom: 10, //地图缩放
        mapKey: '12345678d98aff1166e51962f108bb24',   //你的高德key
        status: { //是否支持放大拖拽
            zoomEnable: true,
            dragEnable: true,
        },
        mapMaker :[  //marker标记点(list)
            {lnglat:[116.401728,39.911984],text:'要显示的内容1'},
            {lnglat:[116.436691,39.921984],text:'要显示的内容2'}
        ],
        plugins:['ToolBar']
    };
    
    ReactDOM.render(
        <div style ={{width:"100%",height:"100%"}}>    
            <Map title="map" mapData={mapData}/>
        </div>,
    
        document.getElementById("root")
    );
    

      注意render方法内引用了Map组件,因此要编写一个Map3.js,提供这个组件

    4、编写Map3.js组件

    import React, { Component } from "react";
    import { Map, Marker } from 'react-amap';
    import ZoomCtrl from './zoom';
    
    class WebMap3 extends Component {
        constructor(props) {
            super(props);
            this.data = props;
            //地图事件
            this.amapEvents = {
                created: (mapInstance) => {
                    var marker = new AMap.Marker({
                        // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9]
                        position: new AMap.LngLat(116.39, 39.9), 
                        title: '北京!!'
                    });
                    
                    mapInstance.add(marker);
                }
            };
    
            //点位事件
            this.markerEvents = {
                click: (markerInstance) => {
                    this.Position = [markerInstance.lnglat.lng,markerInstance.lnglat.lat];
                    this.setState({
                        isShow: true,
                    });
                }
            };
        }
    
        render() {
            let {city, mapCenter,  mapZoom, mapKey, status, plugins} = this.data.mapData;
            return (
                <div style ={{width:"100%",height:"95%"}}>
                <Map amapkey={mapKey} city={city} zoom={mapZoom} center={mapCenter} status={status} plugins={plugins} events={this.amapEvents}>
                    {this.data.mapData.mapMaker.map((comment) => (
                        <Marker position={comment.lnglat} events={this.markerEvents}>
                        </Marker>
                    ))}
                    <ZoomCtrl />
                </Map>
                </div>
            );
        }
    
    }
    
    export default WebMap3;
    

      注意标红部分,会报错

    这个是关键! 有两个办法解决,分别见下面的5.1和5.2

     

    5、解决react下找不到原生高德地图AMap类的问题

    5.1 方法1

    暴力手段,直接搞定。

    使用注释    //eslint-disable-next-line  写在每个出现AMap类的前面一行,如下所示

    原理是告诉eslint:注释下面这一行您别管。

     5.2 方法2

    强迫症手段,分为3步。

    5.1.1 在项目根目录下新加.eslintrc.js文件,把AMap变量放到globals集合里面

    module.exports = {
        "env": {
            "browser": true,
            "es6": true
        },
        // 脚本在执行期间访问的额外的全局变量
        // 当访问未定义的变量时,no-undef 规则将发出警告。
        // 如果你想在一个文件里使用全局变量,推荐你定义这些全局变量,这样 ESLint 就不会发出警告了。
        // 你可以使用注释或在配置文件中定义全局变量
        "globals": {
            "Atomics": "readonly",
            "SharedArrayBuffer": "readonly",
            "AMap":true,
            "window":true,
            "document":true,
        },
        "parserOptions": {
            "ecmaFeatures": {
                "jsx": true
            },
            "ecmaVersion": 2018,
            "sourceType": "module"
        },
        "plugins": [
            "react"
        ],
        "rules": {
            "semi": ["error","always"],
        }
    };  

    注意红色部分代码表示:AMap是个全局变量,是webpack我罩着的,保证能用,eslint你别管。

    当然,webpack.config.js要做点修改,以支持我们刚写的.eslintrc.js文件。可是react-create-app生成的项目的webpack.config.js不好找啊,也能找到:

    5.2.2 修改 node_modules\react-scripts\config\webpack.config.js文件

    在这个文件搜索字符串 useEslintrc, 大概在webpack.config.js文件的第326行,把 useEslintrc: false,  改成 useEslintrc: true, 然后保存。如下所示:

    5.2.3 完工

     呃

     

    6 验收

    在控制台运行npm start,然后访问http://localhost:3000,出现下图表示OK!

     

    7 总结

    此方法适用于在react中调用jquery、百度地图、高德地图、OpenLayer、echart等等使用ES5编写的各类控件库。

    转载于:https://www.cnblogs.com/zjw0901/p/11103744.html

    展开全文
  • Source Map原理探究

    2019-06-17 10:54:04
    摘要: Source Map很神奇,它的原理挺复杂的… 原文:source map原理探究 地址:https://www.cnblogs.com/Wayou/p/understanding_frontend_source_map.html 作者:刘哇勇 Fundebug经授权转载,版权归原作者所有...
  • 一: 使用 react-app-rewired 时,除了根据文档对应修改设置外,还给予了一些配合此插件直接使用的 webpack 插件集:... 反之,根据观...
  • react工作原理

    2019-01-02 15:04:08
    现在最热门的前端框架有AngularJS、React、Bootstrap等。自从接触了ReactJS,ReactJs的虚拟DOM(Virtual&amp;amp;amp;nbsp;DOM)和组件化的开发深深的吸引了我,下面来跟我一起领略ReactJs的风采吧~~ 文章有点长...
  • react和vue底层原理

    2020-05-28 23:33:25
    react的diff算法? 1.把树形结构按照层级分解,只比较同级元素。时间复杂度为n 2.给列表结构的每个单元...4.合并操作,调用 component 的 setState 方法的时候, React 将其标记为 dirty.到每一个事件循环结束, Re...
  • 一、 React 的使用 React 的基本知识点,如下所示: JSX 基本使用,变量、表达式、class style、子元素和组件等等,代码如下所示: import React from 'react' import './style.css' import List from '../List'...
  • React-Redux使用方法

    2018-07-17 15:22:35
    React-Redux使用方法 理解 在React项目中使用react-redux,可以让你更方便的使用redux,原理是在index.js中注册app时用一个&lt;Povider&gt;标签嵌套,把你的App.js变Provideer的子组件,将所有的...
  • 感慨:react-thunk真的是经典的不能再经典的中间件,它对applyMiddleware的利用真的是登峰造极。 react-thunk源码分析 react-thunk源码: function createThunkMiddleware(extraArgument) { return ({ dispatch, ...
  • 很多人都使用过React,但是很少人能说出它内部的渲染原理。有人会说,会用就行了,知道渲染原理有必要么?其实渲染原理决定着性能优化的方法,只有在了解原理之后,才能完全理解为什么这样做可以优化性能。正所谓:...
  • 2019独角兽企业重金招聘Python工程师标准>>> ...
  • 简述react-router-dom原理

    2020-02-25 10:34:59
    实现根据不同路径渲染不同的组件 有两种实现方式: HashRouter :利用监听hash变化(有一个事件hashchange)实现路由切换,它是路由容器,渲染子组件,并向下层子组件传递(Context上下文传递)loaction,history等...
  • React通过引入Virtual DOM的概念,极大地避免无效的Dom操作,已使我们的页面的构建效率提到了极大的提升。但是如何高效地通过对比新旧Virtual DOM来找出真正的Dom变化之处同样也决定着页面的性能,React用其特殊的...
  • 第一步 ... 第二步 ...注意:AMap类不是react中定义的类,会在运行时报错, 暴力手段,直接搞定。 使用注释 //eslint-disable-next-line写在每个出现AMap类的前面一行,如下所示 原理是告诉esl...
  • [Java 8 HashMap 详解系列] 文章目录 1.HashMap 的存储数据...3.HashMap 的 put() 方法执行原理 4.HashMap 的 get() 方法执行原理 5.HashMap 的 remove() 方法执行原理 6.HashMap 的扩容 resize() 原理 7.HashMap ...
  • 前言以下,是我在2018 React Conf的分享内容,希望对大家有所帮助。可以先在官网下载我的ppt...其实渲染原理决定着性能优化的方法,只有在了解原理之后,才能完全理解为什么这样做可以优化性能。正所谓:知其然,然...
1 2 3 4 5 ... 20
收藏数 6,398
精华内容 2,559