React实战之React+Redux实现一个天气预报小项目

引言

通过一段时间的React学习,React和Vue的开发确实有很大的不一样,可是都是MVVM框架,所以上手没有很大的难度,此次用React+Redux开发一个天气预报小项目。源码地址:github.com/Beichenlove…javascript

技术栈

前端html

  • React: 用于构建界面的MVVM框架
  • Redux: React的集中状态管理,方便快捷实现组件间通讯
  • Redux-thunk: 经常使用的 redux 异步 action 中间件,用来处理接口请求等异步操做
  • styled-components: 以组件化的思想编写CSS样式
  • React-Redux:组件从Redux中读取数据,并向store分发actions以更新数据
  • antd:基于React的UI库
  • immutable:一种持久化数据结构,防止state对象被错误赋值

数据获取前端

  • axios: 实现数据接口请求(用本地json文件模拟数据)

项目预览

页面初始化java

                                        

       

选择热门城市react

                                   


搜索其它城市ios

                                   


实现功能

获取本地实时地位

初次打开页面,根据所在城市进行天气展现,须要咱们进行一个实时地位的获取,这里我使用了高德地图Web JS API。首先咱们在public文件夹下的index.html引入在页面添加 JS API 的入口脚本标签;git

// key值需在官网上申请
<script type="text/javascript" src="https://webapi.amap.com/maps?v=1.4.15&key=申请的key值">
</script> 复制代码

咱们使用官方提供的接口实现实时定位,由于须要首次渲染就展现天气信息,因此使用componenDidMount生命周期函数进行该请求:github

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)    
   }
}复制代码

这里须要作一个判断,若是从其它页面更改了城市选择,回到此页面会从新进行一个加载于是修改掉更改后的城市,所以咱们用一个标识符来判断是否是首次加载。web

另外咱们注意有个坑,React会提示找不到 AMap 实例问题。这里使用注释json

//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,也欢迎你们留言交流~

相关文章
相关标签/搜索