React實戰之React+Redux實現一個天氣預報小項目

引言

經過一段時間的React學習,React和Vue的開發確實有很大的不同,但是都是MVVM框架,因此上手沒有很大的難度,這次用React+Redux開發一個天氣預報小項目。源碼地址:github.com/Beichenlove…

“我自己是一名從事了6年web前端開發的老程序員(我的微信:web-xxq),今年年初我花了一個月整理了一份最適合2019年自學的web前端全套培訓教程(視頻+源碼+筆記+項目實戰),從最基礎的HTML+CSS+JS到移動端HTML5以及各種框架和新技術都有整理,打包給每一位前端小夥伴,這裏是前端學習者聚集地,歡迎初學和進階中的小夥伴(所有前端教程關注我的微信公衆號:web前端學習圈,關注後回覆“2020”即可領取)。

技術棧

前端

  • React: 用於構建界面的MVVM框架
  • Redux: React的集中狀態管理,方便快捷實現組件間通信
  • Redux-thunk: 常用的 redux 異步 action 中間件,用來處理接口請求等異步操作
  • styled-components: 以組件化的思想編寫CSS樣式
  • React-Redux:組件從Redux中讀取數據,並向store分發actions以更新數據
  • antd:基於React的UI庫
  • immutable:一種持久化數據結構,防止state對象被錯誤賦值

數據獲取

  • axios: 實現數據接口請求(用本地json文件模擬數據)

項目預覽

頁面初始化

 

                                        

       

選擇熱門城市

                                   

 

搜索其它城市

                                   

 

實現功能

 

獲取本地實時地位

初次打開頁面,根據所在城市進行天氣展示,需要我們進行一個實時地位的獲取,這裏我使用了高德地圖Web JS API。首先我們在public文件夾下的index.html引入在頁面添加 JS API 的入口腳本標籤;

 

// key值需在官網上申請
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=申請的key值">
</script> 複製代碼

我們使用官方提供的接口實現實時定位,因爲需要首次渲染就展示天氣信息,所以使用componenDidMount生命週期函數進行該請求:

 

 

 

componentDidMount() 
{    // 防止作用域被修改    
    let _self = this;    
    if(_self.props.init){      
        //eslint-disable-next-line      
        AMap.plugin('AMap.CitySearch', function () {        
          //eslint-disable-next-line        
          var citySearch = new AMap.CitySearch()        
          citySearch.getLocalCity(function (status, result) {          
          if (status === 'complete' && result.info === 'OK') {            
            // 查詢成功,result即爲當前所在城市信息            
            _self.props.getCity(result.city)            
            _self.initWeather(_self.props.city)            
            _self.props.getInit()          
        }        
    })      
   })    
   }    
    else{      
    _self.initWeather(_self.props.city)    
   }
}複製代碼

 

這裏需要做一個判斷,如果從其它頁面更改了城市選擇,回到此頁面會重新進行一個加載因而修改掉更改後的城市,因此我們用一個標識符來判斷是不是首次加載。

另外我們注意有個坑,React會提示找不到 AMap 實例問題。這裏使用註釋

//eslint-disable-next-line

寫在每個出現AMap類的前面一行,其eslint忽略此行代碼從而不報錯

獲取城市天氣信息

和獲取定位信息類似,我仍然使用的高德地圖提供的API,這裏我附上官網,lbs.amap.com/api/javascr…

echarts數據可視化

爲了顯示溫度變化趨勢,我使用了echarts的折線圖進行一個數據的可視化

實現代碼

 

 

 

initEchart(array) 
{    
    let domChart = this.dom;    
    //eslint-disable-next-line    
    var myChart = echarts.init(domChart);    
    let option = null;    
    option = {      
        xAxis: {        
        show: false,        
        type: "category",        
        axisLine: {          
            lineStyle: {            
            color: "#fff"          
        }        
    },        
    grid:{bottom: "20"}      
},      
    yAxis: {        
        show: false      
    },      
    series: [        
        {          
        data: array,          
        type: "line"        
        }      
    ]    
    }    
    myChart.setOption(option, true);  
}
複製代碼

 

使用react-redux操作Redux

react-redux是react官方用來綁定Redux,將Provider放在最上層,從而實現store可以被下面組件接收

 

 

 

<Provider store={store}>      
   <Router>        
    <div>         
     <Route exact path='/' component={MainPage}></Route>          
     <Route exact path='/search' component={SearchCity}></Route>        
    </div>      
   </Router>
</Provider>複製代碼

組件中我們使用connect()來獲取store裏的state或者dispatch action,利用其特性可以簡單方便地實現城市的更改,歷史搜索以及判斷標識符等數據的更改和獲取。

中間件thunk的使用 

redux默認的設定是dispatch只能接受一個對象參數,函數和promise都是不允許的,thunk中間件則能解決這個問題,redux-thunk 統一了異步和同步 action 的調用方式,把異步過程放在 action 級別解決,而component 沒有影響,這裏我配合react-redux實現redux數據的一個更新操作。

二級頁面城市搜索

我在二級頁面實現一個搜索城市,查詢城市天氣的功能,這裏我使用本地json文件,並用axios實現請求,

 

 

 

axios.get('/city/citys.json').then((res) => 
{   var tem = []      
    tem = res.data.citys.filter((item) => item.citysName.includes(value))      
    if(tem = [])
    {        
        unfound = 'Not Found'      
    }      
    callback(tem.slice(0, 10))      
    loading = false    
})複製代碼

 

我使用一個filter方法來進行條件篩選,返回含有輸入值的數據,若爲空,則返回一個提示。搜索框我採用了antd官方組件,它已經給我們封裝好了

 

 

 

 <Select  
    showSearch  
    value={this.state.value}  
    placeholder='請輸入城市名,快速查詢天氣信息'  
    defaultActiveFirstOption='flase'  
    showArrow='true'  
    filterOption={false}  
    onSearch={this.handleSearch}  
    onChange={this.handleChange}  
    onBlur={this.handleBlur}  
    notFoundContent={null}  
    style={{ width: '75%' }}  
    bordered='false'  
    loading={loading}  
    notFoundContent={unfound} >   
    {this.state.data.map(d => 
    <Option key={d.id}>{d.citysName}</Option>);} 
</Select>複製代碼

 

我用該組件文本框值變化時的回調函數handleSearch方法實現接口請求,篩選符合搜索條件的內容進行展示。並採用選中options(展示欄)的回調函數handleChange進行redux內state城市的一個更改,同時跳轉到首頁,代碼:

 

 

 

handleSearch = value => {    
    if (value) {      
    loading = true      
    fetch(value, data => this.setState({ data }));    
    } 
    else {      
        this.setState({ data: [] });    
    }  
};  
handleBlur = ()  => unfound = null; 
handleChange = value => {    
 this.state.data.map((item) => {      
 if (item.id == value) {        
    let city = item.citysName.split(',')[0]        
    this.props.changeCity(city)        
    this.props.history.push('/')        
    this.setState({ data: [] });      
    }    
})  
};複製代碼

結語

雖然這個項目只是一個簡單的小項目,但是對於自己的技能提示還是有一定的幫助。在開發過程中也遇到了一些問題,俗話說解決問題的過程就是自己能力提升的過程,畢竟學習之路,道阻且長,行則將至。

更多的項目詳情大家可以訪問我的Github,也 歡迎大家留言交流

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章