React基础
helloReact案例
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
// 引入react的三个包
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
// 解析jsx一定要用bable
<script type="text/babel">
//1.创建虚拟dom
// <!-- 此处不能写引号 -->
const VDOM = <h1>hello,React</h1>
//2.渲染虚拟Dom到页面
ReactDOM.render(VDOM,document.getElementById("test"))
</script>
</body>
两种创建虚拟DOM的方法
//js方法
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script >
//1.创建虚拟dom
// const VDOM = React.createElement(标签名,标签属性,标签内容)
const VDOM = React.createElement('h1',{
id:'title'},React.createElement('span',{
},"hello,React"))
//2.渲染虚拟Dom到页面
ReactDOM.render(VDOM,document.getElementById("test"))
</script>
</body>
//jsx写法
<body>
<!-- 准备好一个容器 -->
<div id="test"></div>
<script src="../js/react.development.js"></script>
<script src="../js/react-dom.development.js"></script>
<script src="../js/babel.min.js"></script>
<script type="text/babel">
//1.创建虚拟dom
// <!-- 此处不能写引号 -->
const VDOM = (
<h1 id="title">
<span>hello,React</span>
</h1>
)
//2.渲染虚拟Dom到页面
ReactDOM.render(VDOM,document.getElementById("test"))
</script>
</body>
对比:jsx创建更加的简单
虚拟DOM与真实DOM
<script type="text/babel">
//1.创建虚拟dom
// <!-- 此处不能写引号 -->
const VDOM = (
<h1 id="title">
<span>hello,React</span>
</h1>
)
//2.渲染虚拟Dom到页面
ReactDOM.render(VDOM,document.getElementById("test"))
console.log("虚拟DOM",VDOM);
const TDOM =document.getElementById("test");
console.log("真实DOM",TDOM);
/*
关于虚拟DOM:
1.本质是Object类型的对象(一般对象)
2.虚拟DOM比较轻,真实DOM比较重,因为虚拟DOM是React内部在用,无需真实DOM那么多的属性
3.虚拟DOM最终会被转化为真实DOM,呈现在页面上
*/
</script>
JSX语法
- 全称: JavaScript XMLs
- react定义的一种类似于XML的S扩展语法:JS+ XML
- 本质是React.createElernent(component, props…children)方法的语法糖e4作用:用来简化创建虚拟 DOM -
- 写法: var ele = ch1>Hello sx!e-
- 注意1:它不是字符串,也不是 HTMLFXML标签ec.注盒2:它最终产生的就是一个JS对象e
- 标签名任意: HTML标签或其它标签v
<script type="text/babel">
const myID = "Spark"
const myData = "hello,React!"
// 创建虚拟DOM
const VDOM = (
<div>
<h2 className="title" id={
myID}>
<span style={
{
fontSize: 20+"px"}}>{
myData}</span>
</h2>
<h2 className="title" id={
myID.toLocaleUpperCase}>
<span style={
{
fontSize: 20+"px"}}>{
myData}</span>
</h2>
<input type="text"></input>
<good>asdasd</good>
</div>
)
ReactDOM.render(VDOM,document.getElementById("test"))
/*
jsx语法规则
1.定义虚拟DOM时,不要写引号
2.标签中混入js表达式时候要中{}
3.样式的类名指定,不要用class,要用className
4.内联样式,要用style={
{key:value}}的形式去写
5.只有一个根标签
6.标签要闭合
7.标签首字母
(1)。若小字母开头,则将该标签转为html中同名元素,若html中无该标签对应的同名元素,则报错
(2).若大写字母开头,react就去渲染对应的组件,若组件没有定义
*/
</script>
JSX小练习
<script type="text/babel">
const data = [
{
id:1,name:'vue'},
{
id:2,name:'react'},
{
id:3,name:'angular'}
]
const VDOM = (
<div>
<h1>前端js框架列表</h1>
<ul>
{
data.map((item) =>{
return <li key={
item.id}>{
item.name}</li>
})
}
</ul>
</div>
)
ReactDOM.render(VDOM,document.getElementById("test"))
</script>
总结React中数据动态绑定和遍历
const title = '前端js框架列表'
const VDOM = (
<div>
// 数据绑定
<h1>{
title}</h1>
// 类名绑定
<h1 className='test'>{
title}</h1>
//属性绑定
<span style={
{
fontSize: 20+"px"}}><span>
<ul>
{
// 遍历数据使用map
data.map((item) =>{
return <li key={
item.id}>{
item.name}</li>
})
}
</ul>
</div>
)
React 面向组件编程
函数式组件
<script type="text/babel">
// 1.创建函数式组件
function MyComponent() {
console.log(this); //这里的this值为undefind 因为babel开启了严格模式
return <h2>我是函数定义的简单组件</h2>
}
// 2.渲染组件到页面
ReactDOM.render(<MyComponent />, document.getElementById("test"))
/*
执行了ReactDOM.render(<MyComponent />, ....之后发生了什么)
1.React解析组件标签,找到MyCompoent组件
2.发现组件是使用函数定义的,随后调用该函数,将返回的虚拟DOM转为真实DOM,随后呈现在页面中
*/
</script>
类式组件
<script type="text/babel">
//1.创建类式组件
class MyComponent extends React.Component {
render() {
// render是放在类的原型对象上,供实例使用
// 这里的this是MyCompoent的实例对象
console.log(this);
return <h2>我是用类定义的组件,适用于复杂组件</h2>
}
}
//2.渲染组件到页面
ReactDOM.render(<MyComponent></MyComponent>,document.getElementById("test"))
/*
执行了ReactDOM.render(<MyComponent />, ....之后发生了什么)
1.React解析组件标签,找到MyCompoent组件
2.发现组件是使用类定义的,随后new出来该类的实例,并通过该实例,调用到原型上的render方法
3.将render返回的虚拟DOM转为真实DOM,随后呈现在页面上
*/
</script>
组件的三大核心属性
state
完整写法
<script type="text/babel">
//创建组件
class Weather extends React.Component {
//构造器调用了几次-----一次
constructor(props) {
super(props);
// 初始化状态
this.state = {
isHost:false,wind:'微风'}
// 改变changWeather的this指向,解决方法中this指向问题
this.changeWeather = this.changeWeather.bind(this)
}
// render调用了几次 1+n次
render() {
const {
isHost,wind} = this.state;
// 给h1标题绑定一个事件,改变isHost的值
return <h1 onClick={
this.changeWeather}>今天天气很{
isHost?"热":'凉'},{
wind}</h1>
}
// changeWeather调用几次 点几次调用几次
changeWeather(){
//changeWeather在类的原型对象上
// 由于changeWeather是作为onClick的回调,所以不是通过实例调用的,是直接调用
// 类中的方法默认开启了局部的严格模式,所以changeWeather中的this为undefined
//获取与拿来isHost的值
const isHost =this.state.isHost;
// 状态不能直接更改,要借助内置的API
// 状态必须通过setState进行更新,且更新是一种合并,不是直接替换
this.setState({
isHost:!isHost});
}
}
ReactDOM.render(<Weather></Weather>,document.getElementById("test"))
</script>
简写版本
<script type="text/babel">
//创建组件
class Weather extends React.Component {
//初始化状态
state = {
isHost:false,wind:'微风'}
render() {
const {
isHost,wind} = this.state;
return <h1 onClick={
this.changeWeather}>今天天气很{
isHost?"热":'凉'},{
wind}</h1>
}
//自定义方法--要用赋值语句的形式+箭头函数
changeWeather = ()=>{
const isHost =this.state.isHost;
this.setState({
isHost:!isHost});
}
}
ReactDOM.render(<Weather></Weather>,document.getElementById("test"))
</script>
总结
组件中render方法中的 this为组件实例对象-
组件自定义的方法中 this为undefined,如何解决?
强制绑定this:通过函数对象的 bind()
箭头函数
状态数据,不能直接修改或更新
props
完整写法
<script type="text/babel">
//创建组件
class Person extends React.Component{
render(){
//props是只读的
const {
name,age,sex} = this.props;
return (
<ul>
<li>姓名: {
name}</li>
<li>性别: {
sex}</li>
<li>年龄: {
age+1}</li>
</ul>
)
}
}
// 对标签属性进行类型必要性的限制
Person.propTypes = {
name: PropTypes.string.isRequired, //限制name为字符串,且必传
sex: PropTypes.string, //限制sex为字符串
age: PropTypes.number, //限制age为number
speak: PropTypes.func //限制speak为函数
}
//指定默认标签属性值
Person.defaultProps ={
sex:'saas',
age:20
}
const p = {
name:'张三',age:18,sex:"男"}
// ReactDOM.render(< Person name = "tom" age = "18" sex = "male" />, document.getElementById("test"))
ReactDOM.render(< Person {
...p} speak = {
speak}/>, document.getElementById("test"))
function speak(){
console.log("adsadas");
}
</script>
简写方式
<script type="text/babel">
//创建组件
class Person extends React.Component{
// 对标签属性进行类型必要性的限制
static propTypes = {
name: PropTypes.string.isRequired, //限制name为字符串,且必传
sex: PropTypes.string, //限制sex为字符串
age: PropTypes.number, //限制age为number
speak: PropTypes.func //限制speak为函数
}
//指定默认标签属性值
static defaultProps ={
sex:'saas',
age:20
}
render(){
const {
name,age,sex} = this.props;
return (
<ul>
<li>姓名: {
name}</li>
<li>性别: {
sex}</li>
<li>年龄: {
age+1}</li>
</ul>
)
}
}
const p = {
name:'张三',age:18,sex:"男"}
// ReactDOM.render(< Person name = "tom" age = "18" sex = "male" />, document.getElementById("test"))
ReactDOM.render(< Person {
...p} speak = {
speak}/>, document.getElementById("test"))
function speak(){
console.log("adsadas");
}
</script>
函数式写法
<script type="text/babel">
//创建组件
function Person(props){
const {
name,age,sex} = props;
return (
<ul>
<li>姓名: {
name}</li>
<li>性别: {
sex}</li>
<li>年龄: {
age+1}</li>
</ul>
)
}
// 对标签属性进行类型必要性的限制
Person.propTypes = {
name: PropTypes.string.isRequired, //限制name为字符串,且必传
sex: PropTypes.string, //限制sex为字符串
age: PropTypes.number, //限制age为number
speak: PropTypes.func //限制speak为函数
}
//指定默认标签属性值
Person.defaultProps ={
sex:'男',
age:20
}
const p = {
name:'张三',age:18,sex:"男"}
ReactDOM.render(< Person {
...p}/>, document.getElementById("test"))
</script>
refs
字符串形式写法
问题:效率不高,不推荐使用
<script type="text/babel">
class Demo extends React.Component {
render() {
return (
<div>
<input ref="input1" type="text" placeholder="点击按钮提示数据"></input>
<button ref="button1" onClick={
this.showData}>点我提示闭合</button>
<input onBlur={
this.showData2} ref="input2" placeholder="失去焦点提示"/>
</div>
)
}
showData = ()=> {
console.log(this.refs.input1.value);
}
showData2 = ()=> {
console.log(this.refs.input2.value);
}
}
ReactDOM.render(<Demo></Demo>,document.getElementById("test"))
</script>
回调形式的ref
<script type="text/babel">
class Demo extends React.Component {
render() {
return (
<div>
<input ref={
c =>this.input1= c} type="text" placeholder="点击按钮提示数据"></input>
<button ref={
c=>this.button1 =c} onClick={
this.showData}>点我提示闭合</button>
<input onBlur={
this.showData2} ref={
c =>this.input2 = c} placeholder="失去焦点提示"/>
</div>
)
}
showData = ()=> {
console.log(this.input1.value);
}
showData2 = ()=> {
// console.log(this.input2);
}
}
ReactDOM.render(<Demo></Demo>,document.getElementById("test"))
</script>
createRef
<script type="text/babel">
class Demo extends React.Component {
//React.createRef调用后可以返回一个容器,该容器可以储存被ref标识的节点,该容器是专人专用的
myRef = React.createRef();
myRef1 = React.createRef();
render() {
return (
<div>
<input ref={
this.myRef} type="text" placeholder="点击按钮提示数据"></input>
<button onClick={
this.showData}>点我提示闭合</button>
<input onBlur={
this.showData1} ref={
this.myRef1} type="text" placeholder="点击按钮提示数据"></input>
</div>
)
}
showData = ()=> {
console.log(this.myRef.current.value);
}
showData1 = ()=>{
console.log(this.myRef1.current.value);
}
}
ReactDOM.render(<Demo></Demo>,document.getElementById("test"))
</script>
事件处理
<script type="text/babel">
class Demo extends React.Component {
/*
1.通过onXXX属性指定事件处理函数,注意大小写
a.React使用的是自定义(合成)事件,而不是使用的原生的DOM事件
b.React中的事件是通过事件委托的方式处理的(委托给组件最外层的元素)
2.通过event.target得到发生事件的DOM元素对象----不要过度使用Ref
*/
// 创建Ref容器
myRef = React.createRef();
myRef1 = React.createRef();
render() {
return (
<div>
<input ref={
this.myRef} type="text" placeholder="点击按钮提示数据"></input>
<button onClick={
this.showData}>点我提示闭合</button>
<input onBlur={
this.showData1} ref={
this.myRef1} type="text" placeholder="点击按钮提示数据"></input>
</div>
)
}
showData = ()=> {
console.log(this.myRef.current.value);
}
showData1 = (event)=>{
// console.log(this.myRef1.current.value);
console.log(event.target.value);
}
}
ReactDOM.render(<Demo></Demo>,document.getElementById("test"))
</script>
react中收集表单数据
非受控组件
<script type="text/babel">
//创建组件
class Login extends React.Component {
render(){
return (
<form onSubmit={
this.handleSubmit}>
用户名:<input type="text" ref={
c=>this.username = c} name="username" />
密码:<input type="password" ref = {
c=>this.password = c} name="password"/>
<button>登录</button>
</form>
)
}
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {
username,password} = this
console.log(username.value,password.value);
}
}
ReactDOM.render(<Login></Login>,document.getElementById("test"))
</script>
受控组件
<script type="text/babel">
//创建组件
class Login extends React.Component {
// 初始化状态
state = {
username: "",//用户名
password: ""//密码
}
render(){
return (
<form onSubmit={
this.handleSubmit}>
用户名:<input type="text" onChange={
this.saveUsername} name="username" />
密码:<input type="password" onChange= {
this.savePassword} name="password"/>
<button>登录</button>
</form>
)
}
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {
username,password} = this.state
console.log(username,password);
}
//保存用户名到状态中
saveUsername = (event)=>{
this.setState({
username:event.target.value})
}
//保存密码到状态中
savePassword = (event)=>{
this.setState({
password:event.target.value})
}
}
ReactDOM.render(<Login></Login>,document.getElementById("test"))
</script>
高阶函数与柯里化
<script type="text/babel">
//创建组件
class Login extends React.Component {
/*
高阶函数:如果一个函数符合下面2个规范中的任何一个,那么这个函数就是高阶函数
1.若A函数,接收参数是一个函数,那么A就可以称之为高阶函数
2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
常见的高阶函数有:Promise setTimeout 数组常用的方法
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
*/
render(){
return (
<form onSubmit={
this.handleSubmit}>
用户名:<input type="text" onChange={
this.saveFormData('username')} name="username" />
密码:<input type="password" onChange= {
this.saveFormData('password')} name="password"/>
<button>登录</button>
</form>
)
}
// 初始化状态
state = {
username: "",//用户名
password: ""//密码
}
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {
username,password} = this.state
console.log(username,password);
}
// 保存表单数据到状态中
saveFormData = (dataType)=>{
return (event)=>{
this.setState({
[dataType]:event.target.value});
}
}
}
ReactDOM.render(<Login></Login>,document.getElementById("test"))
</script>
不用柯里化实现
<script type="text/babel">
//创建组件
class Login extends React.Component {
/*
高阶函数:如果一个函数符合下面2个规范中的任何一个,那么这个函数就是高阶函数
1.若A函数,接收参数是一个函数,那么A就可以称之为高阶函数
2.若A函数,调用的返回值依然是一个函数,那么A就可以称之为高阶函数
常见的高阶函数有:Promise setTimeout 数组常用的方法
函数的柯里化:通过函数调用继续返回函数的方式,实现多次接收参数最后统一处理的函数编码形式
*/
render(){
return (
<form onSubmit={
this.handleSubmit}>
用户名:<input type="text" onChange={
event=>this.saveFormData('username',event)} name="username" />
密码:<input type="password" onChange= {
event=>this.saveFormData('pass',event)} name="password"/>
<button>登录</button>
</form>
)
}
// 初始化状态
state = {
username: "",//用户名
password: ""//密码
}
handleSubmit = (event)=>{
event.preventDefault() //阻止表单提交
const {
username,password} = this.state
console.log(username,password);
}
// 保存表单数据到状态中
saveFormData = (dataType,event)=>{
this.setState({
[dataType]:event.target.value});
}
}
ReactDOM.render(<Login></Login>,document.getElementById("test"))
</script>