当前位置: 首页 > 工具软件 > php-proxy-app > 使用案例 >

函数式组件进行数据请求 && 类组件进行 异步数据请求 && better-scroll && http-router-proxy && 动态路由@stage3---week5--day4

吴英武
2023-12-01

函数式组件 useEffect 进行数据请求

需要进行判断,否则会进行多次数据请求

import React, { useState, useEffect } from "react";
import axios from "axios";
import HotItem from "./hot_item";
import "./index.scss";

function MoviesHot() {
  let [movies_hot, setMovies_hot] = useState([]);

  useEffect(() => {
    if (movies_hot.length !== 0) return;
    axios
      .get("/ajax/movieOnInfoList", {
        params: {
          token: ""
        }
      })
      .then(ret => {
        setMovies_hot((movies_hot = ret.data.movieList));
      });
  });

  function renderHotItem() {
    return movies_hot.map(item => <HotItem key={item.id} {...item}></HotItem>);
  }
  return <article id="hot_list">{renderHotItem()}</article>;
}

export default MoviesHot;

然后进行简单的数据渲染

import React from "react";
import { Button } from "antd-mobile";

function HotItem(props) {
  function sc() {
    return (
      <p>
        <span>观众评</span>
        <span className="hot_sc">{props.sc}</span>
      </p>
    );
  }
  function wish() {
    return (
      <p>
        <span className="hot_wish">{props.wish}</span>
        <span>人想看</span>
      </p>
    );
  }
  return (
    <article className="hot_item">
      <section className="hot_img">
        <img src={props.img.replace("w.h", "128.180")} />
      </section>
      <section className="hot_main">
        <h4>{props.nm}</h4>
        {(props.globalReleased && sc()) || wish()}
        <p>主演:{props.star}</p>
        <p>{props.showInfo}</p>
      </section>
      <section className="hot_state">
        <Button
          inline
          size="small"
          type={(props.globalReleased && "warning") || "primary"}
        >
          {(props.globalReleased && "购买") || "预售"}
        </Button>
      </section>
    </article>
  );
}

export default HotItem;

类组件进行 异步数据请求

import React, { Component } from "react";
import request from "../../utils/request.js";
import "./index.scss";
import CateList from "./cate_list.js";

export default class List extends Component {
  constructor(props) {
    super(props);

    this.state = {
      lists: []
    };
  }

  async componentDidMount() {
    //? 数据请求
    //* 先发送数据请求,然后获得数据,然后赋值给我们组件的状态
    const result = await request({
      method: "get",
      url: "/index.php",
      params: {
        r: "class/category",
        type: 1
      }
    });
    this.setState({
      lists: result.data.data.data
    });
  }
  render() {
    let { lists } = this.state;
    return (
      <article id="list">
        <CateList lists={lists}></CateList>
      </article>
    );
  }
}

然后进行多层数据 渲染

import React, { Component } from "react";
import { Tabs } from "antd-mobile";
import { Link } from "react-router-dom";

export default class CateList extends Component {
  renderList = list => {
    //todo 渲染每一个最小的 元素
    return list.map(item => (
      <li key={item.api_cid} className="list_item">
        <Link
          to={{
            pathname: `/category/${item.api_cid}`,
            search: `?cid=${item.api_cid}`
          }}
        >
          <img src={item.img} />
          <span>{item.name}</span>
        </Link>
      </li>
    ));
  };

  renderFloors = floors => {
    //todo 渲染主内容中的每一个楼层结构
    return floors.map((item, index) => (
      <section key={index} className="list_floor">
        <h3>
          {item.name} <Link to={item.label_url}>{item.label_name}</Link>
        </h3>
        <ul>{this.renderList(item.list)}</ul>
      </section>
    ));
  };

  renderContent = (
    tab // todo 渲染每条数据的主要内容
  ) => (
    <article
      style={{
        padding: "0.1rem .2rem",
        height: "100%",
        backgroundColor: "#fff"
      }}
    >
      <section className="list_banner">
        <a href={tab.banner_url} style={{ display: "block", width: "100%" }}>
          <img src={tab.banner_img} style={{ width: "100%" }} />
        </a>
      </section>
      {this.renderFloors(tab.floors)}
    </article>
  );

  render() {
    let lists = this.props.lists;
    lists.map(item => {
      //* 给每一个数据添加title 属性
      item.title = item.name;
    });
    // console.log("张浩雨: CateList -> render -> lists", lists)

    const tabs = lists; //? tabs 为数据

    return (
      <article id="category_list">
        <Tabs
          tabs={tabs}
          tabBarPosition="left"
          tabDirection="vertical"
          renderTabBar={props => <Tabs.DefaultTabBar {...props} page={13} />}
        >
          {this.renderContent}
        </Tabs>
      </article>
    );
  }
}

http-router-proxy

进行反向代理

  • 通过第三方模块 http-proxy-middleware 来进行跨域
  • 易错点: setupProxy.js 文件存放目录
// > src/setupProxy.js文件
//! 这个文件就是反向代理的配置文件
const proxy = require("http-proxy-middleware");

module.exports = function(app) {
  //* app.use( proxy(标识符,配置))
  app.use(
    proxy("/ajax", {
      target: "http://m.maoyan.com",
      changeOrigin: true
    })
  );
  app.use(
    proxy("/index.php", {
      target: "http://www.qinqin.net",
      changeOrigin: true
    })
  );
};

better-scroll

实现长列表滚动
BetterScroll 是一款重点解决移动端(已支持 PC)各种滚动场景需求的插件。它的
布局要求

<div class="wrapper">
  <ul class="content">
    <li>...</li>
    <li>...</li>
    ...
  </ul>
  <!-- 这里可以放一些其它的 DOM,但不会影响滚动 -->
</div>

上面的代码中 BetterScroll 是作用在外层 wrapper 容器上的,滚动的部分是 content 元素。这里要注意的是,BetterScroll 只处理容器(wrapper)的第一个子元素(content)的滚动,其它的元素都会被忽略。

实例化要求
最简单的初始化代码如下:

import BScroll from "@better-scroll/core";
let wrapper = document.querySelector(".wrapper");
let scroll = new BScroll(wrapper);

案例

//! movies > index.js
import React, { Fragment, useEffect } from "react";
import MoviesHot from "./movie_hot";
import MoviesComming from "./movies_commint";
import MoviesNav from "./movies_nav";
import { Route, Redirect } from "react-router-dom";
import BScroll from "better-scroll";
import "./index.scss";

function MoviesContainer() {
  useEffect(() => {
    setTimeout(() => {
      new BScroll(document.querySelector("#moviescontainer"), {
        click: true // todo 这里的意思是点击去除遮罩层
      });
    }, 0);
  });
  return (
    <Fragment>
      <MoviesNav></MoviesNav>
      <article id="moviescontainer">
        <Redirect from="/home" to="/home/movies_hot"></Redirect>
        <Route path="/home/movies_hot" component={MoviesHot}></Route>
        <Route path="/home/movies_comming" component={MoviesComming}></Route>
      </article>
    </Fragment>
  );
}

export default MoviesContainer;

动态路由

<Route path = “/list” component = { List }/>

​ <Route path = “/list/:id” component = { List }/>

以上两个形式都可以,但是如果写了/:id之后,路径必须全跟

​ 举例: http://localhost:3000/list/001?a=1&b=2

路由传参

  • 定义
src > router > index.js;
import React, { useState } from "react";
import { Route, Switch, Redirect } from "react-router-dom";
import Home from "../views/home";
import Category from "../views/category";
import Shopcar from "../views/shopcar";
import Mine from "../views/mine";
import List from "../views/list";

function RouterComp() {
  const [routes] = useState([
    {
      id: 1,
      path: "/home",
      component: Home
    },
    {
      id: 2,
      path: "/category/:id", //todo 定位
      component: Category
    },
    {
      id: 3,
      path: "/shopcar",
      component: Shopcar
    },
    {
      id: 4,
      path: "/mine",
      component: Mine
    },
    {
      id: 5,
      path: "/list",
      component: List
    }
  ]);

  function renderRoutes() {
    return routes.map(item => (
      <Route
        key={item.id}
        path={item.path}
        component={item.component}
        exact={item.exact}
      ></Route>
    ));
  }
  return (
    //* Route是一个路由展示组件,通过component属性来确定渲染哪一个组件
    //* Switch组件一次只渲染一个Route
    // * 可以实现类似按需加载组件的作用,可以起到一定的性能优化作用
    //* exact 是路由完全匹配
    //* Redirect 是重定向组件  from 来源  to 目标     /  /home
    // <BrowserRouter>
    <Switch>
      <Redirect from="/" to="/home" exact></Redirect>
      {renderRoutes()}

      {/* <Router path="/home" component={Home} exact=></Router> */}
    </Switch>
    //{/* </BrowserRouter> */}
    // <Home></Home>
  );
}

export default RouterComp;
  • 使用
// > src > views> list > cate_list.js

import React, { Component } from "react";
import { Tabs } from "antd-mobile";
import { Link } from "react-router-dom";

export default class CateList extends Component {
  renderList = list => {
    //todo 渲染每一个最小的 元素
    return list.map(item => (
      <li key={item.api_cid} className="list_item">
        <Link
          to={{
            pathname: `/category/${item.api_cid}`, // todo 定位
            search: `?cid=${item.api_cid}` // todo 定位
          }}
        >
          <img src={item.img} />
          <span>{item.name}</span>
        </Link>
      </li>
    ));
  };

  renderFloors = floors => {
    //todo 渲染主内容中的每一个楼层结构
    return floors.map((item, index) => (
      <section key={index} className="list_floor">
        <h3>
          {item.name} <Link to={item.label_url}>{item.label_name}</Link>
        </h3>
        <ul>{this.renderList(item.list)}</ul>
      </section>
    ));
  };

  renderContent = (
    tab // todo 渲染每条数据的主要内容
  ) => (
    <article
      style={{
        padding: "0.1rem .2rem",
        height: "100%",
        backgroundColor: "#fff"
      }}
    >
      <section className="list_banner">
        <a href={tab.banner_url} style={{ display: "block", width: "100%" }}>
          <img src={tab.banner_img} style={{ width: "100%" }} />
        </a>
      </section>
      {this.renderFloors(tab.floors)}
    </article>
  );

  render() {
    let lists = this.props.lists;
    lists.map(item => {
      //* 给每一个数据添加title 属性
      item.title = item.name;
    });
    // console.log("张浩雨: CateList -> render -> lists", lists)

    const tabs = lists; //? tabs 为数据

    return (
      <article id="category_list">
        <Tabs
          tabs={tabs}
          tabBarPosition="left"
          tabDirection="vertical"
          renderTabBar={props => <Tabs.DefaultTabBar {...props} page={13} />}
        >
          {this.renderContent}
        </Tabs>
      </article>
    );
  }
}

路由接参

import React, { useState, useEffect } from "react";
import "./index.scss";
import { Route, NavLink, Redirect } from "react-router-dom";
import Picture from "./children/picture";
import Text from "./children/text";
import Comment from "./children/comment";
import request from "../../utils/request";
import axios from "axios";

function Category(props) {
  const [navLink] = useState([
    {
      id: 1,
      text: "图片",
      path: "/category/picture"
    },
    {
      id: 2,
      text: "文字",
      path: "/category/text"
    },
    {
      id: 3,
      text: "评论",
      path: "/category/comment"
    }
  ]);
  let [detail, setDetail] = useState([]);
  let [cid, setCid] = useState(22);
  function renderNavLink() {
    return navLink.map(item => {
      return (
        <NavLink to={item.path} key={item.id}>
          {item.text}
        </NavLink>
      );
    });
  }

  useEffect(() => {
    let id =
      props.location.pathname
        .slice(0)
        .split("/")
        .pop() || 22; //todo 定位
    console.log("张浩雨: Category -> id", id);
    setCid((cid = id));

    setTimeout(() => {
      if (detail.length) {
        return;
      } else {
        axios
          .get("/index.php", {
            params: {
              r: "class/cyajaxsub",
              page: 1,
              cid: cid,
              px: "t"
            }
          })
          .then(ret => {
            console.log(ret.data.data.content);
            setDetail((detail = ret.data.data.content));
          });
      }
    }, 0);
  });
  return (
    <article className="category-box">
      <section className="category-nav">{renderNavLink()}</section>
      <section className="category-main">
        <h3>列表</h3>
        {/* <Redirect from="/category" to="/category/text" exact></Redirect> */}
        <Route path="/category/picture" component={Picture}></Route>
        <Route path="/category/text" component={Text}></Route>
        <Route path="/category/comment" component={Comment}></Route>
      </section>
    </article>
  );
}

export default Category;
 类似资料: