1.遍历一个对象
jsx 里面的 { } 提供js语境,可以执行js合法代码,也可以插值表达式
在 react 的jsx里面,如果遇到 < 当成jsx语法,如果 { 当成变量
{ userList.map((item) => {
return (
<ul key={item.id}>
<li>序号:{item.id}</li>
<li>姓名:{item.username}</li>
<li>年龄:{item.age}</li>
</ul>
);
})}
2.react中的数据类型
import React from 'react';
import ReactDOM from 'react-dom';
//1. 如果要写jsx语法,有且仅有一个根节点
//2. 习惯在根节点的外面加上一个括号。如果不加 括号, div 根节点必须写在 = 后面
let title = 'hi react'; // 在 react 的jsx里面,如果遇到 < 当成jsx语法,如果 { 当成变量
// jsx 里面的 { } 提供js语境,可以执行js合法代码,也可以插值表达式
let arr = [1, 2, 43, 4];
// jsx
let arrJsx = [<li key={1}>1</li>, <li key={2}>2</li>, <li key={3}>43</li>, <li key={4}>4</li>];
// 对象数组 二维
const userList = [
{
id: 1,
username: 'andy',
age: 23,
},
{
id: 2,
username: 'mark',
age: 24,
},
{
id: 3,
username: 'liyang',
age: 23,
}
]
let virtualDomByJsx = (
<div>
<h2>jsx语法</h2>
<p>直接在 js 语境写 html 代码</p>
<p>1. 如果js里面存在变量,如何在jsx里面使用</p>
<p>2. jsx里面的元素的属性有几个要注意 for class</p>
<hr/>
<h2>基本数据类型</h2>
<p>{title}</p>
<p>{'lorem字符串'}</p>
<p>{10 > 2 ? '真的' : '假的'}</p>
<hr/>
<h2>复合数据类型</h2>
<p>一维数组:react自动进行遍历操作</p>
{arr}
<hr/>
<ul>
{arrJsx}
</ul>
<p>二维数组:使用map转换为一维数组</p>
{/*[ ul, ul, ul ]*/}
{ userList.map((item) => {
return (
<ul key={item.id}>
<li>序号:{item.id}</li>
<li>姓名:{item.username}</li>
<li>年龄:{item.age}</li>
</ul>
);
})}
</div>
);
ReactDOM.render(
virtualDomByJsx,
document.getElementById('root')
);
3.组件的使用与事件的使用
import React from 'react';
import ReactDOM from 'react-dom';
// 导入样式 yarn eject webpack 配置弹射 webpack.config.js - less-loader
// import './assets/main.less'
// 需求:如何在 react 项目里面使用 less sass stylus
// 使用自定义的css 使用第三方的css文件 bootstrap@3.x
import './assets/main.css'
import 'bootstrap/dist/css/bootstrap.min.css';
import SecondComponent from './components/SecondComponent'
let message = '我是 index.js 里面的消息';
let version = 'v3'
let info = {
id: 1,
username:'andy',
age: 23,
email: 'gerot@173.com'
}
/**
* 思考:1. 在调用组件的时候,我们有给组件传递属性,如果用户没有传递属性,该如何处理? (设置默认值)如果传递了属性与我们事先预期的不一致该如何处理?(设置类型的约束)
* https://www.cnblogs.com/zhangxiaoshuang/p/6917589.html
*
* 思考:组件调用的时候可以使用标签的方式调用。 1. 单标签 2. 双标签(标签内部存放信息该如何处理?)
*/
//下面的number1 vstatus都是在传值
ReactDOM.render(
<SecondComponent message={message} number1={12} vstatus={version} {...info}>
Lorem ipsum dolor sit amet, consectetur adipisicing elit. Iusto, voluptates.
</SecondComponent>,
document.getElementById('root')
);
import React, { Component } from 'react'
import PropTypes from 'prop-types';
export default class SecondComponent extends Component {
static defaultProps={
message: '默认值',
}
static propTypes = {
// 实际的开发中,属性的类型是存在多种多样的,需要借助PropTypes库进行约束。
// https://www.jianshu.com/p/4b3488696288?utm_campaign=maleskine&utm_content=note&utm_medium=seo_notes&utm_source=recommendation
number1: PropTypes.number.isRequired,
}
constructor(props){
super(props);
this.state={
title: 'hi react',
}
}
clickHandler(event){
console.log('event',event);
console.log('this',this);
}
clickHandler2=(event)=>{
console.log('event',event);
console.log('this',this);
}
render() {
return (
<div id="container">
<h2>类组件-{this.props.message}</h2>
{/*在react里面,如果是要给元素设置 class,则需要将class的名称改为 className 因为 js语境下 class 是 类 关键字*/}
{/*class定义样式 style定义样式*/}
{/*react 里面的事件需要使用 on+事件类型,事件类型的首字母大写*/}
{/*回调函数就是类的方法*/}
{/*回调函数不能加括号*/}
<button onClick={this.clickHandler.bind(this)} className={ "btn btn-danger btn-lg btn-block" }>bind-this-bt按钮</button>
<button onClick={this.clickHandler2 } className={ "btn btn-danger btn-lg btn-block" }>es6-arrow-fn-bt按钮</button>
<p style={ {'fontSize': '30px', 'color': 'red'} }>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Esse, repudiandae?</p>
<div>
{/*children 属性代表是以双标签方式调用组件时候,组件内部的内容*/}
{ this.props.children }
</div>
</div>
)
}
}
4.受控表单和不受控表单
import React, { Component } from 'react';
class Form extends Component {
constructor(props){
super(props);
this.state={
message:'default'
}
}
clickHandler=(event)=>{
console.log(event);
this.setState({
message:'hadChange'
})
}
changeHandler=(event)=>{
let value=event.target.value;
this.setState({
message:value
})
}
ageHandler = () => {
console.log(this.refs);
console.log(this.age); // dom
console.log(this.age.value);
}
render() {
return (
<div>
<h2>表单处理-收集数据</h2>
<button onClick={this.clickHandler}>按钮</button>
<hr/>
用户名:
{/*react里面没有指令*/}
{/*如果表单元素的value值是收到state里面的值的控制的组件,我们称之为 受控组件。*/}
<input type="text" onChange={this.changeHandler} value={this.state.message} className="form-control"/>
<h2>表单处理-收集数据-非受控组件-ref简化写法</h2>
{/** 形参用户自定义
* function (ref) => {
* // this 代表当前的组件对象,
* this的属性值用户自定义,只要不和当前组件里面的其他的属性冲突即可。
* 该属性的属性值就是当前的dom 对象。
return this.age = ref;
// this.age = documenent.getElementById('')
* }*/}
年龄:<input type="text" ref={ref => this.age = ref} className="form-control"/>
<button onClick={this.ageHandler}>手工触发年龄校验</button>
</div>
);
}
}
export default Form;
5.生命周期
import React, { Component } from 'react';
import PropTypes from 'prop-types';
class Life extends Component {
constructor(props) {
super(props);
this.state = {
'title': 'hi react',
'userList':[]
}
console.log("1.construct",this,this.props,this.state);
}
getUserList(){
console.log(this);
let url = 'http://jsonplaceholder.typicode.com/users';
fetch(url).then(response=>{
return response.json();
}).then(data=>{
console.log(data);
this.setState({
userList: data
})
}).catch(error=>{
console.log(error);
})
}
clickHandler = () => {
console.log('clickHandler');
this.setState({
title: this.state.title + Math.random(),
})
}
// 组件还没有放置在页面上,虚拟DOM
/**
* 将来有可能不存在,建议使用 UNSAFE_componentWillMount
*/
componentWillMount() {
this.getUserList();
console.log("2.componentWillMount",this,this.props,this.state);
}
componentDidMount() {
console.log('4. componentDidMount 在页面上可以DOM操作', this, this.props, this.state);
}
// .... 上面的这些生命周期函数都是初次渲染的时候进行触发
// 还有一类是在更新的时候进行触发 (1. props 属性更新 2. state 更新)
// 组件间通信,嵌套组件 父 state--->子组件 props
componentWillReceiveProps(nextProps, nextContext) {
// 如果组件的props发生变化后,则会触发该声明周期函数
console.log('componentWillReceiveProps', nextProps);
}
/**
*
* should 请求
* 这个生命周期函数代表 是否需要进行修改,返回值 boolean
* // 如果是 true 则进行修改
*
* // false 则不会触发修改
* @param nextProps
* @param nextState
* @param nextContext
*/
shouldComponentUpdate(nextProps, nextState) {
console.log('shouldComponentUpdate', nextProps, nextState);
console.log(this.state);
return true;
}
/**
* 将要更新页面,但是页面还没有变化
* @param nextProps
* @param nextState
* @param nextContext
*/
componentWillUpdate(nextProps, nextState) {
console.log('componentWillUpdate', nextProps, nextState);
console.log(this.state);
}
/**
* 页面展示最新的状态,数据是最新的
* @param prevProps
* @param prevState
* @param snapshot
*/
componentDidUpdate(prevProps, prevState) {
console.log('componentDidUpdate', prevProps, prevState);
console.log(this.state);
}
componentWillUnmount() {
}
render() {
console.log('3. render 虚拟DOM转换为真实的DOM', this, this.props, this.state);
return (
<div>
<h2>生命周期函数-获取用户列表</h2>
{/*userList: 复合 [{}, {}]*/}
{this.state.userList.map((item, index)=>{
return (
<ul key={item.id}>
<li>序号:{item.id}</li>
<li>用户名:{item.username}</li>
</ul>
);
})}
</div>
);
}
}
Life.propTypes = {
};
export default Life;
6.父子传值
//父
import React, { Component } from 'react';
import Son from './components/Son'
class App extends Component {
constructor(props) {
super(props)
this.state = {
message:'传给子组件的值',
sonMessage:''
}
}
//定义个回调函数传给子组件
fnCallBack=(data)=>{
console.log(data);
this.setState({
sonMessage:data
})
}
render() {
return (
<div>
<h1>我是父组件</h1>
<h3>下面是子组件给父组件的值</h3>
<p>{this.state.sonMessage}</p>
<hr/>
//通过属性的方式传值
<Son message={this.state.message} fnCallBack={this.fnCallBack}></Son>
</div>
);
}
}
export default App;
子
import React, { Component } from 'react';
class Son extends Component {
constructor(props) {
super(props)
this.state = {
}
}
father=()=>{
this.props.fnCallBack('我是子组件传给父组件的值')
}
render() {
return (
<div>
<h2>我是子组件</h2>
<p>我是父组件传过来的值</p>
<p style={{color:'red'}}>{this.props.message}</p>
<button onClick={this.father}>处理子传父</button>
</div>
);
}
}
export default Son;