react基础(不包含脚手架)

什么是React

一个用于构建用户界面的javaScript库
一个将数据渲染为HTML视图的开源Javascript库

特点

1.采用组件化模式,声明式编码,提高开发效率,组件复用率
2.使用虚拟DOM,尽量减少与真实DOM交互

第一个代码

<!DOCTYPE html>
<html>
<head>
	<meta charset="utf-8" />
	<title>react</title>
	<!-- 核心库 全局多了React -->
	<script type="text/javascript" src="./react.development.js"></script>
	<!-- 支持react操作dom 全局多了ReactDOM -->
	<script type="text/javascript" src="./react-dom.development.js"></script>
	<!-- babel转为js -->  
	<script type="text/javascript" src="./babel.min.js"></script>
	<!-- babel -->
	<script type="text/babel">
	// 不要加引号
		const VDOM = <h1 id='hid'>hello</h1>
		ReactDOM.render(VDOM, document.getElementById("idiv"))
	</script>
</head>
<body>
	<div id="idiv">
</body>
</html>

虚拟dom创建的两种方式

// 注意 只要创建了虚拟dom,就必须导入前两个库
/*
方法一:
	不使用babel,第三个导入的可以删掉
	只引入前两个
*/
<script type="text/javascript">
	const VDOM = React.createElement('h1', { id: 'hid' }, 'hello')
	ReactDOM.render(VDOM, document.getElementById("idiv"))
</script>
/*
方法二:
	使用babel
	灵活,多层嵌套
*/
<script type="text/babel">
// 括号可以不加
const VDOM = (<h1>
	<span>
		<p>
			你好
		</p>
	</span>
</h1>);	
ReactDOM.render(VDOM,document.getElementById('idiv'))
</script>

语法规则

js语句和js表达式

/*
会产生返回值的都算表达式,返回为空也算
	eg:
		a
		a+b
不产生值的都算语句
	eg:
		if(){}
		for(){}

*/
/*
jsx语法规则
	1. 定义虚拟dom,不要写引号
	2. 标签中混入js表达式(注意注意注意是表达式) 加{}
		eg:
			const myid = 'gcid'
			const mydata = 'gcdata'
			const VDOM = (<h1><span><p id= {myid}>{mydata}</p></span></h1>);
	3. 混入css,不需要{},直接用 
		eg:
			类名需要写className
			const VDOM = (<h1 className='myclass'><span>{mydata}</span></h1>);
	4. 内联样式使用,使用json格式,再嵌套{}
		eg:
			const VDOM = (<h1 style={{background:'aqua'}}>{mydata}</h1>);
			// 外层括号表示jsx中引用js表达式,内层括号表示使用json格式传递
			// style ={{key:value,key:value}}
	5. 虚拟dom只能有一个根标签,所有标签必须闭合
	6. 标签首字母
		若以小写开头,则直接将标签转为html同名元素,没有的话报错(不要写h5中没有的标签)
		若以大小开头,react就去渲染对应的组件,若没有定义该组件,则报错
*/

组件

组件实例的三大属性

state,props,refs

简单组件:无状态
复杂组件:有状态

函数式组件

/*
	1.首字母大写
	2.渲染时要使用闭合标签
*/
function Demo(){
	return <h2>demo组件的标签</h2>
	}
ReactDOM.render(<Demo/>,document.getElementById('idiv'))

类式组件

/*
	1. 首字母大写
	2. 必须继承React.Component
*/
class MyComponent extends React.Component{
    render() {
        return (<div>mycomponent组件的标签</div>);
    }
}
ReactDOM.render(<MyComponent/>,document.getElementById('idiv'))

state


// state 设置
constructor(props){
    super(props)
    this.state={ishot:true,wind:'大'}
}

// state 获取
// 一般用法
render(){
return <h1>今天天气很{this.state.ishot ? '炎热':'凉爽'}</h1>
}
// 进阶用法 
const {wind} = this.state
/*
	1. 传入格式为dict,可以多个属性
	2. 使用进阶用法时,{}里面的key必须在status已经存在,可以多个同时获取
*/

事件绑定

一般用法

/*
1. onClick c要大写
2. 调用时 {}
3. function 不能加(),否则是函数返回值进行赋值(未执行操作已经出结果) 
*/
function demo(){
    console.log('点击')
    }
return <h1 onClick={demo}>今天天气很{this.state.ishot ? '炎热':'凉爽'}</h1>

事件修改state

一般形式

/*
注意1 :
    为什么要有这句???
        因为在 onClick={this.changeweather} 中,并未调用changeweather方法,只是将其绑定给了onclick,当在页面中点击调用时,该方法已经脱离了weather类,即无获取到类中的state属性
    1. 等号右边先在下方查找changeweather()方法,因为是在类中定义的方法,需要this调用
    2. 为1中的方法绑定this,该this是指weather类中的this,并将其赋给一个新的function,名称为this.changeweather
    3. 2中的this.changeweather 便可获取到weather中的state,onclick中调用的方法也是2中等号左边的方法
*/
class Weather extends React.Component {
constructor(props){
    super(props)
    this.state={ishot:true,wind:'大'}
    //注意1
    this.changeweather = this.changeweather.bind(this)
    }
render(){
    const {ishot,wind} = this.state
    return <h1 onClick={this.changeweather}>今天天气很{this.state.ishot ? '炎热':'凉爽'}</h1>
    }
changeweather(){
    const ishot = this.state.ishot
    // 不能够直接修改变量,即 ishot = !ishot 是错误的,必须使用setState该方法
    // 修改格式是更新,而不是全部覆盖
    this.setState({ ishot : !ishot})
    console.log(this.state.ishot)
    }
}
/*
    constructor 调用 1次
    render 调用 1+n(状态更新次数)次
    changeweather 调用 n(点击几次,调用几次)次
*/

精简模式

/*
=> 箭头函数,没有自己的this,它会在当前所在地方的父级指定为this
    eg:
        下面箭头函数的父级为weather类,所以this为weather这个类

在类中直接写个赋值语句,相当于在类之后创建的所有的对象中,都会有此属性
*/
class Weather extends React.Component {
    state = { ishot: true, wind: '大' }
    render() {
        const { ishot, wind } = this.state
        return <h1 onClick={this.changeweather}>今天天气很{this.state.ishot ? '炎热' : '凉爽'}</h1>
    }
    // 箭头函数的父级
    changeweather = () => {
        const ishot = this.state.ishot
        this.setState({ ishot: !ishot })
    }
}   

props

一般用法

/*
    1. 渲染时可以直接设置属性, 多传不报错,少传不报错
    2. const {name,age,sex} = this.props 获取到不显示不报错
    3. 没有获取,显示,会报错
 
*/
class Person extends React.Component {
    render() {
        const {name,age,sex} = this.props
        return (
            <ul>
            <li>{name}</li>
            <li>{age}</li>
            <li>{sex}</li>
            </ul>
        )
    }
}
        ReactDOM.render(<Person name='gc' age='18' sex='男' />, document.getElementById('idiv1'))
        ReactDOM.render(<Person name='gc' age='18' sex='男' />, document.getElementById('idiv2'))
        ReactDOM.render(<Person name='gc' age='18' sex='男' />, document.getElementById('idiv3'))

props限制

// 错误示范
Person.propTypes = {
    name:React.PropTypes.string
}
/*
    直接如上写法报错,在react15以及15以前,都在维护PropTypes,react16以后,因为怕react过于庞大,所以删减了,将其放在prop-types.js文件中,想要使用,导入即可
*/
// 正确示范
<script type="text/javascript" src="./prop-types.js"></script>

// 为属性添加设置
Person.propTypes = {
    name:PropTypes.string
}

常见的属性限制
/*
    PropTypes.string  必须为字符串
    PropTypes.string.isRequired 必填
    PropTypes.number  必须为数字
    PropTypes.func  必须为函数
    
*/

// 为属性加默认值,传递的时候没有传递,自动获取
Person.defaultProps = {
     sex :'不男不女'
}

props值只可以读,不可以修改,this.props.name = 'gc' 是错误的

精简模式

/*
 Person.propTypes等一系列相当于类方法,将其放在类内部,并加上static
*/
class Person extends React.Component {
    static propTypes = {
        name:PropTypes.string.isRequired,
    }
    static defaultProps = {
        sex :'不男不女'
    }
    render() {
        const {name,age,sex} = this.props
        return (
        <ul>
            <li>{name}</li>
            <li>{age}</li>
            <li>{sex}</li>
        </ul>
        )
    }
}
ReactDOM.render(<Person  name={100} age='18'  />, document.getElementById('idiv1'))

函数式组件使用props

/*
    函数也可以使用props,此时类似于传参,props是形参名,可以随意
*/
function Person(a) {
    const { name, age, sex } = a
    return (
        <ul>
        <li>{name}</li>
        <li>{age}</li>
        <li>{sex}</li>
        </ul>
    )
}

小扩展

构造器中是否接受props,是否传递给super,取决于是否希望在构造器中通过this访问props,但一般不用

refs

字符串型(过时了)

/*
1. 个人感觉ref就像id
2. 多用箭头函数
*/
 class Demo extends React.Component {
    showData1 =()=>{
        const {input1} = this.refs;
        alert(input1.value)
        }
    showData2 =()=>{
        const {input2} = this.refs;
        alert(input2.value)
        }
    render() {
        return (
        <div>
            <input ref="input1" type="text" placeholder="点击按钮提示数据"/>
            <button ref="btn" onClick = {this.showData1}>点我提示左边数据</button>
            <input ref="input2" onBlur = {this.showData2} type="text" placeholder="失去焦点提示数据"/>
        </div>
        )
    }
}

回调形式的ref(推荐使用)

/*
    1. a代表的是当前标签
    2. (a)=>this.input2 = a 箭头函数只有一句,可以省略括号
    3. this 指的是这个类
*/
class Demo extends React.Component {
    showData1 =()=>{
        const {input1} = this;
        alert(input1.value)
    }
    showData2 =()=>{
        const {input2} = this;
        alert(input2.value)
    }
    changeweather = () => {
        const { ishot } = this.state;
        this.setState({ ishot: !ishot })
    }
    render() {
        return (
            <div>
                <input ref={ a =>{this.input1 = a;console.log(this)}} type="text" placeholder="点击按钮提示数据"/>
                <button ref="btn" onClick = {this.showData1}>点我提示左边数据</button>
                <input ref={(a)=>this.input2 = a} onBlur = {this.showData2} type="text" placeholder="失去焦点提示数据"/>
                <br/><button ref="btn1" onClick={this.changeweather}>更改天气</button>
            </div>
        )
    }
}
/*
内联方式的ref调用次数 1+2*n
    每次render都会清空上一次,所以每次都是新的function,并且赋null
*/

createRef

/*
    创建的myRef只能供一个使用,多次赋值会被覆盖
    所以想要多个使用,创建myref1,myref2……
*/
class Demo extends React.Component {
    myRef = React.createRef()
    howData1 = () => {
        console.log(this.myRef.current.value)
    }
    render() {
        return (
            <div>
                <input ref={this.myRef} type = "text" />
                <button ref="btn" onClick={this.showData1}>点我提示数据</button>
            </div>
        )
    }
}

事件处理

/*
    1. 通过onXxx属性指定事件处理函数(注意大小写)
        1). 使用的是合成事件,不是原生dom事件(大写了字母,react重新封装的)
        2). 事件委托给最外层元素
    2. event.target 得到发生事件的dom元素对象
    3. 不要过度的使用ref
    4. ref 避免:
        发生事件的元素正好是你操作的元素,可以避免(事件你自己调用,并且自己出结果,不经过其他的元素)
*/
// 可以避免
<input  onBlur={this.showData2} type="text" placeholder="失去焦点提示数据" />
// 不可以避免(button不是操作自身,而是操作input)
<input ref={a => { this.input1 = a;console.log("@",a) }} type="text" placeholder="点击按钮提示数据" />
<button ref="btn" onClick={this.showData1}>点我提示左边数据</button>

非受控组件

/*
1. `${}`,直接可以填入字符串,类似于py的format格式
2. event.preventDefault() 阻止页面跳转

*/
 class Login extends React.Component{
    mysubmit=(event)=>{
        event.preventDefault()
        const {username,password} = this;
        alert(`用户名是:${username.value},密码是:${password.value}`)
    }
    render(){
        return(
                <form onSubmit={this.mysubmit}>
                    用户名:<input ref ={c=>this.username = c} type='text'/>
                    密码:<input ref ={c=>this.password= c} type='password'/>
                    <button>登录</button>
                </form>
           )
        }
}

受控组件

/*
    输入类的组件再输入中将value维护到state中,在使用的时候直接从state中取
    没有用 ref
*/
class Login extends React.Component {
    state ={
        username:'',
        password:''
    }
    saveusername = (event) => {
        this.setState({ username: event.target.value })
    }
    savepassword = (event) => {
        this.setState({ password: event.target.value })
    }
    mysubmit = (event) => {
        event.preventDefault()
        const { username, password } = this.state;
        alert(`用户名是:${username},密码是:${password}`)
    }
    render() {
        return (
            <form onSubmit={this.mysubmit}>
                用户名:<input onBlur={this.saveusername} type='text' />
                密码:<input onChange={this.savepassword} type='password' />
                <button>登录</button>
            </form>
        )
    }
}

高阶函数

/*
    高阶函数:若一个函数符合下面2个规范的任何一个,都算
        1. 接受的参数是一个function
        2. 返回值是一个 function
    函数的柯里化: 通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
    注意:
        1. onChange={this.savedata('username')} onchege接受的是一个函数,而等式右边的返回值也是一个function
        2. {[key]:event.target.value} 可以获取多个参数 类似于mydic[key]的形式
*/
class Login extends React.Component {
    state = {
        username: '',
        password: ''
    }
    savedata = (key) => {
        return (event)=>{
            this.setState({[key]:event.target.value})
        }
    }
    mysubmit = (event) => {
        event.preventDefault()
        const { username, password } = this.state;
        alert(`用户名是:${username},密码是:${password}`)
    }
    render() {
        return (
            <form onSubmit={this.mysubmit}>
                用户名:<input onChange={this.savedata('username')} type='text' />
                密码:<input onChange={this.savedata('password')} type='password' />
                <button>登录</button>
            </form>
        )
    }
}

/*
    内联式写法
*/
savedata = (key,event) => {
    this.setState({[key]:event.target.value})
}
用户名:<input onChange={this.savedata('username')} type='text' />
密码:<input onChange={this.savedata('password')} type='password' />
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值