React總結和遇到的坑

1、react項目javascript

前端react後端node:https://github.com/GainLoss/react-juejincss

前端react後端Pyton:https://github.com/GainLoss/python-reacthtml

 

2、react理解前端

1.react優勢vue

組件、單向數據、虛擬DOM、生態系統、JSXhtml5

組件:一個組件就像一個接受道具做爲輸入並輸出聲明的函數接口。 UI應該由儘量多的組件組成能夠最大限度地提升可重用性。java

單項數據:React使用單向數據流,所以只會更改數據結果更改UI。若是您使用Redux,則能夠在全局應用程序中更改數據存儲,組件監聽那裏的變化。node

  具體流程:(1)操做經過將數據傳輸到Dispatcher來啓動數據流。(2)Dispatcher接收操做並將數據傳遞到全部store。(3)store包含應用程序的狀態,並在收到相關操做後對其進行更新(4)視圖從store接收數據並從新呈現組件python

虛擬DOM:虛擬DOM容許UI在UI變化中具備高效性。這個組件應呈現的內部和之間的過程實際渲染是什麼,它容許React在不一樣的工做平臺。react

生態系統:react有豐富的生態,有不少插件能夠供開發者使用。

 2.react和vue的對比

相同之處:(1)使用虛擬DOM (2)組件化 

不一樣之處:(1)react若是狀態變化,是從根節點開始從新渲染;vue是肯定到某一個節點須要變化,只是更新這個節點;(2)react是用jsx渲染模板;vue使用的是Template模板渲染,仍是Html模板;

選取:react生態比較好,插件多;vue學習難度低;

 

3、在建立項目的時候,各類坑和總結

關於react-router的坑和總結:

1.react-router如今版本是4,因此若是將嵌套的路由都放一塊的話,就會出錯:

報這種錯誤Warning: You should not use <Route component> and <Route children> in the same route; 

因此將須要嵌套的路由放到你的組件中

2.在頁面有導航的時候,咱們須要實現點擊導航跳轉頁面的功能,這時候咱們須要在導航的render中這樣寫:

咱們用Link: <li key={index}><Link to="/+{item.name}">{item.name}</Link></li>       並且咱們須要引入一個import { Link } from 'react-router-dom'

3.咱們想要獲取當前頁面的路由或者說是瀏覽器中地址欄的地址:

在當前組件中props裏面有當前的地址,找一個恰當的生命週期鉤子而後再這個函數中this.props裏面就能夠獲取到,或者能夠直接在render中return中元素裏的{}裏面直接獲取

4.react-router路由有兩種形式:

HashRouter這種的帶hash # 

BrowerBouter這種是利用html5中history的,這種是須要服務器端支持的,兼容性不是很好

6.有時候須要實現,根據當前地址實現對應導航顯示:

在當前組件中獲取this.props,而後將這個值賦給this.state,在須要當前組件中渲染導航組件的位置,在導航組件中寫<Nav urlLocation={this.state.url}/>,最後在導航組件中獲取到this.props裏面包含的就是當前路由地址

7.有時候咱們須要實現點擊排序,給當前路由添加參數:我用的是Link這種方法

組件裏面:

<div style={homeMainLeftTwodiv2}>
      {
           this.state.HomeMenutwo.map((item,index)=>
               <span key={index} className={this.query===item.sort?"homesortactive":''}>
                  <Link to={{pathname:"/home",search: 'sort='+item.sort,}}>{item.name}</Link>
                  <Route path="/home/:id" component={Home}/>
               </span>
            )
     } 
</div>

在router路由中:仍是和以前同樣的

8.想只是改變地址欄的地址而不是調轉頁面,就好比我當前頁面有兩個選擇,點擊選擇,改變地址欄地址,可是仍是當前的組件

import createHashHistory from 'history/createHashHistory'
const history = createHashHistory()

//點擊一級菜單事件
    clickTop(event) {
        let that = this;
        let tab = event.currentTarget.dataset.tab;
        that.setState({ menuOne: tab })
        console.log(that.setState)
        history.push({
            pathname: '/home/'+tab,
        })
    }

{
this.state.HomeMenuTop.map((item, index) =>
        <span key={index} className={this.state.menuOne === item.tab ? "homesortactive" : ""} data-tab={item.tab} onClick={this.clickTop}>
             {item.name}{this.state.menuOne}
        </span>
   )
}

 9.react-router2遷移到react-router4的特性:https://github.com/gmfe/Think/issues/6

 10.在npm start以後頁面出現這種錯誤Uncaught TypeError: Super expression must either be null or a function, not undefined

  緣由是:在編寫組件的時候React.Component寫錯了

 11.在react中使用事件:

  若是沒有用bind的話那麼點擊事件只在頁面一開始的時候執行,不會在元素點擊的時候執行,只有用this.click.bind(this)就能夠,在點擊元素的時候也執行這個函數

class FLeft extends React.Component{
    constructor(props){
        super(props)
        this.state={
            currentIndex:0,
        }

    }
    clickTab(index,e){       
        this.setState({currentIndex:index});
    }
    render(){
        var styles={
            width:'100%',
            height:'300px'
        }
        var index=this.state.currentIndex;
        return (
            <div className="f_left">
                <textarea className="f_left_text"></textarea>
                <div className='f_left_text_choose'>
                    <span>圖片</span>
                    <span>連接</span>
                    <span>話題</span>
                    <button>發佈</button>
                </div>
                <div className='choose_tab'>
                    <span onClick={this.clickTab.bind(this,0)} className={this.state.currentIndex===0?'active':''}>推薦</span>
                    <span onClick={this.clickTab.bind(this,1)} className={this.state.currentIndex===1?'active':''}>動態</span>
                </div>
            </div>
        )
    }
}

 12.在react中使用iconfont (Unicode編碼)

 通常使用的時候直接用<i className="iconfont">編碼</i>這樣就能夠了,可是當你循環出來i標籤的時候,那麼iconfont使用的是字符串表示unicode編碼,那麼咱們須要改寫一下編碼

  想使用字符串來傳遞的話,只要將 "&#xe655;" 改成 「\ue655」 便可。

13.在react中循環中設置點擊事件

這個裏面只有把點擊事件設置成異步的纔不會循環出所有的元素的點擊事件

1 <HomeHeader>
2       {
3                             this.props.homeheader.map((item)=>{
4                                 var id=item.id;
5                                 return <HomeHeaderItem onClick={()=>this.props.clickChangeList(id)} key={item.id}><Link to={{pathname:'/home/'+id}}>{item.val}</Link></HomeHeaderItem>
6                             })
7         }
8 </HomeHeader>

 14.配置文件的路徑:

有時候在一個組件中要引入一個新的組件,可能路徑須要寫不少的../,如今咱們須要設置一個單詞表示父級文件夾

背景:"react": "^16.5.2","react-dom": "^16.5.2","react-scripts": "2.0.4"

打開node_modules中的react-script中webpack.config.dev.js這個文件(是開發環境配置),裏面的

resolve:{  
    alias: {
        'react-native': 'react-native-web',
        '@': paths.appSrc //對應的是相同文件夾下面的paths.js文件夾裏面
    },
}     

設置完成以後,在組件中引入import Header from '@/common/header/header.js'

關於在react中引入css或者引入外部文件:

1.在react中怎麼引入css文件呢:

這樣引入css文件:import './style/nav.css'   須要注意的是:webpack.config.js文件中針對css文件引入的包須要loader必須寫全,不能簡寫
{
                test:/\.css$/,
                exclude: /node_modules/,
                loader: "style-loader!css-loader"
}

2.html元素中添加css樣式的時候:

兩種:一種是class名字填寫,可是在jsx中class須要寫成className; 二種是在行間寫樣式style={{}}裏面放置樣式 ;三種是style={colorstyle}裏面放置一個變量

關於react中元素渲染和數據交互的總結:

1.在組件中循環某些元素的時候;
須要在每一個組件中加一個key值,
this.state.HomeMenuone.map((item,index)=>
      <span key={index}>{item.name}</span>
)

若是不加的話,會出這種錯誤

2.在react中引入圖片的話,固然以前的直接放在src中也是能夠的,可是比較好的方法是:

import img from './right.png'
<img src={img}/>

這種方法有可能會出現這種錯誤:出現Uncaught Error: Module parse failed: Unexpected character '�' (1:0),這種個人解決辦法是從新npm install就能夠了

3.在先後臺交互的時候我用的是fetch實現的:

注意的是在fetch成功調取以後將結構賦給一個數組的時候,在then中須要用這個才能設置好this.setState({result:data}),而後map這個result

4.使用fetch獲取後臺數據:

fetch("/list/show").then((response)=>{
            if(response&&response.status===200){
                return response.json();
            }
}).then((data)=>{
            this.setState({result:data})
});

 5.上面的是直接獲取後臺的數據,可是有時候咱們須要用fetch給後臺傳參數(後臺用的是express):

咱們若是用get就是和上面是同樣的,可是若是咱們用post是有區別的和以前的寫法,有兩種寫法:

一種:

if(this.props.location.search){
            let idValue=this.props.location.search.split('=')[1];
            fetch('/list/detail',{method:'POST',headers: {
                'Content-Type': 'application/x-www-form-urlencoded'
            },body: `id=${idValue}`}).then((response)=>{
                return response.json()
            }).then((result)=>{
                this.setState({result:result})
            })
}

二種:

if(this.props.location.search){
            let idValue=this.props.location.search.split('=')[1];
            let formData = new FormData();  
            formData.append("id",123); 
            fetch('/list/detail',{method:'POST',body:
formData}).then((response)=>{
                return response.json()
            }).then((result)=>{
                this.setState({result:result})
            })
}

上面這兩種均可以;

另外後臺由於用的是express,因此你須要在dev-server.js中添加一個body-parser這個模塊是爲了解析客戶端請求的body的內容,內部使用JSON編碼,url編碼處理以及對文件的上傳處理。

關於react中事件處理的總結:

1.當咱們想點擊元素,相應的改變state的時候,能夠這樣:

//constructor
 this.clickMenu=this.clickMenu.bind(this)
//點擊事件
    clickMenu(event){
        var that=this;
        let sort=event.currentTarget.dataset.sort;
        that.setState({query:sort})
        
    }
// render中
<div style={homeMainLeftTwodiv1}>
{
      this.state.HomeMenuone.map((item,index)=>
          <span key={index} className={this.state.query===item.sort?"homesortactive":'' } data-sort={item.sort}  onClick={this.clickMenu}>
             <Link to={ {pathname:"/home",  search: 'sort='+item.sort,} } >{item.name}</Link>                              
             <Route path="/home/:id" component={Home}/>
          </span>
      )
}
</div>
相關文章
相關標籤/搜索