react H5app项目 电影 高德地图获取当前城市 获取所有城市列表并渲染 react路由的三种传参方式

项目初始化准备

创建项目:create-react-app 项目名
删除无用文件
建立工程化目录:apis utils views hooks router assets components
快速初始化页面:rfc
安装:npm i sass sass-loader react-router-dom -D
启动项目:npm start / npm run start
重置样式结构更改为.scss .jsx文件
index.scss中重置样式:去掉margin padding
百度配置 react @别名:

创建页面

一级页面(占整个页面):登录、注册、layout、电影详情、选座位、选择城市
二级页面:热映、影院、我的

配置路由

配置路由表router/index.js

import Cinema from "@/pages/cinema"
import Citys from "@/pages/citys"
import Detail from "@/pages/detail"
import Layout from "@/pages/layout"
import Login from "@/pages/login"
import Register from "@/pages/register"
import Seat from "@/pages/seat"
import Show from "@/pages/show"


export default[
  {
    path:'/login',
    element:<Login/>
  },
  {
    path:'/register',
    element:<Register/>
  },
  {
    path:'/layout',
    element:<Layout/>,
    children:[
      {
        path:'show',
        element:<Show/>
      },
      {
        path:'cinema',
        element:<Cinema/>
      },
      {
        path:'my',
        element:<My/>
      },
    ]
  },
  {
    path:'/detail',
    element:<Detail/>
  },
  {
    path:'/seat',
    element:<Seat/>
  },
  {
    path:'/citys',
    element:<Citys/>
  },
]

工具函数中计算路由的函数 /utils/getRoutes.js

import { Route } from 'react-router-dom'
import router from '@/router'
import { Suspense } from 'react'

export const getRoutes = (routes = router)=>{
    return routes.map(route =>{
        return (
            <Route path={route.path} key={route.path} element={
                <Suspense>
                    {route.element}
                </Suspense>
            }>
                {
                    route.children && route.children.length?getRoutes(route.children):""
                }
            </Route>
        )
    })
}

App.jsx

import React from 'react'
import { HashRouter,  Routes } from 'react-router-dom'
import './App.scss'

import {getRoutes} from './utils/getRoutes'
export default function index() {
  return (
    <div className='app'>
      <HashRouter>
        <Routes>
          {
            getRoutes()
          }
        </Routes>
      </HashRouter>
    </div>
  )
}

安装:yarn add antd-mobile -D
安装axios:npm i axios
验证码防抖安装:npm i react-simple-verify
/utils/config.js配置

export const baseURL = 'http://129.211.169.131:3333'

封装axios /utils/http.js

import axios from "axios"
import { baseURL } from "./config"
//创建axios实例
const instance = axios.create({
    baseURL,//服务器地址
    timeout:30000 //超时时间
})

//请求拦截器
instance.interceptors.request.use(
    config =>{
        return config
    },
    err =>{
        return Promise.reject(err)
    }
)

//响应拦截器
instance.interceptors.response.use(
    res =>{
        return res
    },
    err =>{
        return Promise.reject(err)
    }
)

export default instance

模块化api /apis/user

import http from '@/utils/http'

//用户登录
export const api_user_login =(data) =>{
    return http({
        url:'/login',
        method:'POST',
        data
    })
}

登录页面 /login

import React, { useRef, useState } from 'react'
import { Button, Input, Toast } from 'antd-mobile'
import './index.scss'
import { api_user_login } from '@/apis/user'
import ReactSimpleVerify from 'react-simple-verify'
import 'react-simple-verify/dist/react-simple-verify.css'
import { useNavigate } from 'react-router-dom'

export default function Login() {

    let [acc, setAcc] = useState('')
    let [pwd, setPwd] = useState('')
    let [isNone, setIsNone] = useState(true) // true:隐藏
    let verify = useRef(null)
    let navigate = useNavigate()

    const verifySuccess = async () => {
        const res = await api_user_login({
            acc,
            pwd
        })
        // console.log(111, res);
        if (res.data.code === 0) {
            console.log('verify', verify);
            // 登陆失败重置验证码
            verify.current.reset()
        } else {
            // 登陆成功跳转至首页
            navigate('/layout/show')
        }
    }

    const handleLogin = () => {
        console.log('登录', acc, pwd);
        if (!acc || !pwd) {
            Toast.show({
                content: '请输入用户名和密码',
            })
            return
        }
        setIsNone(false)
    }

    return (
        <div className='login'>
            <div>
            <Input placeholder='请输入用户名' clearable value={acc} onChange={val => {
                setAcc(val)
            }} />
            </div>
            <Input placeholder='请输入密码' clearable type='password' value={pwd} onChange={val => {
                setPwd(val)
            }} />
            <div style={{ display: isNone ? 'none' : '' }}>
                <ReactSimpleVerify ref={verify} success={verifySuccess} />
            </div>
            <Button block color='primary' fill='solid' onClick={handleLogin}>
                登录
            </Button>
        </div>
    )
}

框架layout,使用tabBar
import { TabBar } from 'antd-mobile'
import React, { useEffect, useState } from 'react'
import { Outlet, useLocation, useNavigate } from 'react-router-dom'
import './index.scss'
import {
  AppOutline,
  CalendarOutline ,
  UserOutline,
} from 'antd-mobile-icons'


export default function Layout() {
  let [curKey,setCurkey] = useState('show')
   // 可以从useLocation hooks函数中获取路由的信息
   const { pathname } = useLocation()

   useEffect(()=>{
  let key = pathname.substring(pathname.lastIndexOf('/')+1)
  setCurkey(key)
   },[])

  const navigate = useNavigate()

  const handleChange = (key) =>{
    console.log(key)
    setCurkey(key)
    navigate(`/layout/${key}`)
  }
  return (
    <div className='layout'>
      <Outlet/>
      <div className='tabbar'>
        <TabBar onChange={handleChange} activeKey={curKey}>
          <TabBar.Item key='show' title="热映" icon={<AppOutline />}/>
          <TabBar.Item key='cinema' title="影院" icon={<CalendarOutline />}/>
          <TabBar.Item key='my' title="我的" icon={<UserOutline />}/>
        </TabBar>
      </div>
    </div>
  )
}

热映界面 /layout/show

import React, { Suspense } from 'react'
import './index.scss'
import { Tabs } from 'antd-mobile'
import Showing from './components/showing'
import WillShow from './components/willShow'

export default function Show() {
  return (
    <div className='show'>
      <Tabs>
        <Tabs.Tab title='正在热映' key='show'>
          <Suspense>
            <Showing />
          </Suspense>
        </Tabs.Tab>
        <Tabs.Tab title='即将上映' key='vegetables'>
          <Suspense>
            <WillShow />
          </Suspense>
        </Tabs.Tab>
      </Tabs>
    </div>
  )
}

/show/components/movieItem

import { baseURL } from '@/utils/config'
import { Button } from 'antd-mobile'
import React from 'react'
import './index.scss'

export default function MovieItem(props) {
  // console.log(props)

  const {actors,director,image,name,point,type} = props
  return (
    <div className='movie-item'>
        <div className='left'>
          <img src={baseURL+image}  />
        </div>
        <div className='right'>
            <div className='cont'>
              <h3>{name}</h3>
              <p>淘票票评分{point}</p>
              <p>导演:{director}</p>
              <p>主演:{actors}</p>
            </div>
            <div className='btn'>
              <Button block shape='rounded' color='danger' size='small'>{type===1?'购票':'预售'}</Button>
            </div>
        </div>
    </div>
  )
}

/show/components/showing

import React, { useEffect, useState } from 'react'
import {api_search_movielist} from '@/apis/showing'
import MovieItem from '../movieItem'

export default function Showing() {

    let [list,setList] = useState([])

    useEffect(()=>{
        getList()
    })

    const getList = async() =>{
        const res = await api_search_movielist({
            state:1
        })
        // console.log(res)
        setList(res.data.data)
    }
  return (
    <div>
        {
            list.map(item => {
                return <MovieItem key={item.id} {...item} type={1}/>
            })
        }
    </div>
  )
}

/show/components/willShow

import React, { useEffect, useState } from 'react'
import {api_search_movielist} from '@/apis/showing'
import MovieItem from '../movieItem'

export default function WillShow() {

    let [list,setList] = useState([])

    useEffect(()=>{
        getList()
    })

    const getList = async() =>{
        const res = await api_search_movielist({
            state:2
        })
        // console.log(res)
        setList(res.data.data)
    }
  return (
    <div>
        {
            list.map(item => {
                return <MovieItem key={item.id} {...item} type={2}/>
            })
        }
    </div>
  )
}

H5App使用高德地图,获取当前城市

地图JS API -》定位-》地图初始化时加载定位到当前城市-》相关示例=》获取经纬度
在Index.html中引入,此处 key:是自己申请
控制台 -> 应用管理 -> 我的应用 -> 创建新应用(如果没有的话) -> 添加(服务平台选择:web端(JS API))

<!-- 引入高德地图的IP城市定位文件 -->
    <script type="text/javascript" src="//webapi.amap.com/maps?v=2.0&key=31d40fd2642d893417c1752a510f3591"></script>

获取经纬度后,再调用web服务API 逆地理编码API去获取城市

//初始化地图时,若center属性缺省,地图默认定位到用户所在城市的中心
    let map = new AMap.Map('container', {
      zoom: 11,
    });
    console.log(map.getCenter())
    // 获取经纬度
    let {lng,lat} = map.getCenter()

在http.js中添加

// 高德服务
export const amap_server = axios.create({
    baseURL: 'https://restapi.amap.com',
    timeout: 30000
})

在apis/amap.js中

/**
 * https://restapi.amap.com  ---> 高德服务器地址
 * /v3/geocode/regeo ---> 接口
 * ---- 参数 ---- 
 * key ---> 用户在高德地图官网申请Web服务API类型Key
 * location ---> 经纬度坐标 (经度,纬度)
 */
import { amap_server } from '@/utils/http'

export const api_amap_geocode = (params) => {
    return amap_server({
        url: '/v3/geocode/regeo',
        method: 'GET',
        params
    })
}

获取到城市(不知道为啥一直获取的是北京)

import { api_amap_geocode } from '@/apis/amap'
import React, { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import './index.scss'


export default function Cinema() {
  // 当前城市
  let [city, setCity] = useState('定位中...')
  let navigate = useNavigate()
  useEffect(() => {
    //初始化地图时,若center属性缺省,地图默认定位到用户所在城市的中心
    let map = new AMap.Map('container', {
      zoom: 11,
    });
    // console.log(map.getCenter())
    // 获取经纬度
    let {lng,lat} = map.getCenter()
    // 发送逆地理编码的请求
    api_amap_geocode({
      // 此处key值是 web服务的key
      key: '959ea2812874784b56a44afb19d96219',
      location: lng + ',' + lat
  }).then(res => {
    // console.log(res)
      setCity(res.data.regeocode.addressComponent.province)
  })
  }, [])
  //跳转到城市列表页
  const handleJumpCity = () =>{
    navigate('/citys')
  }
  return (
    <div className='cinema'>
      <p onClick={handleJumpCity}>{city}</p>
      <div id="container" style={{ display: 'none' }}></div>
    </div>
  )
}


获取城市列表,并渲染

http.js中

// 城市
export const city_server = axios.create({
    baseURL: 'http://129.211.169.131:6368',
    timeout: 30000
})

apis/city.js中

import { city_server } from '@/utils/http'

// 获取城市数据
export const api_get_citys = () => {
    return city_server({
        url: '/citys',
        method: 'GET'
    })
}
通过BetterScroll来联动城市选择

官网1.x:https://better-scroll.github.io/docs-v1/#/
安装:npm install better-scroll@1.11.1
引入:import BScroll from 'better-scroll'
使用:

// 实例化BScroll
let scroll = new BScroll('滚动容器')
// 滚动到指定元素
scroll.scrollToElement(元素, 滚动动画时间)

实现代码/citys/index.jsx

import { api_get_citys } from '@/apis/city'
import React, { useEffect, useState } from 'react'
import './index.scss'
import BScroll from 'better-scroll'

let scroll = null
export default function ChooseCity() {

    const [cityList, setCityList] = useState([
        // {
        // 	letter: 'C',
        // 	citys: [{
        // 			city_name: "重庆",
        // 			city_pinyin: "Chongqing",
        // 			city_pre: "C",
        // 			city_short: "cq",
        // 			count: "230",
        // 			id: "41"
        // 		}
        // 	]
        // },
    ])
    useEffect(() => {
        getCitys()
        // 实例化BScroll
        scroll = new BScroll('.city-cont')
        console.log('scroll', scroll);
    }, [])
    // 获取城市列表数据
    const getCitys = async () => {
        const res = await api_get_citys()
        getCityData(res.data)
    }
    // 处理城市数据
    const getCityData = (data) => {
        // 过滤首字母
        let letter = data.map(item => item.city_pre.toUpperCase())
        // 去重
        letter = [...new Set(letter)]
        // 排序
        letter.sort()
        let list = []
        letter.forEach(item => {
            let obj = {
                letter: item,
                citys: []
            }
            data.forEach(v => {
                if (item === v.city_pre.toUpperCase()) {
                    obj.citys.push(v)
                }
            })
            list.push(obj)
        })

        setCityList(list)
    }
    // 点击右侧字母
    const handleLetter = (id) => {
        scroll.scrollToElement('#' + id, 300)
    }
    return (
        <div className="city-container">
            <div className="city-cont">
                <div>
                    {
                        cityList.map(item => {
                            return (
                                <div id={item.letter} key={item.letter} className="city-type-wrap">
                                    <div className="city-letter">
                                        <span>{item.letter}</span>
                                    </div>
                                    <div className="city-list-wrap">
                                        {
                                            item.citys.map(city => {
                                                return (
                                                    <span className="city-name" key={city.id}>{city.city_name}</span>
                                                )
                                            })
                                        }
                                    </div>
                                </div>
                            )
                        })
                    }
                </div>
            </div>
            <div className="letter">
                {
                    cityList.map((item, i) => {
                        return <div key={i} onClick={() => { handleLetter(item.letter) }} className="letter-item">{item.letter}</div>
                    })
                }
            </div>
        </div>
    )
}

样式文件

.city-container {
    background-color: #fff;
    height: 100%;
    overflow: hidden;

    .city-cont {
        padding: 10px;
        height: 100%;
        overflow-y: scroll;
    }

    .city-type-wrap {
        .city-letter {
            padding: 5px 0;
        }

        .city-list-wrap {
            display: flex;
            flex-wrap: wrap;

            .city-name {
                padding: 13px 18px;
            }
        }
    }

    .letter {
        position: fixed;
        right: 0;
        top: 0;
        bottom: 0;
        width: 20px;
        display: flex;
        flex-direction: column;
        justify-content: center;

        .letter-item {
            padding: 5px 0;
            width: 100%;
            text-align: center;
        }
    }
}

实现效果图

获取影院列表并进行渲染

cinema完整代码,带参跳转到影院详情页,react的三种路由传参方式

import { api_amap_geocode } from '@/apis/amap'
import { api_cenema_list } from '@/apis/showing'
import React, { useEffect, useState } from 'react'
import { useNavigate } from 'react-router-dom'
import './index.scss'


export default function Cinema() {
  // 当前城市
  let [city, setCity] = useState('定位中...')
  // 影院列表
  let [cinemaList, setCinemaList] = useState([
    // {
    //     address: "成华区建设北路3段6号龙湖三千集购物中心5号楼",
    //     cid:1,
    //     name:"UME影城(成都成华店)",
    //     price:28.9,
    //     type:"3D 观影小食 DMAX 可停车",
    // }
  ])
  let navigate = useNavigate()
  //获取城市
  useEffect(() => {
    //初始化地图时,若center属性缺省,地图默认定位到用户所在城市的中心
    let map = new AMap.Map('container', {
      zoom: 11,
    });
    // console.log(map.getCenter())
    // 获取经纬度
    let { lng, lat } = map.getCenter()
    // 发送逆地理编码的请求
    api_amap_geocode({
      // 此处key值是 web服务的key
      key: '959ea2812874784b56a44afb19d96219',
      location: lng + ',' + lat
    }).then(res => {
      // console.log(res)
      setCity(res.data.regeocode.addressComponent.province)
    })
  }, [])
  //跳转到城市列表页
  const handleJumpCity = () => {
    navigate('/citys')
  }
  //获取影院
  useEffect(() => {
    getCinemaList()
  },[])

  //获取影院列表
  const getCinemaList = async () => {
    const res = await api_cenema_list()
    // console.log(res)
    if (res.data.code === 1) {
      setCinemaList(res.data.data)
    }
  }
  //跳转到详情页
  const handleJumpDetail = (item) => {
    // console.log(item)
    //react路由的三种传参方式
    // navigate('/detail/' + JSON.stringify(item))
    // search方式
    // navigate('/detail?cinemaInfo=' + JSON.stringify(item))
    // state方式
    navigate('/detail', {
      state: item
    })
  }
  return (
    <div className='cinema'>
      <p onClick={handleJumpCity}>{city}</p>
      <div id="container" style={{ display: 'none' }}></div>
      <div className='list-wrap'>
        {
          cinemaList.map(item => {
            return (
              <div className='list' key={item.cid} onClick={() => handleJumpDetail(item)}>
                <div className='title'>
                  <h3>{item.name}</h3>
                  <span className='price'>{item.price}</span>
                </div>
                <h6>{item.address}</h6>
                <p className='type'>{item.type}</p>
              </div>
            )
          })
        }
      </div>
    </div>
  )
}

react的三种路由跳转传参方式

方式一:

//跳转传参
  const handleJumpDetail = (item) => {
    // console.log(item)
     navigate('/detail/' + JSON.stringify(item))
  }
//router.js
{
	path:'/detail/:cinemaInfo',
	element:<Detail />
}
//获取
// 刷新不会丢失
const params = JSON.parse(useParams().cinemaInfo)

方式二:传递的是search参数,路由不需要像上面那样配置

//传参
 const handleJumpDetail = (item) => {
    // console.log(item)
   // search方式
    navigate('/detail?cinemaInfo=' + JSON.stringify(item))
  }
//获取
// search接收 刷新不会丢失
 const [searchParams] = useSearchParams()
 console.log('searchParams', searchParams.get('cinemaInfo'));

方式三:传递的是state参数 【推荐】

const handleJumpDetail = (item) => {
    // console.log(item)
    // state方式
    navigate('/detail', {
      state: item
    })
  }
// state接收 刷新不会丢失
    const { state } = useLocation()
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
React高德地图是一个针对React进行封装的地图插件,可以通过引入react-amap库来使用。你可以在官方网址https://elemefe.github.io/react-amap/components/map找到更多关于该插件的API文档。在使用时,你可以通过安装react-amap来引入插件,也可以直接使用SDN方式引入。在React组件中,你可以使用Map和Marker等组件来展示地图和标记点。你需要在高德官网上申请一个地图的API Key,并将其作为amapkey属性递给Map组件。你还可以通过设置属性和绑定事件来自定义地图的行为,比如设置地图的中心点、缩放级别,以及绑定单击、双击、移动等事件。如果需要销毁地图实例,你可以使用map.destroy()方法来注销地图实例并释放内存。\[1\]\[2\]\[3\] #### 引用[.reference_title] - *1* *2* [React使用高德地图react-amap)(一)](https://blog.csdn.net/u013262823/article/details/92795965)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [【高德地图React项目中的使用——(二)各种配置的使用】](https://blog.csdn.net/qq_45149366/article/details/126125667)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值