React学习笔记

参考网站:http://jspang.com/2017/08/15/react_basic/

1、React起源于Facebook的内部项目

      ReactJS官方地址:https://facebook.github.io/react/

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

react特点:

      虚拟DOM:React是以数据驱动的,每次数据变化React都会扫码整个虚拟DOM树,自动计算与上次虚拟DOM的差异变化,然后针对需要变化的部分进行实际的浏览器DOM更新

      组件化:React可以从功能角度横向划分,将UI分解成不同组件,各组件都独立封装,整个UI是由一个个小组件构成的一个大组件,每个组件只关系自身的逻辑,彼此独立

     单向数据流:Reac设计者认为数据双向绑定虽然便捷,但在复杂场景下副作用也是很明显,所以React更倾向于单向的数据流动--从父节点传递到子节点。(使用ReactLink也可以实现双向绑定,但不建议使用)

2、react.js和react-dom.js文件

     react.js:实现React核心逻辑,且与具体的渲染引擎无关,从而可以跨平台共用。如果应用要迁移到React Native,这一部分逻辑是不需要改变的。

     react-dom.js:包含了具体的DOM渲染更新逻辑,以及服务端渲染的逻辑,这部分就是与浏览器相关的部分

3、React.createElement( string/ReactClass type,[object props], [children ...])   返回一个给定类型的ReactElement元素

     type:必须,可以是html标签名称字符串,也是可以是ReactClass

     [object props]:可选,该标签的属性,一般为null

     [children ...]:可选,该元素的子节点   

     链接:http://www.onmpw.com/tm/xwzj/web_103.html

 4、JSX的好处:

      可以使用熟悉的语法仿照HTML来定义虚拟DOM

      与javaScript之间等价交换,代码更加直观

5、getInitialState函数是用来设置state里面值的默认值的

     必须有返回值return

1 getInitialState: function () {
2    return {enable: false}
3 }

     getDefaultProps函数是用来设置state里面值的默认值的

 6、props与state的区别

      props不能被其所在的组件修改,从父组件传递进来的属性不会在组件内部更改;state只能在所在组件内部更改,或在外部调用setState函数对状态进行间接修改。

 7、render成员函数

      首先说render是一个函数,它对于组件来说,render成员函数是必需的。render函数的主要流程是检测this.props和this.state,再返回一个单一组件实例。

      render函数应该是纯粹的,也就是说,在render函数内不应该修改组件state,不读写DOM信息,也不与浏览器交互。如果需要交互,应该在生命周期中进行交互。

8、react的表单--bind复用

     bind方法为事件相应函数增加一个参数,事件响应函数通过该参数识别事件源

     bind可以点击这里:http://www.cnblogs.com/zhaobao1830/p/8016638.html 

    

 1 <!DOCTYPE html>
 2 <html lang="zh">
 3 <head>
 4   <meta charset="UTF-8">
 5   <meta http-equiv="x-ua-compatible" content="ie=edge">
 6   <title>表单--bind复用</title>
 7   <meta name="viewport" content="width=device-width, initial-scale=1,minimum-scale=1,maximum-sacle=1,user-scalable=no">
 8   <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
 9   <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
10   <script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
11 </head>
12 <body>
13   <div id="demo"></div>
14   <script type="text/babel">
15     var MyForm = React.createClass({
16       getInitialState: function() {
17         return{
18           username: '',
19           gender: 'man',
20           checked: true
21         }
22       },
23       handleChange: function (name, event) {
24         var newState = {}
25         newState[name] = name === 'checked' ? event.target.checked : event.target.value
26         this.setState(newState)
27         console.log(newState)
28       },
29       handleSubmit: function (e) {
30         e.preventDefault()
31         var is = this.state.checked ? '' : '不是'
32         var gender = this.state.gender === 'man' ? '帅哥' : '美女'
33         alert(this.state.username+ is + gender +'.' );
34       },
35       render: function () {
36         return (
37             <form onSubmit={this.handleSubmit}>
38               <label htmlFor="username">请输入您的名字:</label>
39               <input type="text" name="username" id="username" onChange={this.handleChange.bind(this, "username")} value={this.state.username}/>
40               <br/>
41               <label htmlFor="checkBox">是或否:</label>
42               <input type="checkbox" value="是否" name="checked" id="checkBox" onChange={this.handleChange.bind(this, "checked")} checked={this.state.checked}/>
43               <br/>
44               <label htmlFor="username">请选择</label>
45               <select name="gender" onChange={this.handleChange.bind(this, "gender")} value={this.state.gender}>
46                 <option value="man">帅哥</option>
47                 <option value="woman">美女</option>
48               </select>
49               <br/>
50               <button type="submit">提交</button>
51             </form>
52         )
53       }
54     })
55     ReactDOM.render(
56       <MyForm/>,
57       document.getElementById("demo")
58     )
59   </script>
60 </body>
61 </html>

这个里面的bind,this是绑定到当前环境下,第二个参数是预设一个参数,对应的是handleChange()里的name参数

9、react表单--name复用

   name复用方式直接读取表单的属性值,比bind写法少一个参数(React中事件响应函数会自动绑定this)。其原理是在所有的标签中设置统一的name属性,并将这个属性值对应为state属性,在事件响应函数中通过读取表单的name值获得state属性,从event.target.value获取用户输入的值(check控件稍有不同),要求所有相关的标签(包括input标签)都要统一设置name属性。

就是每个标签加一个name,然后判断name来进行state的更改。但是我不建议这样使用,因为为每个标签增加一个name属性值并不友好。

 1 <!DOCTYPE html>
 2 <html lang="zh">
 3 <head>
 4   <meta charset="UTF-8">
 5   <meta http-equiv="x-ua-compatible" content="ie=edge">
 6   <title>表单--name复用</title>
 7   <meta name="viewport" content="width=device-width, initial-scale=1,minimum-scale=1,maximum-sacle=1,user-scalable=no">
 8   <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
 9   <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
10   <script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
11 </head>
12 <body>
13   <div id="demo"></div>
14   <script type="text/babel">
15     var MyForm = React.createClass({
16       getInitialState: function() {
17         return{
18           username: '',
19           gender: 'man',
20           checked: true
21         }
22       },
23       handleChange: function (event) {
24         var newState = {}
25         newState[event.target.name] = event.target.name === 'checked' ? event.target.checked : event.target.value
26         this.setState(newState)
27         console.log(newState)
28       },
29       handleSubmit: function (e) {
30         e.preventDefault()
31         var is = this.state.checked ? '' : '不是'
32         var gender = this.state.gender === 'man' ? '帅哥' : '美女'
33         alert(this.state.username+ is + gender +'.' );
34       },
35       render: function () {
36         return (
37             <form onSubmit={this.handleSubmit}>
38               <label htmlFor="username">请输入您的名字:</label>
39               <input type="text" name="username" id="username" onChange={this.handleChange} value={this.state.username}/>
40               <br/>
41               <label htmlFor="checkBox">是或否:</label>
42               <input type="checkbox" value="是否" name="checked" id="checkBox" onChange={this.handleChange} checked={this.state.checked}/>
43               <br/>
44               <label htmlFor="username">请选择</label>
45               <select name="gender" onChange={this.handleChange} value={this.state.gender}>
46                 <option value="man">帅哥</option>
47                 <option value="woman">美女</option>
48               </select>
49               <br/>
50               <button type="submit">提交</button>
51             </form>
52         )
53       }
54     })
55     ReactDOM.render(
56       <MyForm/>,
57       document.getElementById("demo")
58     )
59   </script>
60 </body>
61 </html>

 10、在react里面,input标签有点特殊

        将Input中的value绑定到state的React组件是可控组件,反之则是不可控组件

        在render()函数中设置了value的<Input>是一个功能受限的组件,渲染出来的HTML元素始终保存value属性的值,即使用户输入也不会改变     

1 var  MyForm = React.createClass({
2     render:function(){
3         return(
4             <div>
5             <input type="text" value="zb" />
6             </div>
7         )
8     }
9 });

      这时打开浏览器,value值无法改变,也无法删除,这时由React的渲染策略决定的

11、可控组件

      

 1 <!DOCTYPE html>
 2 <html lang="zh">
 3 <head>
 4   <meta charset="UTF-8">
 5   <meta http-equiv="x-ua-compatible" content="ie=edge">
 6   <title>Title</title>
 7   <script src="https://cdn.bootcss.com/react/15.4.2/react.min.js"></script>
 8   <script src="https://cdn.bootcss.com/react/15.4.2/react-dom.min.js"></script>
 9   <script src="https://cdn.bootcss.com/babel-standalone/6.22.1/babel.min.js"></script>
10 </head>
11 <body>
12    <div id="demo"></div>
13    <script type="text/babel">
14      var MyForm = React.createClass({
15        getInitialState: function () {
16          return {value: 'zb'}
17        },
18        handleChange: function (event) {
19          this.setState({value: event.target.value})
20        },
21        render: function () {
22          return (
23            <div>
24              <input type="text" value={this.state.value} onChange={this.handleChange}/>
25            </div>
26          )
27        }
28      });
29      ReactDOM.render(
30        <MyForm/>,
31        document.getElementById('demo')
32      )
33    </script>
34 </body>
35 </html>

 在条件允许的情况下,我们应该优先考虑编写可控组件

 可控组件的特点:

   1、符合React单向数据流特性,即从state流向render输出的结果

   2、数据存储在state中,便于访问和处理

12、快速构建react开发环境的脚手架工具:create-react-app

       地址:https://github.com/facebookincubator/create-react-app

       create-react-app优点:

          无需配置:官方的配置堪称完美,几乎不用你再配置任何东西,就可以上手开发项目

          高集成性:集成了对React、JSX、ES6和Flow的支持

          自带服务:集成了开发服务器,你可以实现开发预览一体化

          热更新:保存自动更新

          全兼容性:自动处理css的兼容问题,无需添加-webkit前缀

          自动发布:集成好了发布成品功能,编译后直接发布,并且包含了sourcemaps功能 

13、构建工具:generator-react-webpack

        参考地址:http://jspang.com/2017/10/22/react-all-01/

       它是需要yeoman的支持的

       优点:

              基于webpack构建,可以很容易的配置自己需要的webpack

              支持ES6,集成了Bable-Loader

              支持不同风格的CSS(sass,less,stylue)

              支持PostCSS转换样式

              集成了esLint功能

             可以轻松配置单元测试,比如Karma和Mocha

14、React路由需要用到俩个模块:Router(路由器)和Route(路由)

       exact是精确匹配的意思

       React会匹配所有能匹配的路由组阶,exact可以使我们的匹配更精确。exact的值为bool型,为true是表示严格匹配,为false时为正常匹配

1  <Route  path="/" component={Jspang} />
2  <Route  path="/Jspangb" component={Jspangb} />
3  //这种情况下,输入路由"/Jspangb",会把Jspang组件也展示出来
4 
5 //所以我们经常使用exact来解决这个问题。
6 <Route  exact  path="/"  component={Jspang} />
7 <Route  path="/Jspangb" component={Jspangb} />

         作为一个链接是用激活状态的,激活状态就是当我们处在这个链接时。activeClassName就是设置激活状态的样式,它接受一个类名

1 .active{
2   color: red
3 }
4 <NavLink to='/Jspangc' activeClassName='active'>Jspangc</NavLink>

15、404页面,需要用到Switch组件

       地址:http://jspang.com/2017/10/22/react-all-01/#03webpack01       

       Redirect组件使用 

       有时候我们开发中希望在程序中根据业务逻辑进行跳转,或者一个链接点击后直接跳转到其它链接。这时候可以使用Redirect组件解决。

 16、路由:Router中属性和路由模式 

        basename属性

        basename的作用是个我们增加一级导航目录,比如以前的导航目录是:http://localhost:1717/Jspangb  现在想访问同一个页面,但是路径变成http://localhost:1717/demo/Jspangb。这时候就可以使用basename属性来设置。basename属性是放在<router>标签里边的。     

 1  <Router basename="demo">
 2         <div>
 3          <Nav/>
 4             <Switch>
 5                 <Route  exact  path="/"  component={Jspang} />
 6                 <Route  path="/Jspangb" component={Jspangb} />
 7                 <Route  path="/Jspangc/:param" component={Jspangc} />
 8                 <Redirect from="/redirect" to="/Jspangb" />
 9                 <Route  component={Error} />
10             </Switch>
11             
12         </div>
13     </Router>,

          forceRefresh属性

         这个属性的作用是开启或者关闭React Router,也就是说如果你把forceRefresh的值设置成真,它将关闭React路由系统,而真实的去服务器端请求信息。

         现在我们把forceRefresh设置成true,你会发现路由已经不能使用了。          

 1 <Router basename="demo" forceRefresh={true}>
 2     <div>
 3         <Nav/>
 4         <Switch>
 5             <Route  exact  path="/"  component={Jspang} />
 6             <Route  path="/Jspangb" component={Jspangb} />
 7             <Route  path="/Jspangc/:param" component={Jspangc} />
 8             <Redirect from="/redirect" to="/Jspangb" />
 9             <Route  component={Error} />
10         </Switch>
11         
12     </div>
13 </Router>,

           这个操作经常使用在大型项目,在服务器跳转和ReactRouter切换时使用。比如作一个APP活动页面,第一次请求时我们到服务器端请求整个页面,然后请求后,整个页面DOM进行本地缓存,生成React Router实现本地单页应用。 只要设置我们的forceRefresh就可以了。   

       5种路由方式

        我们一直在使用的路由方式是BrowserRouter,也就是浏览器的路由方式,其实React还有几种路由方式:          

  1. BrowserRouter:浏览器的路由方式,也是我们一直在学习的路由方式,在开发中最常使用。
  2. HashRouter:在路径前加入#号成为一个哈希值。Hash模式的好处是,再也不会因为我们刷新而找不到我们的对应路径了。
  3. MemoryRouter:不存储history,所有路由过程保存在内存里,不能进行前进后退,因为地址栏没有发生任何变化。
  4. NativeRouter:经常配合ReactNative使用,多用于移动端,以后ReactNative课程中会详细讲解。
  5. StaticRouter:设置静态路由,需要和后台服务器配合设置,比如设置服务端渲染时使用。

17、prompt用法讲解

       地址: http://jspang.com/2017/10/22/react-all-01/#10prompt

       动态该改变when的状态那,这里做一个小实例:写一个按钮,然后设置一个power状态,通过点击按钮改变状态,来控制<Prompt>标签的启用和关闭

        

 1 import React from 'react';
 2 import {Prompt} from 'react-router-dom';
 3 export default class jspangb extends React.Component{
 4  
 5  
 6     constructor(props){
 7         super(props);
 8         this.state={
 9             power:false
10         }
11         this.changePower=this.changePower.bind(this);  //备注:这个是为了给changePower绑定作用域,如果没有这个的话,方法里的this找不到
12     }
13     changePower(){
14         alert('已经开启');
15         this.setState({
16             power:true
17         })
18     }
19  
20     render(){
21         return(
22             <div>
23                 <p> B页面</p>
24                 <Prompt message="残忍离开?" when={this.state.power}/>
25                 <button onClick={this.changePower}>启用</button>
26             </div>
27         )
28     }
29 }
原文地址:https://www.cnblogs.com/zhaobao1830/p/7998185.html