一,父子通信
通信方法
1.父传子是通过属性 , 子传父是通过方法,回调函数
子传父
import React, { Component } from 'react'
class App extends Component {
render() {
return <div>1
<Child onMyEvent={() => {
console.log('defined by app')
}}></Child>
</div>
}
}
class Child extends Component {
state = {
childname: 'childname-111111'
}
render() {
console.log(this.props.onMyEvent)
return <div>child
<button onClick={() => {
this.props.onMyEvent()
}}>子传父</button>
</div>
}
}
export default App
案例,在Navbar中点击按钮,控制Sidebar隐藏显示,通过回调函数调用onEvent事件。
import React, { Component } from 'react'
class App extends Component {
state = {
isShow: false
}
render() {
return <div>app
<Navbar onEvent={this.handleClick}></Navbar>
{
this.state.isShow ? <Sidebar></Sidebar> : null
}
{/* <Sidebar></Sidebar> */}
</div >
}
handleClick = () => {
this.setState({
isShow: !this.state.isShow
})
}
}
var Navbar = ({ onEvent }) => {
console.log(onEvent)
return <div>
navbar
<button onClick={() => {
onEvent()
}}> click</button >
</div>
}
var Sidebar = () => {
return <div>
Sidebar
</div>
}
export default App
var Navbar = ({ onEvent }) => {
console.log(onEvent)
return <div>
navbar
<button onClick={() => {
onEvent()
}}> click</button >
</div>
}
//可以改写成
var Navbar = ({ onEvent }) => <div>
Navbar
<button onClick={onEvent}></button>
</div>
2.ref标记,父组件拿到子组件的引用,从而调用子组件的方法
在父组件中清除子组件的input输入框的value值(了解即可,不提倡)
render() {
return <div>
App
<Child ref="mychild"></Child>
<button onClick={() => {
this.refs.mychild.mymethod('app')
}}>click</button>
</div>
}
二,非父子通信
1.状态提升(中间人模式)
2.发布订阅模式
3.context状态树传参
import React, { Component } from 'react'
const Store = {
list: [],
subscribe(callback) {
this.list.push(callback)
},
publish(data) {
for (var i in this.list) {
this.list[i](data)
}
}
}
class App extends Component {
render() {
return <div>
App
<Child1></Child1>
<Child2></Child2>
</div>
}
}
class Child1 extends Component {
render() {
return <div>
Child1 ---- 发布者
<button onClick={() => {
console.log('发布')
Store.publish('child1发布')
}}>发布</button>
</div>
}
}
class Child2 extends Component {
componentDidMount() {
console.log('ajax,监听事件')
Store.subscribe(this.mycallback)
}
mycallback(data) {
console.log('订阅者:我订阅到啦~~~~~', data)
}
render() {
return <div>
Child2 ---- 订阅者
<button onClick={() => {
console.log('订阅')
}}>订阅</button>
<Child2A></Child2A>
</div>
}
}
class Child2A extends Component {
componentDidMount() {
console.log('ajax,监听事件')
Store.subscribe(this.mycallback)
}
mycallback(data) {
console.log('订阅者2A(订阅者2的孩子):我订阅到啦~~~~~', data)
}
render() {
return <div>
Child2A --- Child2 的孩子
</div>
}
}
export default App
context
import React, { Component } from 'react'
const GlobalContext = React.createContext()
class App extends Component {
state = {
number: 100
}
render() {
return <GlobalContext.Provider value={
{
call: '打电话',
sms: '短信服务' + this.state.number,
changesms: () => {
console.log('change sms')
this.setState({
number: 20000
})
}
}
}>
<div>
App
<Child1></Child1>
<Child2></Child2>
</div>
</GlobalContext.Provider>
}
}
class Child1 extends Component {
render() {
return <GlobalContext.Consumer>
{
(context) => <div>child1-- {context.call}
<button onClick={() => {
context.changesms()
}}>click</button>
</div>
}
</GlobalContext.Consumer>
}
}
export default App
三,插槽
{this.props.children}
import React, { Component } from 'react'
import Swiper from 'swiper'
import "swiper/swiper-bundle.min.css"
class App extends Component {
state = {
datalist: []
}
render() {
return <div>app
<button onClick={() => {
this.setState({
datalist: ['111', '222', '333']
})
}}>click</button>
<SwiperA key={this.state.datalist.length}>
{this.state.datalist.map(item =>
<div class="swiper-slide" key={item}>{item}</div>
)}
</SwiperA>
</div>
}
}
class SwiperA extends Component {
render() {
return <div className="swiper-container">
<div className="swiper-wrapper">
{this.props.children}
</div>
</div>
}
componentDidMount() {
new Swiper(".swiper-container")
}
}
export default App
四,动态组件
import React, { Component } from 'react'
export default class App extends Component {
state = {
current: Home
}
render() {
return <div>
<ul>
<li onClick={() => this.handleClick(Home)}>home</li>
<li onClick={() => this.handleClick(List)}>list</li>
<li onClick={() => this.handleClick(Shopcar)}>shopcar</li>
</ul>
<Dcomponent component={this.state.current}></Dcomponent>
</div>
}
handleClick(data) {
this.setState({
current: data
})
}
}
class Dcomponent extends Component {
render() {
console.log(this.props.component)//组件
var MyComponent = this.props.component
return <div>
<MyComponent></MyComponent>
</div>
}
}
function Home() {
return <div>home</div>
}
function List() {
return <div>List</div>
}
function Shopcar() {
return <div>Shopcar</div>
}
五,路由
路由是根据不同的url地址展示不同的内容或页面
cnpm install react-router-dom
1.声明式导航,重定向
route.js
import React, { Component } from 'react'
import { HashRouter, Route, Redirect, Switch } from 'react-router-dom'
import App from '../App'
import Film from '../Views/Film/Film'
import Center from '../Views/Center/Center'
import Cinema from '../Views/Cinema/Cinema'
const router = <HashRouter>
<App>
<switch>
<Route path="/film" component={Film}></Route>
<Route path="/center" component={Center}></Route>
<Route path="/cinema" component={Cinema}></Route>
<Redirect from="/" to="/film" exact></Redirect>
<Redirect to="/error"></Redirect>
</switch>
</App>
</HashRouter>
export default router
Tabbar.js
NavLink
import React, { Component } from 'react'
import { Link, NavLink } from 'react-router-dom'
import './tabbar.css'
export default class Tabbar extends Component {
render() {
return (
<nav>
<ul>
<li><NavLink to="/film" activeClassName="active">电影</NavLink></li>
<li><NavLink to="/cinema" activeClassName="active">影院</NavLink></li>
<li><NavLink to="/center" activeClassName="active">个人中心</NavLink></li>
</ul>
</nav>
)
}
}
2.嵌套路由
Film.js中留好插槽 {this.props.children}
route.js
<App>
<Switch>
<Route path="/film" render={() =>
<Film>
<Switch>
<Route path="/film/commingSoon" component={CommingSoon}></Route>
<Route path="/film/nowPlaying" component={NowPlaying}></Route>
<Redirect from="/film" to="/film/commingSoon"></Redirect>
</Switch>
</Film>}
></Route>
<Route path="/center" component={Center}></Route>
<Route path="/cinema" component={Cinema}></Route>
<Redirect from="/" to="/film" exact></Redirect>
<Redirect to="/error"></Redirect>
</Switch>
</App>
3.动态路由
componentDidMount(){
console.log(this.props.match.params.myid)
}
handleClick = (id) => {
console.log(this.props)
this.props.history.push(`/detail/${id}`)
}
4.路由拦截
<Route path="/center" render={() =>
localStorage.getItem('token') ? <Center></Center> : <Redirect to="/login"></Redirect>
}></Route>
5.withRouter 高阶函数,高阶组件
HOC— High Order Component高阶组件
import React, { Component } from 'react'
import { withRouter } from 'react-router'
class FilmItem extends Component {
render() {
let { item } = this.props
return (
<div>
<li onClick={() => this.handleClick(item)}>film item--- {item}</li>
<WrapChild><Child> </Child></WrapChild>
</div>
)
}
handleClick = (id) => {
console.log(11)
this.props.history.push(`/detail/${id}`)
}
}
export default withRouter(FilmItem)
var Child = (props) => <div>child --{props.name}</div>
var WrapChild = withShirley(Child)
function withShirley(MyComponent) {
return class WithShirleyComponent extends Component {
render() {
return <div>
我是包装组件,传进来的组件 , 成为我的孩子组件
<MyComponent name="111"></MyComponent>
</div>
}
}
}