布局
移动端 flexbox 布局
div{
display: flex;
justify-content: space-around;
align-items: center;
li{
text-align:center;
a{
color:white;
text-decoration: none;
}
.router-link-exact-active{
color: green !important;
}
}
}
在 React 中,如果想使用 SCSS,那么需要先安装 node-sass,重启服务可以直接运行(无需修改配置页)。
iscroll
// yarn add iscroll
import IScroll from 'iscroll';
componentDidMount(){
document.getElementsByClassName('box')[0].addEventListener('touchmove', function(e){
e.preventDefault()
});
// window.$('.box').on('touchmove', e=>e.preventDefault())
setTimeout(()=>{
new IScroll('.box')
}, 0)
}
public/index.html 通过 script 标签引入 zepto.js 后,可以使用 $ 对象。(如果是嵌套路由,刷新该页面,因为spa原因,引入的zepto会识别成index.html,所以会报错)
zepto 的作用和 jquery 一样,可以理解成移动版的 jq。
.box{
flex: 1;
overflow: hidden;
>ul{
background: yellow;
}
}
路由
SPA 单页面应用开发(重点)
SPA 的优势:因为是把页面都合并到一起,所以路由切换时,实际上是在当前页面切换显示,所以不会因网络问题造成页面卡顿、白屏。
SPA 的不足:合并后的文件体积特别的大,所以第一次打开页面时,比较慢。(解决方法是用按需加载)
下载路由
yarn add react-router-dom
# or
npm install react-router-dom -S
react-router-dom是第四代路由,对应的react16;react-router是第三代路由,对应的react15。
配置路由
在 React 中,没有所谓的路由规则页面,只需要把路由看作组件即可。
创建文件 /components/Router.js:
BrowserRouter 组件看作是路由外壳,所有的路由切换操作都在里面完成。
解析jsx的前提是必须引入react
import { BrowserRouter, Route } from 'react-router-dom'
const BasicRoute = ()=>{
return (
<BrowserRouter>
<div>只能有1个子节点</div>
</BrowserRouter>
)
}
export default BasicRoute
在主入口 /main.js 中渲染路由组件:
import Router from './components/Router.js'
ReactDOM.render(<Router />, document.getElementById('root'))
路由组件
HashRouter
HashRouter, 外壳,浏览器地址栏中使用#标记来描述网址
BrowserRouter
BrowserRouter, 外壳,浏览器地址栏中使用斜杠及文件名来描述网址
MemoryRouter
MemoryRouter, 外壳,浏览器地址栏中url无变化
Route
React中的路由为包容性路由,而Vue中的路由为排他性路由。
包容性路由其实指模糊匹配,比如我们定义规则/,访问/about,包容性路由会认为他俩是匹配的。
Route, 每一条路由规则,通常为:
<Route exact path='/' component={Index}></Route>
不要在 Route 的双标签中加空格或其他内容
exact属性表示绝对匹配(精准匹配)
Switch
Switch, 一个url,有可能匹配多个路由规则,使用Switch后,只渲染第一个匹配组件。
<Switch>
<Route path='/' component={Index} />
<Route path='/about' component={About} />
</Switch>
Link
Link, 其实就是a标签
<Link to="/inbox" replace></Link>
<Link to={{pathname:'/inbox'}}></Link>
<Link replace={{pathname:'/inbox'}}></Link>
NavLink
NavLink, 也是a标签,会自动在a标签添加class属性。
默认的class值为active,可以通过activeClassName属性修改。
<NavLink exact activeClassName="active"></NavLink>
Prompt
Prompt, 询问对话框
<Prompt when={true} message="您确定要离开当前页面吗?" />
比如在某组件中使用Prompt,那么路由离开这个组件时,触发提示。
Redirect
Redirect, 重定向
比如在某组件中
<Redirect to='/inbox' />
表示访问这个组件时,跳转到to对应的页面。
或者在Switch中根据用户的访问来决定匹配哪个重定向
<Switch>
<Redirect exact strict from='/Mine/' to='/a' />
<Redirect from='/Mine/Login' to='/b' />
</Switch>
exact 表示精准的;例如访问 /Mine/Login 时,如果没有exact,则匹配第一个
strict 表示是否匹配结尾的/;例如访问/Mine 时,如果有strict,那么找不到匹配
嵌套路由
Router.js 父层路由:
<Route path='/about' component={About}></Route>
注意:嵌套路由外层不能有exact,否则刷新时子层匹配不到组件
About.js 子层路由:
<Link to="/about/comp1">comp1</Link>
<Link to="/about/comp2">comp2</Link>
<Route exact path="/about/comp1" component={Comp1} />
<Route exact path="/about/comp2" component={Comp2} />
路由中数据的传递
从一个页面,把数据传递给另一个页面的方法。
query数据
a 页面的链接(链接中含有要传递给b页面的数据)
不建议使用,因为获取到的数据是将多个query连在一起的字符串。
<Link to="/b?x=1&y=2">b页面</Link>
b 页面的接收(接收a页面传递过来的数据)
this.props.location
解决query字符串转换为js对象的方案:
import querystring from 'querystring';
console.log(querystring.parse(this.props.location.search.substring(1)))
也可以把链接地址由字符串改为js对象
不建议使用,因为刷新页面时,数据无保存。
<Link to={{pathname:'/b',query:{x:1,y:2}}}>b页面</Link>
b 页面
this.props.location.query
state数据
刷新页面时,数据有保存,所以建议用此方法。
<Link to={{pathname:'/b',state:{x:1,y:2}}}>b页面</Link>
b 页面
this.props.location.state
params数据
链接
<Link to={{pathname:'/about/comp2/3/4'}}></Link>
路由出口(如果路由规则匹配,则把Comp2组件渲染到这个位置)
<Route path="/about/comp2/:a/:b" component={Comp2}></Route>
在 Comp2 组件中接收 params 数据
this.props.match.params
钩子函数
我们学的是 react-router-dom 这是第四代路由,网上的教程多是 react-router 这是第三代路由。
第三代路由中有 onEnter onUpdate onLeave 方法,而第四代路由中,这些方法都去掉了,直接使用:
- componentDidMount 或 componentWillMount 代替 onEnter
- componentDidUpdate 或 componentWillUpdate 代替 onUpdate
- componentWillUnmount 代替 onLeave
编程式导航
必须在后代路由组件中使用
路由组件:使用 Route 渲染出来的组件,才具有 history 属性。
this.props.history.push({pathname:'/abc'})
// or
this.props.history.replace({pathname:'/mine'})
// or
this.props.history.go(-1)
如果不是路由组件,则history不存在,那是否意味着非路由组件就不能用编程式导航?
高阶组件
高阶组件(Higher-Order Components)其实就是一个函数,该函数的作用就是将原始组件进行一些扩充,提供了一些额外的能力。
withRouter 让普通组件 Mine 具有 history 属性。
import { withRouter } from 'react-router-dom'
import Mine from './mine'
export default withRouter(Mine)
普通组件 Mine 就可以使用 history 属性了
this.props.history.push({pathname:'/abc'})
过渡动画
在 React 项目中实现动画效果
引入 animate
<link href="https://cdn.bootcss.com/animate.css/3.7.0/animate.min.css" rel="stylesheet" />
下载过渡模块
yarn add react-transition-group
# or
npm install react-transition-group -S
使用过渡模块
import {CSSTransition, TransitionGroup} from 'react-transition-group';
react-transition-group 提供了三个子组件,Transition 和 CSSTransition 是单节点动画;TransitionGroup 是多节点动画。Transition 是使用 js 的形式写动画,所以项目中通常都使用 CSSTransition,表示用 CSS 形式写动画。
Transition官方说明:https://reactcommunity.org/react-transition-group/transition
constructor(){
this.state = {
showBox:true
}
}
toggleBox(){
this.setState({
showBox: !this.state.showBox
})
}
render(){
return (
<div>
<button onClick={this.toggleBox}>切换</button>
<CSSTransition
in={this.state.showBox}
timeout={3000}
classNames={{
enterActive:'animated fadeIn',
exit:'animated fadeOut',
exitDone:'animated fadeOut'
}}
onEnter={function(){}}
onExited={function(){}}
unmountOnExit={true}
>
<div>
这个元素在进入及离开时,具有动画效果。<br />
in属性为true时,表示进入,反之为离开。
</div>
</CSSTransition>
</div>
)
}
in
in 属性决定样式为进入还是离开
timeout
指多长时间完成动画。
动画的执行时长取决于css中的transition设置,而这个timeout指到达这个时间点后,className和钩子函数会被触发。
classNames
classNames 属性
classNames={{
enter:'x',
enterActive:'y',
enterDone:'z',
exit:'a',
exitActive:'b',
exitDone:'c'
}}
或者
classNames="menu3"
需要自己定义css
.menu3-enter{ left: 10px; transition: all 1s; }
.menu3-enter-active{ left: 200px; }
.menu3-enter-done{ left: 200px; }
unmountOnExit
unmountOnExit={true}
exit后,是否删除元素,默认不删除。
钩子函数
动画效果执行到某个阶段的时候,自动触发的函数。
- onEnter
- onEntering
- onEntered
- onExit
- onExiting
- onExited
classNames={{
exit:'a',
exitActive:'b',
exitDone:'c'
}}
onExit={function(){console.log('onExit')}}
onExiting={function(){console.log('onExiting')}}
onExited={function(){console.log('onExited')}}
onEnter={function(){console.log('onEnter')}}
onEntering={function(){console.log('onEntering')}}
onEntered={function(){console.log('onEntered')}}
举例:a样式添加上时,触发onExit;b样式添加上时,触发onExiting;c样式添加上时,触发onExited
Group动画
通过数据的添加和删除来决定动画的进出效果,所以在组动画中,CSSTransition组件中不需要写in属性。
<TransitionGroup>
{this.props.todos.map((item, ind)=>(
<CSSTransition
key={ind}
timeout={500}
classNames={{enterActive:'animated fadeIn'}}
>
<li> {item} </li>
</CSSTransition>
))}
</TransitionGroup>
网友评论