1、refs 参照
this.refs —> 对象,存放的是组建中使用ref属性,并且属性值为字符串的,将node节点保存到refs中。
DOM对象
event.target 可以获取
挂载在组件上
//子组件
import React from 'react;
class MyRefs extends React.Component{
constructor(props){
super(props);
this.state = {};
}
//willMount willUpdate将被废弃
componentDidMount(){
//保存该组件内有ref属性,并且属性值为字符串的元素
console.log(this.refs);//
}
render(){
return (
<div>
<h3 ref="hello">hello</h3>
<h3 ref="world">world</h3>
</div>
);
}
}
export default MyRefs;
//父组件
import React from 'react';
import './App.css';
import MyRefs from './components/1-MyRefs';
// console.log(MyRefs); //只是一个导入的东西不完整
// console.log(MyRefs.state); //undefined 拿不到导入的子组件的state,子组件的state只允许在子组件内部访问
class App extends React.Component {
componentDidMount() {
console.log(this.refs);
console.log(this.refs.myrefs); //组件实例
console.log(this.refs.myrefs === MyRefs); //false
console.log(this.refs.myrefs.state); //msg
//父组件通过refs来修改子组件的state中的值的方法
//this.setState({},()=>{}); 第一个参数要修改的内容,第二个参数是一个回调函数,当页面渲染结束触发的函数
this.refs.myrefs.setState({ msg: 'hello1111' }, () => {
console.log(this.refs.myrefs.state.msg);
});
}
render() {
return (
<div>
<MyRefs ref="myrefs"></MyRefs>
</div>
);
}
}
export default App;
2、父组件修改子组件中的state中的数据的方法
思路:如果父组件中拿到子组件的实例,就可以通过子组件的实例调用setState去更改子组件state的数据。
子组件改父组件state数据:需要父组件传递修改自己state的函数给子组件调用;
父组件:
import React,{Component} from 'react';
calss Pc extends Component{
constructor(props){
super(props);
this.state = {
parentMsg:'parentMsg'
};
}
handle = ()=>{
//获取子组件的实例对象
const myc = this.refs.myc;
console.log(myc.state.msg);
myc.setState({
msg:'hello'
})
}
//更改父组件的state数据
changeParentState = () =>{
this.setState({
parentMsg:'parentHello'
})
}
render(){
return (
<div>
<button onclick={this.handle}>点击更改子组件中的state中的msg</button>
<MyC ref="myc" parentMsg={this.state.parentMsg} changeParentState={this.changeParentState}></MyC>
</div>
)
}
}
export default Pc;
子组件:
import React,{Component} from 'react';
class MyC extends Component{
constructor(props){
super(props);
this.state = {
msg:'msg';
};
}
render(){
return (
<div>
<h3>{this.state.msg}</h3>
<h2>接收父组件中的数据:{this.props.parentMsg}</h2>
<button onClick={this.props.changeParengtState}>更改父组件中的数据</button>
</div>
);
}
}
export default MyC;
3、ref值为回调函数:在组件被加载或卸载的时候会调用回调函数
<div ref={(node)=>{console.log(node,'-----')}}>ref值为回调函数</div>
4、JSX中写style
import React,{Component} from 'react';
//引入外部样式,这里可以写sass样式
import './Style.css';
class Style extends Component{
//
let btnStyle = {
backgeroundColor:'teal',
width:100,
border:'none',
fontSize:30
};
render(){
return (
<div className="Style">
<span style={{color:'red',fontSize:12,}}>
hello
</span>
<button style={btnStyle}></button>
<h3></h3>
</div>
)
}
}
5、双向数据绑定
input text
输入框中的内容发生改变的视乎,数据模型中预支对应的数据发生更改。
数据模型中的数据发生更改的时候,输入框中的内容发生改变。
import React,{Component} from 'react';
class MyFrom extends Component{
constructor(props){
super(props);
this.state = {
inputValue :'inputValue'
};
}
render(){
retun (
<div>
<form>
用户名:
<input value={this.state.inputValue} onChange={this.changeHandle} type="text" />
</form>
</div>
)
}
}
export default MyForm;
//多种表单控件的双向数据绑定,state
//在当前组件中有很多数据,其中有一个数据存放的是模态框表单的数据
import React,{Component} from 'react';
class MyForm extends Component{
constructor(props){
super(props);
this.state = {
//页面显示男,女,传递后台male,female
genders:[{
name:'男',
value:'male'
},{
name:'女',
value:'female'
}],
//地址
address:[{
name:'江苏',
value:'jiangsu'
},{
name:'江西',
value:'jiangxi'
},{
name:'山西',
value:'shanxi'
}],
hobby:[{
name:'游泳',
value:'swimming'
},{
name:'跳舞',
value:'dancing'
},{
name:'阅读',
value:'readding'
}],
msg:'注册页面',
form:{
username:'',
age:'',
gender:'',
address:'',
desc:'',
//用户选中的复选框的数据
hibbies:[]
}
};
}
//change事件处理程序
inputChange = (attr,e)=>{
//先获取到副本form,修改副本中的username,再设置到state的form上
//方法一
//let form = Object.assign({},this.state.form);
//form[attr] = e.target.value;
//this.setState({
//form
//})
//方法二
this.setState({
form:{
...this.state.form,
[arrr]:e.target.value
}
});
}
toSubmit = (e)=>{
console.log(this.state.form);
}
radioChange = (e)=>{
let form = Object.assign({},this.state.form);
form.gender =
}
checkboxChange = (e)=>{
//如果数组中没有它的值,添加,否则,删除
let value = e.target.value;
let hobbies = [...this.state.form.hobbies];
if(hobbies.includes(value)){
//执行移除
//找到当前元素的索引,然后通过索引删除
let index = hobbies.indexOf(value);
hobbies.splice(index,1);
}else{
//执行添加
hobbies.push(value);
}
this.setState({
form:{
...this.state.form,
hobbies
}
},()=>{
console.log(this.state.form.hobbies);
})
}
render(){
//const form = this.state.form;将form解构出来,方便书写
const {form} = this.state;
return (
<div className="MyForm" style={{padding:20}}>
<h3>{this.statemsg}</h3>
<form action="">
用户名:<input type="text" value={form.username} onChange={this.inputChange.bind(this,'username')} /><br/>
年龄:<input type="number" value={form.age} onChange={this.inputChange.bind(this,'age')} /><br />
性别:{
this.state.genders.map((item,index)=>{
return (
<lable htmlFor="" key={index}>
<input type="radio" onChange={this.state.inputChange.bind(this,'gender')} value={item.value} checked={form.gender == item.value? true: flase} />{item.name}
</lable>
)
})
}
地址:<select value={form.address} onChange={this.inputChange.bind(this,'address')} name="" id="">
<option value="">请选择</option>
{
this.state.address.map((item,index)=>{
<option value={item.value} key={index}>{item.name}</option>
});
}
</select><br/>
描述:<textarea onChange={this.state.inputChange.bind(this,'desc')} value={form.desc} name="" id="" cols="30" rows="10"></textarea>
爱好:{
this.state.hobby.map((item,index)=>{
return(
<label htmlFor={item.value} key={index}>
<input id={item.value} type="checkbox" value={item.value} checked={form.hobbies.includes(item.value)} onChange={this.checkboxChange}/>{item.name}
</label>
)
});
}
</form>
<button onClick={this.toSubmit}>提交</button>
</div>
);
}
}
5、css模块化导入与使用
方法一、配置WbePack模块化导入css
1、执行 yarn eject 或 cnpm run eject 命令,在新项目创建好之后,将webPack配置文件暴露出来;遇到问题输入y即可;
2、找到 config-> webpack.config.js 文件,将438,439行的
modules:true,//开启css模块化
getLocalIdent:getCSSModuleLocalIdent,
这两行复制到上一个use的最后一行(即,在检测css的地方),此时在导入css时就是以模块的形式导入
3、运行项目
4、src目录下新建文件夹components,之下新建TestCss.js和TestCss.css(注意:css文件不能以数字开头,会导致样式文件无效)
5、在js文件下
import React,{Component} from 'react';
//注意这个地方引入css文件跟以往有所区别,css模块化处理之后,将不再直接导入运行,而是直接导入一个对象;
import style form './TestCss.css'
class TestCss extends Component{
render(){
return (
<div>
{/*注意,这里在使用的时候也有变化,要从对象.属性名的形式调用*/}
<span className={style.one}>hello</span>
<span id={style.two}>world</span>
</div>
)
}
}
export default TestCss;
在css文件下
.one{
color:red;
}
#two{
color:green;
}
方法二:在react项目中使用Sass(推荐)
以.sass和.scss结尾的文件都是Sass文件,.scss结尾的文件可以用css嵌套写
1、安装sass环境,执行命令
yarn add node-sass
2、运行项目
3、src目录下新建文件夹components,之下新建TestSass.js和TestSass.scss
4、在js文件下
import React,{Component} from 'react';
import './TestSass.scss';
class TestSass extends Component{
render(){
return (
<div className="TestSass">
<span className={style.one}>hello</span>
<span>world</span>
</div>
)
}
}
export default TestSass;
在scss文件中
.TestSass{
span{
color:red;
}
span:last-child{
color:blue;
}
.one{
font-size:20px;
}
}
5、路由
hash路由
localhost:3000/#/student
浏览器路由
localhost:3000/student
实现选项卡、导航的切换
import React,{Component} form 'react';
//导入组件
import Student form './Student';
import Child form './Index';
import Teacher form './Teacher';
import Course form './Course';
class MyTab extends Component{
constructor(props){
super(props);
this.state = {
CurrentCom:Index
}
}
//点击切换
changeTab = (component)=>{
this.setState({
CurrentCom : component
})
}
render(){
//CurrentCom 就是某个组件,解构之后可以用标签展示在页面上
let {CurrentCom} = this.state;
return (
<div>
<nav>
<button onClick={this.changeTab.bind(this,Index)}>首页</button>
<button onClick={this.changeTab.bind(this,Student)}>学生管理</button>
<button onClick={this.changeTab.bind(this,Teacher)}>教师管理</button>
<button onClick={this.changeTab.bind(this,Course)}>课程管理</button>
</nav>
<div>
<CurrentCom></CurrentCom>
</div>
</div>
)
}
}
准备好 首页,学生管理,教师管理,课程管理 四个组件,分别导出。
在项目中引入路由
1、在项目中安装react-rout-dom插件。执行命令 yarn add react-router-dom
2、启动项目
3、src目录下新建文件夹components,之下新建MyRoute.js
//yarn add react-router-dom
import React,{Component} from 'react';
import {BrowserRouter,HashRouter,Switch,Link,Route,navLink,Redirect} from 'react-route-dom';
//引入组件
import Student form './Student';
import Child form './Index';
import Teacher form './Teacher';
import Course form './Course';
import './MyRoute.scss'
class MyRoute extends Component{
render(){
return (
//推荐使用<HashRouter></HashRouter>写路由
<BrowserRouter>
<nav>
//可以用 <navLink> 设置选中的样式,cativeClassName处于活动状态时的样式,exact完全匹配
<navLink exact cativeClassName="navActive" to="/">首页</navLink>
<Link exact to="/student">学生管理</Link>
<Link exact to="/course">课程管理</Link>
<Link exact to="/room">教室管理</Link>
<Link exact to="/teacher">教师管理</Link>
</nav>
<div>
{/*展示的组件*/}
<Switch>
<!--重定向 -->
<Redirect from="/" to="/student"></Redirect>
<!--exact 完全匹配路由-->
<Route exact path="/" component={Index}></Route>
<Route path="/student" component={student}></Route>
<Route path="/course" component={course}></Route>
<Route path="/room" component={room}></Route>
{/*使用render可以方便的进行内联渲染和包装,而无需进行上下文解释的不必要的组件重装*/}
<Route path="/teacher" render={()=>{return <div>hello</div>;}}></Route>
</Switch>
</div>
</BrowsRouter>
)
}
}
export default MyRoute;
MyRoute.scss
.navActive{
color:teal;
}
7、API跳转
this.props.history.push(’/content’)
//跳转传递参数
this.props.history.push({
pathname:’/content’,
state:{
name:‘zhangsan’,
age:12
}
})
//接收传递的参数
componentDidMount(){
//api传参,参数存放的位置
console.log(this.props.location);
//查询字符串参数的获取
console.log(this.props.location.search);
//获取动态路由的参数
console.log(this.props.match);
}
8、url传参
//使用动态路由
<Route path='/course/:id' component={Course}></Route>
<NavLink activeClassName='navActive' to='/course/4'>课程管理</NavLink>
//参数获取
this.props.match.params.id
9、查询字符串传参
/studentDetails?name=zhangsan
参数获取:通过 this.props.location.search来获取参数
10、其他跳转
<Link to={{
pathname:'/courses',//传递的pathname
serach:'?sort=name',//传递的URL参数
}} />
//在courese获取参数
componentDidMount(){
//接收其他组件传递的数据
console.log(this.props.location);
}
<a href="#/student">a标签跳转</a>
总结:
路由跳转
1. API跳转
this.props.history.push(’/course’)
2.NavLink
</>
3.Link
4.a
路由传参
API路由传参
this.props.history.push({
pathname:’’,
state:{
test:‘test’,
obj:{}
},
test:’’
})
获取
this.props.location.test
this.props.location.state
查询字符串传参
/course?name=zhangsan
获取
this.props.location.search
动态路由传参
先配置
<Route path="/course/:test component={Course}>
跳转四种方法都可以,/后面带任何东西
/course/hello
获取
this.props.match.params.test