引言
經過一段時間的React學習,React和Vue的開發確實有很大的不同,但是都是MVVM框架,因此上手沒有很大的難度,這次用React+Redux開發一個天氣預報小專案。原始碼地址:github.com/Beichenlove…
技術棧
前端
- 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,也歡迎大家留言交流~