案例:React路由商品页面


app.js

import React from 'react';

import {Route, Link} from 'react-router-dom';

import './css.css';

import Home from './views/Home';

import About from './views/About';

import View from "./views/View";

/**

 * 页面 - 组件

 * 根据不同的 url 的变化,在我们的应用中指定的位置渲染不同的组件,从而显示出来不同的内容

 *

 * 组件

 *  - 页面组件(视图组件),一个页面组件一般对应的就是完整的页面(完整:一个url所表示的页面)

 *  - 功能组件(具有一定功能的,但一般情况下又不是一个完整的页面的组件,轮播图,对话框)

 *      - 带视图的功能组件(轮播图)

 *      - 不带视图的功能组件(数据过滤,请求 - 容器,错误捕获)

 *  - 容器组件

 */

class App extends React.Component {

    constructor(props) {

        super(props);

        this.state = {

            items: [

                {

                    id: 1,

                    name: 'iPhone XR',

                    price: 542500

                },

                {

                    id: 2,

                    name: 'Apple iPad Air 3',

                    price: 377700

                },

                {

                    id: 3,

                    name: 'Macbook Pro 15.4',

                    price: 1949900

                },

                {

                    id: 4,

                    name: 'Apple iMac',

                    price: 1629900

                },

                {

                    id: 5,

                    name: 'Apple Magic Mouse',

                    price: 72900

                },

                {

                    id: 6,

                    name: 'Apple Watch Series 4',

                    price: 599900

                }

            ]

        }

    }

    render() {

        // console.log(window.location);

        // let hash = window.location.hash || '#home';

        //

        // console.log(hash);

        return (

            <div className="App">

                <h1>React路由</h1>

                <nav>

                    {/*<a href="/">首页</a>*/}

                    <Link to="/">首页</Link>

                    <span> | </span>

                    {/*<a href="/about">关于我们</a>*/}

                    <Link to="/about">关于我们</Link>

                </nav>

                <hr/>

                {/*<input type="text"/>*/}

                {/*{*/}

                {/*    hash === '#home' && <Home />*/}

                {/*}*/}

                {/*{*/}

                {/*    hash === '#about' && <About />*/}

                {/*}*/}

                {/*

                    用来配置 url 与 组件的映射关系:什么url与什么组件显示在页面的什么位置

                    <Route /> 所在的位置就是满足要求以后组件渲染对应的位置

                */}

                {/*

                    下面这种写法,items 是传递给了 Route ,而不是 Home

                */}

                {/*<Route path="/" component={Home} exact items={this.state.items} />*/}

                {/*

                    传递 props 给 component 指定的 组件

                    Route 还提供了一个 render 属性,传入一个函数,函数返回的值就是 等同于 Component 指定的组件渲染的结果

                 */}

                {/*<Route path="/" exact items={this.state.items} render={() => {*/}

                {/*    return <div>我是render出来的</div>*/}

                {/*}} />*/}

                <Route path="/" exact render={() => <Home items={this.state.items} />} />  

                                {/* 只有一个return,所以可以简写 */}

                {/*<Home items={this.state.items} />*/}

                {/*商品详情*/}

                {/*<Route path='/view' render={() => {*/}

                {/*    // 如果组件是页面组件,那么这个两个不同的页面组件之间的数据传递就不要通过 传统组件父子通信来做,数据要通过页面(路由等方式来进行传递)*/}

                {/*    return <View />*/}

                {/*}}></Route>*/}

                {/*

                    下面的路由是动态,后面的 id 表示动态部分匹配到内容

                    当下 /view/*** 才能匹配当前的路由

                    如果一个组件是路由组件(路由直接绑定并访问的组件),那么该组件就不会自动注入

                    - history: 同history api 类似

                    - match: 当前访问的路由信息

                    - location: 等同 原生的 location

                */}

                {/*<Route path="/view/:id(\d+)" component={View} />*/}

                {/*

                    View 不在是路由组件了,那么也就表示 Route 注入的 路由相关信息就没有了

                    如果使用了 render 函数,那么路由注入的 history、match 等对象都作为参数传递给了render函数了

                    render 其实就是一个函数式的组件

                */}

                <Route path="/view/:id(\d+)" render={(props) => {

                    // console.log(props);

                    // return <View match={props.match} history={props.history} location={props.location} />

                    return <View {...props} items={this.state.items} />

                }} />

                <Route path="/about" component={About}/>

            </div>

        )

    }

}

export default App;

// class Route extends React.Component {

//

//     render() {

//

    //         // this.props.component.props.history

//         // this.props.component.props.match

//         // this.props.component.props.location

//

//         return this.props.component;

//     }

//

// }


index.js

import React from 'react';

import ReactDOM from 'react-dom';

import App from './App';

import * as serviceWorker from './serviceWorker';

import {HashRouter, BrowserRouter} from 'react-router-dom';

/**

 * HashRouter: 组件

 *  被 HashRouter 包含的组件才能响应路由

 *

 * BrowserRouter: 基于 HTML5 History API

 */

ReactDOM.render(

    <BrowserRouter>

        <App />

    </BrowserRouter>,

    document.getElementById('root')

);

// If you want your app to work offline and load faster, you can change

// unregister() to register() below. Note this comes with some pitfalls.

// Learn more about service workers: https://bit.ly/CRA-PWA

serviceWorker.unregister();


home.js

import React from 'react';

import Item from '../components/Item.js';

export default class Home extends React.Component {

    constructor(props) {

        super(props);

        this.state = {

            items: this.doSort('desc')

        };

        this.sort = this.sort.bind(this);

    }

    sort(e) {

        console.log(e.target.value);

        let items = this.doSort(e.target.value);

        this.setState({

            items

        });

    }

    doSort(type = 'desc') {

        let {items} = this.props;

        return items.sort( (a, b) => {

            return 'desc' === type ? b.price - a.price : a.price - b.price;

        } );

    }

    render() {

        // console.log(this.props);

        // let {items} = this.props;

        // items = items.sort( (a, b) => {

        //     return b.price - a.price;

        // } );

        let {items} = this.state;

        return (

            <div>

                <h2>商品列表</h2>

                <select onChange={this.sort}>

                    <option value="desc">降序</option>

                    <option value="asc">升序</option>

                </select>


                <ul className="item-list">

                    <li className="head">

                        <span>名称</span>

                        <span>价格</span>

                    </li>

                    {/*<Item />*/}

                    {

                        items.map( item => <Item item={item} key={item.id} /> )

                    }

                </ul>

            </div>

        );

    }

}


about.js

import React from 'react';

export default class About extends React.Component {

    render() {

        return(

            <div>

                关于我们

            </div>

        );

    }

}


view.js

import React from 'react';

export default class View extends React.Component {

    render() {

        /**

         * 从动态路由 url 中拿到 :id 对应的内容

         *

         * 视图组件所需要的数据从何而来??????????????????

         *

         *

         * - 组件的 父子通信

         * - 通过与该组件对应的 url 传递过来

         * - 通过后端获取:在组件的一些生命周期中发送请求(ajax)

         * - 通过本地存储

         * - 全局变量

         *

         * 数据通信

         *  选择何种方式

         *      -

         */

        // console.log(this.props);

        // let {id} = this.props.match.params;

        let {items, match: {params: {id}}} = this.props;

        id = Number(id);

        let item = items.find( v => v.id === id );

        // console.log(items, id, item);

        return(

            <div>

                <h2>商品详情 - {item.name}</h2>

                <p>其它一些详情信息...</p>

            </div>

        );

    }

}


items.js

import React from "react";

import {Link} from "react-router-dom";

export default class Item extends React.Component{

    render() {

        let {item} = this.props;

        return(

            <li>

                <span>

                    <Link to={"/view/" + item.id}>{item.name}</Link>

                </span>

                <span>¥ {(item.price / 100).toFixed(2)}</span>

            </li>

        );

    }

}

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,530评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,403评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,120评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,770评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,758评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,649评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,021评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,675评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,931评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,751评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,410评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,004评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,969评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,042评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,493评论 2 343

推荐阅读更多精彩内容