class BoxCom extends React.Component {
constructor(props){
super(props)
}
testRef(e){
console.log('test-ref',this.refs )
}
render(){
return (
<div>
<input type="text" ref="ipt" />
<button onClick={this.testRef.bind(this)}>获取dom5button>
div>
)
}
}
ref属性可以设置为一个回调函数,这也是官方强烈推荐的用法;这个函数执行的时机为:
- 组件被挂载后,回调函数被立即执行,回调函数的参数为该组件的具体实例。
- 组件被卸载或者原有的ref属性本身发生变化时,回调也会被立即执行,此时回调函数参数为null,以确保内存泄露。
class BoxCom extends React.Component {
constructor(props){
super(props)
this.state = { }
this.inputDom = null
}
testRef(e){
console.log( 'inputDom' , this.inputDom );
console.log( 'inputDom-value' , this.inputDom.value );
}
render(){
return (
<div>
<input type="text" ref={(inputDom)=>{ this.inputDom = inputDom }} />
<button onClick={this.testRef.bind(this)}>获取dom5button>
div>
)
}
}
父组件
import React from 'react';
import PropTypes from 'prop-types'
import GrandSon from './grandSon'
class BoxCom extends React.Component {
constructor(props){
super(props)
this.state = { }
this.GrandSonDom = null
}
boxGrandSon(){
console.log( '获取子组件上的ref' , this.GrandSonDom )
console.log( '获取子组件里面的ref' , this.GrandSonDom.grandSonInput, this.GrandSonDom.grandSonInput.value )
}
render(){
return (
500} height={100} ref={(dom)=>{ this.GrandSonDom = dom }} >
)
}
}
BoxCom.propTypes = {
width: PropTypes.number
height: PropTypes.number
}
export default BoxCom;
子组件
import React from 'react';
import PropTypes from 'prop-types'
class grandSon extends React.Component {
constructor(props){
super(props)
this.grandSonInput = null
}
btnClick(){
console.log( '获取本组件内的ref' , this.grandSonInput, this.grandSonInput.value )
}
render(){
return (
<div style={{border:'3px solid red',width:this.props.width , height:this.props.height}} >
<input type="text" ref={(ipt)=>{ this.grandSonInput = ipt }} />
<button onClick={this.btnClick.bind(this)}>grandSonbutton>
div>
)
}
}
//规定props属性的值必须是数字类型
grandSon.propTypes = {
width: PropTypes.number,
height: PropTypes.number
}
export default grandSon;
import React from 'react';
import { Router, Route , IndexRoute } from 'dva/router';
import Login from './routes/Login';
import Register from './routes/Register';
import Main from './routes/Main';
import Path from './routes/path';
import Admi from './routes/member/admi';
import Technical from './routes/member/technical';
import Marketing from './routes/member/marketing';
function RouterConfig({ history }) {
return (
<Router history={history}>
<Route path="/" component={Login}>Route>
<Route path="/Register" component={Register}>Route>
<Route path="/main" component={Main} > 当路由是/main的时候会加载Main组件和Marketing组件
<IndexRoute component={Marketing} />
<Route path="/admi" component={Admi} />
<Route path="/marketing" component={Marketing} />
<Route path="/technical" component={Technical} />
Route>
Router>
);
}
export default RouterConfig;
Main.js
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'dva'
import { Link } from 'dva/router'
import './main.css';
import { Menu, Icon, Switch , Row , Col } from 'antd';
import { browserHistory } from 'react-router'
const SubMenu = Menu.SubMenu;
var ck = require('js-cookie')
class Sider extends React.Component {
state = {
theme: 'dark',
current: '1',
username:''
}
changeTheme = (value) => {
this.setState({
theme: value ? 'dark' : 'light',
});
}
handleClick = (e) => {
this.setState({
current: e.key,
});
}
componentWillMount(){
// console.log( ck.get('user') )
// var user = ck.get('user') && JSON.parse(ck.get('user'))
// if( !user ){ browserHistory.push('/'); return }
// this.setState({ username:user.name })
}
logoOut(){
// ck.remove('user')
browserHistory.push('/')
}
render() {
return (
<div style={{height:'100%',width:'100%',overflow:'hidden'}}>
<div style={{ backgroundColor:'#36485d', color:'white',height:50,fontSize:'22px',lineHeight:'50px' }}>
{this.props.children} //路由的占位符
div>
div>
);
}
}
export default connect(({ main }) => ({ main }))(Sider)
"inbox" component={Inbox}>
{/* 从 /inbox/messages/:id 跳转到 /messages/:id */}
<Redirect from="messages/:id" to="/messages/:id" />
Route>
"/" component={App}>
<IndexRedirect to="/welcome" />
<Route path="welcome" component={Welcome} />
<Route path="about" component={About} />
Route>
<Route path="/boys/:boyName" component={Boy}/>
<Link to="/boys/宋仲基">宋仲基Link>
<Route path="/country" component={country}/>
<Link to={{ pathname:'country' , query:{addr:'china'} }}>国家Link>
<Link to="/about" activeStyle={{color: 'red'}}>About</Link>
<Link to="/about" activeClassName="active">About</Link> //使用activeClassName指定当前路由的Class。
import { browserHistory } from 'react-router';
browserHistory.push('/some/path');
如果链接到根路由/,不要使用Link组件,而要使用IndexLink组件。
这是因为对于根路由来说,activeStyle和activeClassName会失效,或者说总是生效,因为/会匹配任何子路由。而IndexLink组件会使用路径的精确匹配。
<IndexLink to="/" activeClassName="active">
Home
</IndexLink>
或者
<Link to="/" activeClassName="active" onlyActiveOnIndex={true}>
Home
</Link>
方法一
import { browserHistory } from 'react-router'
handleSubmit(event) {
event.preventDefault()
const userName = event.target.elements[0].value
const repo = event.target.elements[1].value
const path = `/repos/${userName}/${repo}`
browserHistory.push(path)
},
方法二
export default React.createClass({
// ask for `router` from context
contextTypes: {
router: React.PropTypes.object
},
handleSubmit(event) {
// ...
this.context.router.push(path)
},
})
componentWillReceiveProps(arg){
console.log('即将接收props',arg); //arg的值是传入的props
}
shouldComponentUpdate( arg ){
// 需要return false或true
console.log('组件是否被更新' , arg ) //arg的值是传入的最新props
return true //true则更新组件 , false则不更新组件
}
import dva from 'dva';
import './index.css';
import { browserHistory } from 'dva/router'
// 1. Initialize
const app = dva({
history: browserHistory,
});
// 2. Plugins
// app.use({});
// 3. Model
app.model(require('./models/app'));
// 4. Router
app.router(require('./router'));
// 5. Start
app.start('#root');
import {login} from '../services/example';
import { routerRedux } from 'dva/router'
const delay = timeout => new Promise(resolve => setTimeout(resolve, timeout));
export default {
namespace: 'app',
state:
{
loginLoading:false,
num:123456
},
subscriptions: {
setup ({ dispatch }) {
},
},
effects: {
*login ({payload}, { call, put }) {
yield put({ type: 'showLoginLoading' })
yield call(delay,2000)
yield put({ type: 'hideLoginLoading' })
yield call(delay,1000)
yield put(routerRedux.push('/main'))
}},
reducers: {
add( state , { payload:value }){
console.log( 'add' , value )
return { num:value }
},
showLoginLoading (state) {
return {
loginLoading: true,
}
},
hideLoginLoading (state) {
return {
loginLoading: false,
}
},
},
}
import React from 'react'
import PropTypes from 'prop-types'
import { connect } from 'dva'
import TestCom from '../../components/test'
import BoxCom from '../../components/box'
import { request } from '../../utils/request';
// import {delay} from '../utils/request';
import { Button, Row, Form, Input } from 'antd'
const FormItem = Form.Item
const Login = ({
app,
dispatch,
form:{
getFieldDecorator,
validateFieldsAndScroll,
},
myNum
}) => {
function myClick(){
// request('/api/test',{
// method:'POST',
// headers: {
// 'Content-Type': "application/x-www-form-urlencoded; charset=UTF-8"
// },
// body:"name=tom&age=19",
// // body:{name:'jack'}
// }).then((data)=>{
// console.log('data',data)
// })
}
function testClick(e){
// console.log('testClick', this.props.location.query )
}
function routerWillLeave(){
alert('确认是否要离开')
}
function changeRedux(){
var num = app.num + 1
dispatch({
type:'app/add',
payload:num
})
console.log( 'app' , app );
}
var num = 120
return (
<div style={styles.login}>
<div style={{border:'1px solid blue'}}>
<div>{ num }div>
<div>app--{ app.num }div>
<button onClick={changeRedux.bind(this)}>reduxbutton>
div>
{/* <BoxCom width={500} height={322} app={{name:'tom'}}>BoxCom> */}
{/* <form action="post" >form> */}
div>
)
}
Login.propTypes = {
form: PropTypes.object,
app: PropTypes.object,
dispatch: PropTypes.func
}
const styles = {
login:{
width:'100%',
height:'100%',
justifyContent:'center',
alignItems:'center',
// fontSize:'25px',
// color:'red'
}
}
export default connect(({ app }) => ({ app }))(Form.create()(Login))