react classname多个_React全家桶简介

当前前端开发已经进入以vue、react、webpack为代表的编程2.0时代。在1.0时代,代码是写给机器的;在2.0时代,代码是写给工具的,然后由工具处理后再转给机器。

一、React全家桶简介

JSX语法糖

使用React,不一定非要使用JSX语法,可以使用原生的JS进行开发。但是React作者强烈建议我们使用JSX,因为JSX在定义类似HTML这种树形结构时,十分的简单明了。这里简单的讲下JSX的由来。

比如,下面一个div元素,我们用HTML语法描述为:

<div class="test">
  <span>Testspan>div>

如果换做使用javascript描述这个元素呢:

{
  type:"div",
  props:{
    className:"test",
    children:{
      type:"span",
      props:{
        children:"Test"
      }
    }
  }
}

这样我们就可以在javascript中创建一个Virtual DOM(虚拟DOM)了。当然,这样是没法复用的,我们再把它封装一下:

const Div=>({text}){

  return {

    type:"div",

    props:{

      className:"test",

      children:{

        type:"span",

        props:{

          children: text,

        },

      },

    },

  }

}

接下来再实现这个div就可以直接调用Div('Test')来创建。但上述结构看起来实在让人不爽,写起来也很容易写混,一旦结构复杂了,很容易让人找不着北,于是JSX语法应运而生。我们用写HTML的方式写这段代码,再经过翻译器转换成javascript后交给浏览器执行。

上述代码用JSX重写:

const Div =()=>(
<div className="test">  <span>Testspan> div>);


所谓语法糖,就是借助工具将复杂工作由人工转为机器完成。小程序中的WXS,也可以看作是一种语法糖,但是一种尚未成熟的语法糖。ES6的箭头函数在JS中也是语法糖,Bable可以将它自动转化为同等的ES5语法。

Virtual DOM

虚拟DOM的概念并不是FB首创却在FB的手上大火了起来。

在Html中对DOM进行更新操作十分昂贵,为减少对于真实DOM的操作,诞生了Virtual DOM的概念,也就是用javascript把真实的DOM树描述了一遍,使用的也就是我们刚刚说过的JSX语法。对比如下:

65835fb63bf811ba3a15aa840599a1b8.png

每次数据更新之后,重新计算Virtual DOM,并和上一次的Virtual DOM对比,对发生的变化进行批量更新。(注:React也提供了shouldComponentUpdate生命周期回调,来减少数据变化后不必要的Virtual DOM对比过程。)

Virtual DOM虽然渲染比传统的DOM操作要好一些,但对比DOM节点也是需要计算的,最大的好处在于可以很方便的和其它平台集成,比如react-native就是基于Virtual DOM渲染出原生控件。具体渲染出的是Web DOM还是Android控件或是iOS控件就由平台决定了。

React-router

应用程序的路由。它通过管理 URL,实现组件的切换和状态的变化。对应于vue-router。

安装

npm install -S react-router

使用,可以将路由器Router看作React的一个组件

import { Router } from 'react-router';render(<Router/>, document.getElementById('app'));

Router组件本身只是一个容器,真正的路由要通过Route组件定义。使用JXS语法。

import { Router, Route, hashHistory } from 'react-router';render((
  <Router history={hashHistory}>
    <Route path="/" component={App}/>
  </Router>), document.getElementById('app'));

上面代码中,用户访问根路由/(比如http://www.example.com/),组件APP就会加载到document.getElementById('app')。

Redux

从角色功能上讲,相当于vuex。主要包括三个主要概念:State、action、reducer。

Redux 和 React 之间没有关系。Redux 支持 React、Angular、Ember、jQuery 甚至纯 JavaScript。

Redux 默认并不包含 React 绑定库,可能需要单独安装。

npm install --save react-redux

随着 JavaScript 单页应用开发日趋复杂,JavaScript 需要管理比任何时候都要多的 state (状态)。 这些 state 可能包括服务器响应、缓存数据、本地生成尚未持久化到服务器的数据,也包括 UI 状态,如激活的路由,被选中的标签,是否显示加载动效或者分页器等等。如果一个 model 的变化会引起另一个 model 变化,那么当 view 变化时,就可能引起对应 model 以及另一个 model 的变化。Redux就是为了解决这个复杂场景而设计的。

可以把React的model看作是一个个的子民,每一个子民都有自己的一个状态,所有model统一由Redux统一管理。

组件分两种,容器组件和展示组件。

bde11f0c2a74ed52f829b53d4bea21e2.png

Store

Store 是Redux中的主要概念,是保存数据的地方,它实际上是一个Object tree。整个应用只能有一个 Store。

Store主要职责:

  • 维持应用的 state;

  • 提供 getState() 方法获取 state;

  • 提供 dispatch(action) 方法更新 state;

  • 通过 subscribe(listener) 注册监听器;

  • 通过 subscribe(listener) 返回的函数注销监听器。

action

State 的变化,会导致 View 的变化。Action 就是 View 发出的通知,表示 State 应该要发生变化了。即store的数据变化来自于用户操作。一般来说,View会通过 store.dispatch() 将 action 传到 store。

Action 是一个对象。其中的type属性是必须的,表示 Action 的名称

const action = {   type: 'ADD_TODO',   payload: 'Learn Redux'};
reducer

Action 只是描述了有事情发生了这一事实,并没有指明应用如何更新 state。而这正是 reducer 要做的事情。

Store 收到 Action 以后,必须给出一个新的 State,这样 View 才会发生变化。这种 State 的计算过程就叫做 Reducer。Reducer 是一个函数,它接受 Action 和当前 State 作为参数,返回一个新的 State。

const reducer = function (state, action) {  
 // ...  return new_state; };

单向数据流

与vue一样,react的数据流动也是单向的。

Redux 应用中数据的生命周期遵循下面 4 个步骤:

  • 调用 store.dispatch(action)。

  • Redux store 调用传入的 reducer 函数。

  • 根 reducer 应该把多个子 reducer 输出合并成一个单一的 state 树。

  • Redux store 保存了根 reducer 返回的完整 state 树。

3106f950248d3ff2626f0f8dd89e1cc5.png
Connect

React-Redux 提供connect方法,用于从 UI 组件生成容器组件。connect的意思,就是将这两种组件连起来。

import { connect } from 'react-redux';
const TodoList = connect()(Memos);

上面代码中Memos是个UI组件,TodoList就是由 React-Redux 通过connect方法自动生成的容器组件。完整的connect方法这样使用:

import { connect } from 'react-redux'const TodoList = connect(
  mapStateToProps
)(Memos)

上面代码中,connect方法接受两个参数:mapStateToProps和mapDispatchToProps。它们定义了 UI 组件的业务逻辑。前者负责输入逻辑,即将state映射到 UI 组件的参数(props),后者负责输出逻辑,即将用户对 UI 组件的操作映射成 Action。

Provider

这个Provider 其实是一个中间件,它是为了解决让容器组件拿到state对象而存在的。

import { Provider } from 'react-redux'import { createStore } from 'redux'import todoApp from './reducers'import App from './components/App'let store = createStore(todoApp);
render(  
<Provider store={store}>    <App /> Provider>,  
document.getElementById('root') )

上面代码中,Provider在根组件外面包了一层,这样一来,App的所有子组件就默认都可以拿到state了。

这个设计非常符合在React中“一切皆组件”的设计思想。

react-router

安装

npm install --save react-router-dom

React UI库

知名的库有:Ant Design,Material UI

二、React使用简介

获取原始DOM节点

组件并不是真实的 DOM 节点,而是存在于内存之中的一种数据结构,叫做虚拟 DOM (virtual DOM)。只有当它插入文档以后,才会变成真实的 DOM 。根据 React 的设计,所有的 DOM 变动,都先在虚拟 DOM 上发生,然后再将实际发生变动的部分,反映在真实 DOM上,这种算法叫做 DOM diff ,它可以极大提高网页的性能表现。

但是,有时需要从组件获取真实 DOM 的节点,这时就要用到 ref 属性

var MyComponent = React.createClass({

handleClick: function() {

    this.refs.myTextInput.focus();

},

render: function() {

    return (

    );

}

});

上面代码中,组件 MyComponent 的子节点有一个文本输入框,用于获取用户的输入。这时就必须获取真实的 DOM 节点,虚拟 DOM 是拿不到用户输入的。为了做到这一点,文本输入框必须有一个 ref 属性,然后this.refs.[refName]就会返回这个真实的 DOM 节点。

需要注意的是,由于this.refs.[refName]属性获取的是真实 DOM ,所以必须等到虚拟 DOM 插入文档以后,才能使用这个属性,否则会报错。上面代码中,通过为组件指定 Click 事件的回调函数,确保了只有等到真实 DOM 发生 Click 事件之后,才会读取this.refs.[refName]属性。

this.state

组件免不了要与用户互动,React 的一大创新,就是将组件看成是一个状态机,一开始有一个初始状态,然后用户互动,导致状态变化,从而触发重新渲染 UI。

var LikeButton = React.createClass({

getInitialState: function() {

    return {liked: false};

},

handleClick: function(event) {

    this.setState({liked: !this.state.liked});

},

render: function() {

    var text = this.state.liked ? 'like' : 'haven\'t liked';

    return (

            You {text} this. Click to toggle.

    );

}

});

ReactDOM.render(

    ,

    document.getElementById('example')

);

上面代码是一个 LikeButton 组件,它的 getInitialState 方法用于定义初始状态,也就是一个对象,这个对象可以通过 this.state 属性读取。当用户点击组件,导致状态变化,this.setState 方法就修改状态值,每次修改以后,自动调用 this.render 方法,再次渲染组件。

由于 this.props 和 this.state 都用于描述组件的特性,这两个概念可能会产生混淆。一个简单的区分方法是,this.props 表示那些一旦定义,就不再改变的特性,而 this.state 是会随着用户互动而产生变化的特性。

关于表单的值

用户在表单填入的内容,属于用户跟组件的互动,所以不能用 this.props 读取。

var Input = React.createClass({

getInitialState: function() {

    return {value: 'Hello!'};

},

handleChange: function(event) {

    this.setState({value: event.target.value});

},

render: function () {

    var value = this.state.value;

    return (

          value} onChange={this.handleChange} />

{value}

    );

}

});

ReactDOM.render(, document.body);

上面代码中,文本输入框的值,不能用 this.props.value 读取,而要定义一个 onChange 事件的回调函数,通过 event.target.value 读取用户输入的值。

关于组件的生命周期

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

  • Mounting:已插入真实 DOM

  • Updating:正在被重新渲染

  • Unmounting:已移出真实 DOM

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

  • componentWillMount()

  • componentDidMount()

  • componentWillUpdate(object nextProps, object nextState)

  • componentDidUpdate(object prevProps, object prevState)

  • componentWillUnmount()

这五个函数的全名与OC类库的命名风格颇为类似。

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

  • componentWillReceiveProps(object nextProps):已加载组件收到新的参数时调用

  • shouldComponentUpdate(object nextProps, object nextState):组件判断是否重新渲染时调用

Ajax

组件的数据来源,通常是通过 Ajax 请求从服务器获取,可以使用 componentDidMount 方法设置 Ajax 请求,等到请求成功,再用 this.setState 方法重新渲染 UI。

componentDidMount: function() {

    $.get(this.props.source, function(result) {

    var lastGist = result[0];

    if (this.isMounted()) {

        this.setState({

        username: lastGist.owner.login,

        lastGistUrl: lastGist.html_url

        });

    }

    }.bind(this));

},

上面代码使用 jQuery 完成 Ajax 请求,这是为了便于说明。React 本身没有任何依赖,完全可以不用jQuery,而使用其他库。

等等。


参考资料:

  1. https://juejin.im/post/587b52d8570c352201fd993d

  2. http://www.ruanyifeng.com/blog/2016/05/react_router.html

  3. https://blog.csdn.net/stwuyiyu/article/details/86140697

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值