博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
React
阅读量:6568 次
发布时间:2019-06-24

本文共 12895 字,大约阅读时间需要 42 分钟。

网页总是一个链接着另一个的,React一大优势在于每次链接到另一个页面上去的时候,不需要向传统页面一样,得销毁所有代码,重新渲染新页面的代码,而只在一个页面上展现新的内容——单页页面

React另一个优势是,以往的单页页面你需要考虑哪个元素要被删除、哪个元素的行为要被修改,而我们只需要告诉React我们想要的最终页面的效果,React会自动帮我们处理页面上的元素,做删除、修改等操作。

而我只知道React有自己的虚拟DOM,它会对比虚拟DOM和真实DOM的差别,然后在适当的时机更新页面。至于它怎么对比的?怎么知道差别的?怎么进行修改的?我不知道,不过,对于我们,谁在乎呢?

必须首先知道的关于React的术语

  • JSX语法:React特有语法,用来搭建虚拟DOM
  • 组件(Component):一个个代码块,用来封装各种功能,可以类比于函数(function
  • props&status:组件的所有静态属性 & 所有动态属性

引入React

想要使用React,你需要先引入:

上面两个<script>引入了React的核心库,最后一句<script>引入jsx语法编译器,因为浏览器不懂jsx只知道javascript,所以,引入编译器转换为浏览器能懂的javascript语言

请参考React官方文档以获取最新版本React的引入:

初步使用React

并没有什么特别的技巧,先看代码,再做解释:

    
React First Try

解释:

  • 首先引入了三个<script>
  • 新建一个元素<div id="container"></div>
  • 我们必须在一个<scripr type="text/babel">中使用React,请注意<script>type
  • 像一般的javascript语法一样,我们先获取页面元素

    var container = document.querySelector("#container");
  • 修改虚拟DOM,并渲染真实DOM

    其中,ReactDOM.render();就是在渲染,其含义是将第一个参数渲染到第二个参数下。而第一个参数<div>...</div>就是新的虚拟DOM的内容,可更改为我们想要的真实DOM结构。

    ReactDOM.render(    

    Batman

    catwoman

    , container);
  • 效果、页面结构

初用React

初用React_页面结构

  • 我们看到,页面中已经添加了包含两个<p>元素的<div>React.render()函数的第一个参数只能是一个标签,不能是并列的两个标签。不过一个标签里的子标签可以随便的添加,所以最好的方法就是,在外面添加一个<div></div>

使用组件(Component

上面的方法是直接将你想要的写在React.render()里,通常的做法是引用组件

  • 定义一个组件

    class 组件名 extends React.Component(    //your code);
  • 组件里可以添加很多功能,比如想要添加一个按钮,你只需直接写你想要的DOM结构,而不需要使用javascript语法:createElement()appendChild()

    class 组件名 extends React.Component(    render(){        return ();    });
  • 在组件里写好你想要的东西,使用React.render()进行渲染

    React.render(    
    <组件名 />, 想要渲染的位置)
  • 完整代码可以如下

        
    React First Try
  • 效果、页面结构

初用组件

初用组件_页面结构

  • 我们看到,页面上出现了我们想要的按钮,页面结构里也成功添加了<button>标签。注意!!!组件名首字母必须大写!!!引用组件注意代码<组件名/>,一个符号都不能错的!!!

使用props

props用来获取组件的静态属性,可以先看下面的一个小例子:

    
React First Try

不必惊慌,修改的地方只有组件的render()和实际渲染的render()两个函数。

  • 第一个render()添加了<button>type属性,该属性值指向{this.props.buttontype},意思是该组件名为buttontype的静态属性。这个render()还将<button>的显示文字指向{this.props.children},意思是该组件的子元素这个静态属性
  • 第二个render()函数添加了<Myname>的静态属性buttontype,和一个text类型的子元素Batman
  • 结论就是:在渲染真实DOM的时候,会创建一个<button></button>标签,它的type属性值为submit,文字显示为Batman
  • 效果、页面结构,哈哈哈,没啥区别,没区别就对了:

使用props

react_props_页面结构

props的传递性

props只能从父元素向下传递给子元素:

props_传递性

当有多个属性你想传递的时候,你的代码可能就会是这样的,会重复很多遍{this.props.propsName}

如果你不想重复很多遍繁琐的{this.props.propsName},那你可以使用扩展运算符...表示取到所有的静态属性并且都使等于{this.props.propsName},所以我们的代码可以稍作简化:

React操作CSS

此方法可以使你在<script>里更改、渲染CSS。不过使用ReactJSX语法会和CSS语法有一点点不同,就一点点┑( ̄Д  ̄)┍

因为刚开始接触,代码不难,所以直接先看示例代码吧;

    
React First Try
  • 哇!!代码怎么看上去又有这么多的改动啊!!别慌张别慌张!其实和上一小节一样,只改动了一些内容在组件的render()和真实渲染的render()两个函数里
  • 组件render()里首先定义了一个虚拟CSS类,看上去符合CSS语法,但其实呢,他是一个JSX语法,仔细看,它就是一个用JSX语法写的神似CSS对象。其中的一些区别如下:

    • 它不应该有pxpx这种东西JSX会自动补充
      react_css_没有px
    • 它不应该有分号;来表示这个属性结束了,请使用逗号,
      react_css_逗号
    • 它应该把除了纯数字外的所有属性值都加上引号""
      react_css_引号的使用
    • 它应该使用驼峰命名法来表示CSS使用连接号-的属性名:backgroundColor
      react_css_驼峰命名法
  • 所以,在遵循了所有使用JSX语法描述CSS状态的规则之后,你就可以成功的定义一个虚拟CSS。接着,在组件的render()里调用它,像这样<div style={letterColor}>style={虚拟CSS名}
  • 在这里另一个知识点是,在定义虚拟CSSbackgroundColor时,它的参数值是一个变量this.props.thiscolor,同上一小节一样,在真实渲染render()的第一个参数里定义这个静态变量<Mycss thiscolor="#58B3FF">。这样,就成功在CSS(虚拟的)里调用了其它地方的变量来确定属性值。
  • 效果、页面结构:值得注意的是,React处理的CSS是通过内联方式(标签中插入style属性)实现的

react_css_效果

react_css_页面结构

小结

这个时候,我们需要做一个小例子,来巩固下关于组件CSS引入props的概念

我们想要实现的效果

我们想要实现的效果就是,当你输入颜色代码,上面就能正确的展示颜色:

调色板_效果

分离组件

React的世界,一切都是组件,页面上所有的内容都是由一个个组件搭建起来的。你可以将结构划分为很小的组件,这样实现的功能就很详细。你也可以将结构划分为稍大的组件,功能就更集中。

所以,像我们这样的小应用,下面的组件划分方法就足以满足要求:

调色板_组件划分

编写程序

在分析完结构需要分成多少组件之后,可以开始构造代码~

  • 首先,我们编写组件框架。其中每一个class就代表了我们分成的组件。在这里class ColorName表示文字部分,class Color表示颜色显示区,class Board表示用来承载这个应用的底板。每个组件都有一个render()函数用来之后渲染组件到DOM上。

        
    Color
  • 上述步骤等于搭完了骨架,我们需要填充肌肉。写下,最终需要每个组件分别返回什么标签:

    ColorName组件返回一个<p>标签,用以展现颜色的色号
    Color组件返回一个<div>标签,用来显示颜色
    Board组件返回一个<div>标签,并且把上两个组件包在一起

        
    Color
  • 接下来我们只需要添加你想要的CSS就OK了,不过在添加CSS之前,我想对上一步骤简单解释:我们在渲染真实DOM时定义了一个静态属性colorName="#f7a87d",经由组件Board传入组件ColorNameColor。最后通过每个组件各自的render()函数的return渲染在页面上。
  • 最后我们需要添加一些CSS帮页面穿点衣服,其中对CSS的引入使用了两种方法,使用React引入和引入外部CSS文件:

        
    Color

使用state

以上的各个步骤可以创建一个基本的静态页面,如果想要创建一个有点动态,看上不是死气沉沉的页面,那就一定需要state。正如之前提到的,props包含了所有的静态属性,state则包含了所有用于动态展示的属性。

这时,我们需要一个例子

我们的目标

react_state_效果

分离组件

外面一个黑的长方形边框;内部一个黑色的底板;#5dffff的动态数字;三行文字

编写代码

  • 编写代码框架:Times类表示变化的数字;Words表示三行灰色的文字;BlackBoard表示黑色的底板;Board表示最外面一圈黑边框

        
    Lightning
  • 然后我们需要添上返回的内容,我们就只看React的内容

    react_state_1

  • Strike Times变成动态,我们只需改变Times类:

    • 首先需要定义state:必须在constructor内定义this.state={}

      constructor(props){    super(props);    this.state = {        strike: 0,    };}
    • 使用生命周期钩子componentDidMount钩子里的内容会在页面渲染完成后被调用.

      在本例中,页面渲染完成后会调用一个计时器setInterval(),计时器中调用的函数请使用箭头函数,这样被调用的函数里的this才会被正确的指向当前类,其它调用方法会指向window

      componentDidMount() {    setInterval(() => this.addNumber(),1000);}
    • 定义你想调用的函数

      注意!!!如果你想修改state中的值,请必须使用this.setState()来修改!!

      addNumber(){    this.setState({        strike: this.state.strike + 100,    });}
    • 最后,设定返回值,显示的内容为state中的strike

      render(){    return (

      {this.state.strike}

      );}

react_state_2

  • 加上点样式

react_state_结果

使用JSX

即使我们在之前的文章中已经开始使用了JSX这种React特别的语法,但是,我们还是应该为它专门开辟一个新的章节,因为,JSX组件组件生命周期React的三大奠基核心(哈哈哈,当然是我的个人见解)。

说到JSX,令人印象深刻的就是各种在js里添加html标签和出现在各个地方的{}

js里添加html标签

在提倡 css样式js行为html标签 分离的时代,这样的设计别出心裁。主要是因为React的基础设施不是传统的html标签,而是各个组件。一个组件里包含了构成页面某一部分所需要的所有的 css样式js行为html标签 。 所以,遵循这样的思路,在js里添加html标签没什么稀奇的。

像这样:

var myname = 

Batman

;
function functionName(){    // your codes    return 

Batman

;}
const me = (  

Batman

hello gotham

);

注意!!!JSX不能够将 多个html标签 直接赋给一个变量或者直接返回,需要将 多个html标签 包括在一个父元素中,就像上例第三个例子一样。

{}

js里添加html标签对我们来说已经见怪不怪了,大括号{}的使用才是精髓。哈哈哈~~

{}用于在React中的各个地方引用各种合理的JS表达式(valid JavaScript expression)。大括号里可以是变量user.username、表达式2+2、函数调用functionName(user)等。

像这样:

const name = 'Josh Perez';const element = 

Hello, {name}

;
const element = ;
const element = 

2+2={2+2}

;
function formatName(user) {  return user.firstName + ' ' + user.lastName;}const user = {  firstName: 'Harper',  lastName: 'Perez'};const element = (  

Hello, {formatName(user)}!

);ReactDOM.render( element, document.getElementById('root'));

另外,还有双括号{

{}}的写法,这种表达方式用于在JSX里内联样式。

{

{}}内的内容:

  • 对象的写法,将css里的;变成,
  • 属性名使用驼峰写法,css里-后面的第一个字母大写
  • 只会生效最后一个style,下例中只会生效style={gothamStyle}

    var myName = 

    Batman

    ;

像这样:

const myName = 

Batman

;

关于更多React中操作CSS,你还可以浏览这篇文章:

JSX的优势

  • 防止XSS (cross-site-scripting)攻击。因为所有内容在被React渲染到页面上前都会先转成字符串
  • 小巧灵活。JSX本质就是Javascript,所以,JSX可以被放在任何一个地方。再加上JSX里的内容非常丰富。结合React的设计思想,JSX非常好用。
  • 当然JSX还可以撰写css内容,详细可以参见之前章节:React操作CSS

使用JSX的一个例子

只要使用React搭建网站必然需要用到JSX,额,虽然官方是这样表示的:

jsx使用与否
Well~我们还是快速的过一遍这个例子

我们要实现的目标

几个圆圈过1秒就变颜色,颜色随机从颜色库里选取

jsx例子效果图

完整代码

其实很简单,Circle组件负责改变颜色的行为,CreateCircle组件负责定义样式并渲染这些圆圈。

然后因为一直是动态的,所以,使用Circle组件的state,每个一段时间setInterval都会调用changeColor函数,来改变state里的内容,改变之后React会重新渲染页面被改动的部分。

值得注意的是,在这个例子中,JSX被运用在任何一个位置,

  • 可以被压到数组中去

    colorarray.push(
    )
  • 被渲染

    render(){    return (
    {this.state.colorArray}
    );};
  • 撰写、引用css

    class CreateCircle extends React.Component{    render(){        var circleStyle = {            padding: 10,            margin: 20,            display: "inline-block",            backgroundColor: this.props.bgColor,            borderRadius: "50%",            width: 100,            height: 100,        };        return (
    ); }};

注意!!!在React中使用key={}属性来唯一标识一个组件<CreateCircle key={i}/>

完整代码:

    
Lightning

React中的事件

事件的意义不用多说,事件是页面与用户交互的唯一途径,人机交互大部分还是通过鼠标和键盘吧,当然还有像手写板、麦克风、摄像头等设备,但截至今日前端貌似没有什么权限,不然安全性就太差了。

React中,事件的绑定大致和原生网页相似,大概也就是命名方式不同this的指向不同这两点区别。

可以参考:

React中绑定事件

  • 直接绑定

    class Button extends React.Component{    render(){        return ()    }}

    WHAT??这不是和原生的一模一样吗?是呀,只是在命名上采用的是React喜爱的驼峰Camel-Case命名法,原生的都是小写。但这种方法多老式。

  • 间接绑定

    class Button extends React.Component{    consoleLog(){        console.log("Hello gotham");    }    render(){        return ()    }}

    将函数拿到外面去,然后在元素的事件上绑定这个函数,绑定的时候使用JSX{}并且一定加上this,表示绑定的是这个组件里的函数。

  • 超级间接绑定

    class Inner extends React.Component{    render(){        return ()    }}class Outer extends React.Component{    consoleLog(){        console.log("Hello gotham");    }    render(){        return (
    ) }}

    哈哈哈,这是什么鬼?就是利用了Reactprops,把函数绑定在一个props上,本例中是clickHandler,然后渲染了新组件,在新组件中,可以使用this.props来调用这个函数。简单来说就是,将函数从父组件通过props传递到了子组件

this的指向

React中,绝大部分的this都指向组件本身。但是,在自定义的函数中,this是没有指向的,所以会有this is undefined的报错,尤其是自定义的函数需要引用函数外组件内的其它资源的时候。

没有绑定this的报错

像下面这样写是会报错的:

我们想要点击Hello gotham按钮调用greeting函数,greeting函数会调用gotham函数打印Hello gotham字样。但是,greeting函数里的this没有指向,所以会出现上面的报错。

class Welcome extends React.Component{    gotham(){        console.log("Hello gotham");    }        greeting(){        this.gotham();    }    render(){        return ()    }}

所以,如果想要在自定义函数中调用同组件其它资源,你有下面3中方法来绑定this

  • constructor中绑定

    class Welcome extends React.Component{    constructor(props){        super(props);        this.greeting = this.greeting.bind(this);    ?这句是绑定    }    gotham(){        console.log("Hello gotham");    }        greeting(){        this.gotham();    }    render(){        return ()    }}
  • 内联式绑定

    class Welcome extends React.Component{    gotham(){        console.log("Hello gotham");    }        greeting(){        this.gotham();    }    render(){                                              ??????这里是绑定        return ()    }}
  • 内联式箭头函数绑定

    class Welcome extends React.Component{    gotham(){        console.log("Hello gotham");    }        greeting(){        this.gotham();    }    render(){                                 ????????????这里是绑定        return ()    }}

关于绑定this还可以参考:

合成事件SyntheticEvent

React中的合成事件可以对应为通常函数中的事件对象event

function gotham(event){    // your codes}

e...这个功能有点多,你可以自己打印出来看看呀,或者看看官方文档:

这里只贴出来关于鼠标和键盘事件:

  • 鼠标事件

    boolean   altKeyboolean   ctrlKeyboolean   shiftKeyboolean   metaKeynumber    buttonnumber    buttonsnumber    clientXnumber    clientYboolean   getModifierState(key)number    pageXnumber    pageYDOMEventTarget   relatedTargetnumber    screenXnumber    screenY

    适用于如下事件:

    onClick onContextMenu onDoubleClick onDrag onDragEnd onDragEnter onDragExit onDragLeave onDragOver onDragStart onDrop onMouseDown onMouseEnter onMouseLeave onMouseMove onMouseOut onMouseOver onMouseUp
  • 键盘事件

    boolean  altKeynumber   charCodeboolean  ctrlKeyboolean  getModifierState(key)string   keynumber   keyCodestring   localenumber   locationboolean  metaKeyboolean  repeatboolean  shiftKeynumber   which

    适用于如下事件:

    onKeyDown onKeyPress onKeyUp

关于事件的小例子

我们的目标

点击加号按钮数字加1,按住shift点击加号,数字加10

React事件例子

实现思路

  • 分割组件。底板、数字、按钮
  • 点击按钮数字变化,所以,将资料存放于数字组件,并且通过数字组件调用按钮
  • 键盘事件的合成事件中,能够监听shift键是否被按下

抛开样式的完整代码

其它的无关紧要,注意Show组件内的increase函数,我们可以看到合成事件e.shiftKey{this.increase.bind(this)}的使用

    
react-event

组件的生命周期Lifecycle

React创造出来组件,同时也给组件配上了生命周期,用来更好的控制组件,这也是React的一大优势。

组建的生命周期可以参考这个:。往下多翻翻~~

这个参考资料也非常棒:

常用生命周期

  • componentDidMount()
  • componentDidUpdate()
  • componentWillUnmount()

不常用且慎用的生命周期

  • shouldComponentUpdate()
  • static getDerivedStateFromProps()
  • getSnapshotBeforeUpdate()
  • static getDerivedStateFromError()
  • componentDidCatch()

消失的生命周期

消失的生命周期不理他。

React Router

官方文档:

github:

React Router就把他看作是一个插件吧,中文名:React路由。作为一个小白,我怎么会对这个技术的深层理论进行研究,我只知道他有一个我觉得很好用的功能:局部更新页面,并且不用刷新加载新页面,快速、用户体验好。

React Router的效果

  • reactRouter例子-1
  • reactRouter例子-2

看他的样子平平无奇,别别别,这多好呀!不用刷新重新加载就能更新局部页面,看上去又很流畅、代码量不多、兼容性React也帮助你完成了,皆大欢喜~

React Router的引入

React Router的官方文档教你使用npm安装,但是像我这样不喜欢往电脑里装杂七杂八东西的人,还可以使用不同的cdn引入,或者进入你选择的cdn的网址,把你要的复制到本地文件里再引用

  • unpkg

    这是一个cdn
    它的官网:
    中文介绍可以看这篇:
    使用unpkg引入React Router请看下面:

  • cdnjs

    这是一个cdn
    它的官网:
    中文介绍:进入官网,搜索你想要的<script>
    使用cdnjs引入React Router请看下面(截止至2019-2-18):

React Router的使用

通过上述的内容,我们能够正确的使用React框架搭建一个网页,使用React Router需要在组件中修改一点内容,并在随后的ReactDOM.render()中添加像下面这样的渲染内容:

所有,只需要上面这些代码就OK了?我书读的真的少。。。。。。

如果只是要实现白菜功能,像是不管内容怎么变化,总有一条导航栏不变的需求,那这么点代码就ok啦,当然,再加上上面使用React写的组件。

实例中到底写了什么?

  • 首先,搭建React框架,引入React、构建组件Component、渲染页面ReactDOM.render
  • 撰写<script type="text/babel">,注意!!!type="text/babel"必须要加
  • 引入window.ReactRouterDOM,

    var {HashRouter,Link,Route} = window.ReactRouterDOM;

    上面ES6写法,等于:

    var HashRouter = window.ReactRouterDOM.HashRouter;var Link = window.ReactRouterDOM.Link;var Route = window.ReactRouterDOM.Router;
  • ReactDOM.render中必须、只能渲染一个元素,所以使用React Router提供的<HashRouter>,然后,<HashRouter>中也必须只能有一个子元素,所以,加上一个<div>十分安全
  • 下面,渲染了一个<Header/>组件,直接渲染,没有杂七杂八的东西,这个就是永恒不变的导航栏。所以,如果你需要页面上的某些元素不变,那就直接在React Router中直接渲染
  • 接下来,渲染需要改变的部分。方法就是使用React Router提供的<Router>来渲染组件。其基本的属性要求一个path来说明在哪个地址下渲染某个组件、一个component来说明在某个地址下渲染哪个组件。exact的意思是必须一丝不差的匹配地址,组件才能被渲染。
  • 一般,我们是单击导航栏中的链接再更新页面内容,所以我们必须将链接和对应的组件联系在一起。方法就是将通常我们会使用的链接标签<a>修改为<Link to="地址">我是一个链接</Link>

总结:将组件中的链接元素用<Link>代替,在ReactDOM.render中将路径和组件关联上

上述内容都是极易写错导致报错的点,多加小心
ReactRouter结构

通过上面的实例,页面会在不同的地址下,更新局部页面。使用<Router>渲染的组件就是会被更新的内容,虽然可能写了很多个<Router>,但是他们都会在相同的地方被渲染,且一个地址只会渲染一个组件。

ReactRouter示意

更多React Router

  • 我们在例子中,总路由使用的是<HashRouter>,应对不同的情况,总路由还可能是<BrowserRouter><MemoryRouter><NativeRouter><StaticRouter>等,具体可以参见、。
  • <Router>的更多属性可以参见、
  • 初学者教程可以参考这个,本文也有很多内容出自:
  • 这篇简书很好:
  • 这两个网站也可以随便看看:
  • 这个问题关于引入window.ReactRouterDOM错误,参考第二个答案:

本文还可能更新的内容

  • React Router嵌套,额并不是像其它的嵌套一样:<Router><Router></Router></Router>。这里嵌套的意思是在变化的局部页面里,又有一部分内容是不变的,仅针对这个局部页面。e。。。。。。

ReactRouter嵌套

  • React表单

转载地址:http://dyvjo.baihongyu.com/

你可能感兴趣的文章
(转)线程安全的CopyOnWriteArrayList介绍
查看>>
对LinqtoExcel的扩展 【数据有限性,逻辑有效性】
查看>>
WPF TreeView HierarchicalDataTemplate
查看>>
32岁老程序员的现状和尴尬,无奈中透露些许悲凉,有选择却更痛苦
查看>>
WPF MeshGeometry3D
查看>>
puppet cron 模块
查看>>
mysql 协议的ResultsetRow包及解析
查看>>
Ymal格式转Properties格式
查看>>
一个生成全局唯一Sequence ID的高并发工厂类 (Java)
查看>>
调优之系统篇--cpu,内存
查看>>
解决jQuery和其它库的冲突
查看>>
写在除夕夜
查看>>
JAVA中的list去重复
查看>>
JAVA 代码里中文乱码问题
查看>>
Grub的安装方法
查看>>
SpringMVC通过注解方式读取properties文件中的值
查看>>
Spring+Dubbo+Zookeeper简单框架与使用
查看>>
Open Cascade DataExchange DXF
查看>>
Greenplum Hadoop分布式平台大数据解决方案实战教程
查看>>
编译安装LAMP之配置httpd以FastCGI方式与php整合
查看>>