react入门

组件的两种实现模式:

1.函数式组件(相比较函数式性能会更好)

import React from 'react'

export default ()=>{
  return (
    <div id="app">
      <h1>hello world</h1>
    </div>
  )
}

2.class组件

// react组件(class组件)
import React, {Component} from 'react'

export default class App extends Component{
  // 如果继承了Component
  // 就必须实现render函数,这个render函数,提供了组件的dom结构
  render(){
    return (
      <div id="app">
        <h1>hello world~~~~~~~~~~</h1>
      </div>
    )
  }

}
react的指令实现(jsx语法 比较与vue指令实现方式)
v-text

只要在jsx的dom中,作用域可以访问到的变量,可以解析出来的表达式,就可以使用’{表达式}'表示

import React, {Component} from 'react'

let value1 = 'value1......';
export default class App extends Component{
  constructor(){
    super();
    this.value3 = 'value3.......';
  }
  render(){
    let value2 = 'value2........';
    return (
      <div id="app">
        <h1>hello world~~~~~~~~~~</h1>
        <p>{value1}</p>
        <p>{value2}</p>
        <p>{this.value3}</p>
      </div>
    )
  }
}
v-html

在react中没有innerHTML的概念

如果有一段html字符串,需要自己去解析成react dom对象
需要使用 dangerouslySetInnerHTML

export default class App extends Component{
  render(){
    const dom = '<span>富文本 <i>斜体</i><b>粗体</b></span>';
    const renderDom={
    	__html:dom  //必须这样的格式写
    };

    return (
      <div id="app">
        <h1>hello world~~~~~~~~~~</h1>
        {dom} //这样写不会渲染成html标签,会自动转义展示 直接展示:<div className="box">....文本
        <div dangerouslySetInnerHTML={renderDom}></div>  //这样可以显示成功
      </div>
    )
  }
}
v-if
const isExist = true;
export default class App extends Component{
  render(){
    let box = <div style={{width: '100px', height: '100px', background: 'red'}}></div>;
    return (
      <div id="app">
        <h1>hello world~~~~~~~~~~</h1>
        { isExist ? box : '' }
        { isExist && box }
      </div>
    )
  }
}
v-else-if
const flag = 'C';
export default class App extends Component{

  render(){
    let box1 = <div style={{width: '100px', height: '100px', background: 'red'}}>A</div>;
    let box2 = <div style={{width: '100px', height: '100px', background: 'yellow'}}>B</div>;
    let box3 = <div style={{width: '100px', height: '100px', background: 'green'}}>C</div>;
    let box4 = <div style={{width: '100px', height: '100px', background: 'blue'}}>D</div>;

    let result = null;
    // switch (flag) {
    //   case 'A':
    //     result = box1;
    //     break;
    //   case 'B':
    //     result = box2;
    //     break;
    //   case 'C':
    //     result = box3;
    //     break;
    //   case 'D':
    //     result = box4; 
    //     break;
    // }

    if(flag === 'A'){
      result = box1;
    }else if(flag == 'B'){
      result = box2;
    }else if(flag == 'C'){
      result = box3;
    }else if(flag == 'D'){
      result = box4;
    }
    return (
      <div id="app">
        <h1>hello world~~~~~~~~~~</h1>
        {result}
      </div>
    )
  }
}
v-bind

v-bind属性绑定

直接设置标签的属性为一个{表达式}

绑定class,正常写class的表示方式:多个class属性值之间使用空格隔开

绑定style 绑定一个对象

export default class App extends Component{
  render(){
    let className = 'hello';
    let title = 'hello react';
    
    return (
      <div id="app">
        <h1>hello world~~~~~~~~~~</h1>
        <div className={className} title={title}> </div>
        <div style={{width: '100px', height: '100px', background: 'red'}}></div>
      </div>
    )
  }
}
v-show

操作标签的display属性为none

  <div style={{width: '100px', height: '100px', background: 'red', display: isShow ? '': 'none'}}></div>
v-for

数组我们通常用map

其他操作使用自运行函数

删除数组使用filter

添加使用扩展运算符(…)

let list = ['A', 'B', 'C', 'D', 'E'];

export default class App extends Component{
  render(){
    let listDOM = list.map((item)=>{
      return <p key={item}>{item}</p>
    });
    return (
      <div id="app">
        <h1>hello world~~~~~~~~~~</h1>

        {/* {
          list.map((item)=>{
            return <p>{item}</p>
          })
        } */}

        {listDOM}
      </div>
    )
  }
}
v-on

//需要指正this指向:

 this.handleClick = this.handleClick.bind(this);
 <button onClick={this.handleClick}>
    Click me
 </button>
 ———————————————————————————————————————————————————————————


//可以使用class fields语法

handleClick = () => {
    console.log('this is:', this);
}
...

 <button onClick={this.handleClick}>
        Click me
 </button>

 ———————————————————————————————————————————————————————————

 箭头函数语法不推荐:(每次渲染组件时都会创建不同的回调函数,对性能不友好)
 
   <button onClick={(e) => this.handleClick(e)}>
       Click me
   </button>

 ———————————————————————————————————————————————————————————


传递参数:

<button onClick={(e) => this.deleteRow(id, e)}>Delete Row</button>
<button onClick={this.deleteRow.bind(this, id)}>Delete Row</button>
v-model

在react中,没有数据双向绑定

只有单向绑定,js的数据绑定给dom,dom的变化不接受

state的基本操作

在vue中:
内部属性 data
外部属性 props
计算属性 computed
全局属性vuex state

在react中
内部属性state:只能在constructor方法中定义
只有在constructor可以设置this.state = {…}
其他函数,都不能直接操作this.state = {…}
如果需要修改state,那么请使用this.setState({…})方法,并且在componentDidMount之后操作
在update相关的所有更新的生命周期方法中都不能操作this.setState({…})

export default class App extends Component{

  constructor(){
    super();

    // 定义组件内部属性,state
    this.state = {
      value: 'hello world',
      a: 1,
      b: 2,
      c: 3
    }

  }

  render(){
    console.log('render.....');

    return (
      <div id="app">
        <h1>{this.state.value}</h1>
        <h1>{this.state.a}</h1>
        <h1>{this.state.b}</h1>
        <h1>{this.state.c}</h1>
        <button onClick={this.btnAction.bind(this)}>修改</button>

      </div>
    )
  }
  btnAction(){
    console.log('点击了修改');
    // 修改state
    this.setState({
      value: 'hi world'
    });
  }
  // mounted 挂载后
  componentDidMount(){
    // this.state = {
    //   value: 'hi world'
    // }
  }
}

react中的受控组件和非受控组件

表单中有一个input标签,input的value值必须是我们设置在constructor构造函数的state中的值,然后,通过onChange触发事件来改变state中保存的value值,这样形成一个循环的回路影响

就是v-model的功能,在react中需要自己去实现
需要自己实现数据双向绑定
数据绑定在表单标签上,必须绑定state的值,不能是普通的值
然后需要实现表单的change事件,在事件中接收ev,获得表单的value值(ev.target.value
将接收到的value值设置给state上,state变了,界面就会变

非受控也就意味着我可以不需要设置它的state属性,而通过ref来操作真实的DOM。

在react中,只有input=(text number email。。。。) textarea select(单选) 标签可以做成受控组件
input=(radio checkbox…)不能做成受控组件

受控组件都是一个特点
1.绑定value值
2.实现change事件,事件内,接收ev.target.value,重新设置给state中绑定的value值

export default class App extends Component{

  constructor(){
    super();

    this.state = {
      value: '123'
    }

  }

  render(){

    return (
      <div id="app">

        {/* 受控组件 */}
        <input type="text" value={this.state.value} onChange={this.changeAction.bind(this)}/>

        {/* 非受控组件 */}
        <input type="text" ref="input"/>
        <button onClick={this.btnAction.bind(this)}>获取</button>
        
      </div>
    )
  }

  changeAction(ev){
    console.log('changeAction run......');

    this.setState({
      value: ev.target.value
    });

  }
  
  btnAction(){
    console.log('btnAction run ........');
    console.log(this.refs.input.value);
  }
}

可实现的受控组件
export default class App extends Component{

  constructor(){
    super();

    this.state = {
      value: '123',
      selected: 'B'
    }

  };

  render(){
    let {value, selected} = this.state;
    let changeAction = this.changeAction.bind(this);

    return (
      <div id="app">
        <input type="text" value={value} onChange={changeAction}/>

        <textarea value={value} onChange={changeAction}></textarea>

        <select value={selected} onChange={this.selectChangeAction.bind(this)}>
          <option value="A">A</option>
          <option value="B">B</option>
          <option value="C">C</option>
          <option value="D">D</option>
        </select>
        
      </div>
    )
  };

  changeAction(ev){
    console.log('changeAction run......');

    this.setState({
      value: ev.target.value
    });

  };

  selectChangeAction(ev){
    this.setState({
      selected: ev.target.value
    })
  }
}

实现radio标签的数据绑定
export default class App extends Component{

  constructor(){
    super();

    this.state = {
      gender: '男'
    }
  };

  render(){
    let {gender} = this.state;

    return (
      <div id="app">
        <label>
          <input type="radio" value="男" onChange={this.radioAction.bind(this)}
            checked={gender==='男'}/></label>
        <label>
          <input type="radio" value="女" onChange={this.radioAction.bind(this)}
            checked={gender==='女'}/></label>

      </div>
    )
  };

  radioAction(ev){
    console.log(ev.target.value, ':');
    console.log(ev.target.checked);


    if(ev.target.checked){
      this.setState({
        gender: ev.target.value
      })
    }
    
  }
}
实现checkbox标签的数据绑定
export default class App extends Component{

  constructor(){
    super();

    this.state = {
      likes: ['吃']
    }

  };

  render(){
    let {likes} = this.state;
    console.log(likes);
    console.log('render......');

    return (
      <div id="app">
        <p>数据:{likes}</p>
        <label>
          <input type="checkbox" value="吃" onChange={this.checkboxAction.bind(this)}
            checked={     (()=>{
              return this.state.likes.findIndex(item=>item==='吃') >= 0
            })()      }/></label>
        <label>
          <input type="checkbox" value="喝" onChange={this.checkboxAction.bind(this)}/></label>
        <label>
          <input type="checkbox" value="玩" onChange={this.checkboxAction.bind(this)}/></label>
        <label>
          <input type="checkbox" value="乐" onChange={this.checkboxAction.bind(this)}/></label>

      </div>
    )
  };

  checkboxAction(ev){
    
    if(ev.target.checked){
      //选中:将value放在数组中

      // 直接操作state,是错误的
      // this.state.likes.push('value');

      // 通过setState修改state中的数据,是正确的
      this.setState({
        likes: [...this.state.likes, ev.target.value]
      });
    }else{
      //取消选中:将value从数组中拿出来
      // this.state.likes 删除掉其中一个,ev.target.value
      this.setState({
        likes: this.state.likes.filter(item=>(item !==ev.target.value))
      })
    } 
  }
}
组件的传值
1.父子组件:
  传值:
  1.父传子:在父组件中,设置自定义属性,子组件使用porps进行接收
  props外部属性,需要采用单向数据流。props只可以访问,不能修改

  2.子传父:绑定自定义属性,但是属性值为函数。在子组件中,通过props调用该函数,
    通过函数传参的形式将值传给父组件
    
2.非父子组件
  同vue,使用发布订阅模式

  1.new Vue
      $on
      $emit

  2.自己实现发布订阅模式

  3.pubsub.js
父传子

Father.js

export default class Father extends Component {
  constructor(){
    super();
    this.state = {
      list: ['A', 'B', 'C', 'D'],
      selected: 'A',
      selectCity: null
    }
  }

  render() {
    return (
      <div className="father">

        <h1>Father组件</h1>
        

        <nav>
        {
          this.state.list.map(item=>(
            <button key={item} onClick={()=>{
              this.setState({selected: item});  
            }}>{item}</button>
          ))
        }
        </nav>

        <p>选择的城市为:{this.state.selectCity}</p>

        <hr/>

        <Son title="hello wrold" data={this.state.selected} onSelectCity={this.handleSelectCity.bind(this)}/>

      </div>
    )
  }

  handleSelectCity(item){
    console.log('handleSelectCity执行了........', item);
    console.log(this);
    this.setState({
      selectCity: item
    });
  }
}

Son.js

export default class Son extends Component {
//props
  constructor(props) {
    super(props);
    this.state = {
      cities: ['深圳', '北京', '广州']
    }
  }
  render() {
    return (
      <div className="son">
        <h1>Son组件</h1>
        <p>{this.props.title}</p>
        <p>{this.props.data}</p>
        <nav>
        {
          this.state.cities.map(item=>(
            <button key={item} onClick={()=>{
               this.props.onSelectCity(item);
            }}>{item}</button>
          ))
        }
        </nav>
      </div>
    )
  }

}

React.Components生命周期函数

挂载:

constructor() 构造函数

构造函数必须调用super()  
在构造函数中,如果需要访问props,直接调用参数中的props   在构造函数中,设置state的初始值
在构造函数中,给多次使用的函数bind(this)
以及其他的一些初始化操作

static getDerivedStateFromProps() //相当于计算属性

render() //在这个方法中,不能使用setState 需要返回组件的dom

componentDidMount() //挂载后 mounted 通常在这个方法中,请求数据,操作dom

更新:

只有调用了setState组件才会执行更新!!!!!!!!

1.props发生变化,执行更新:
UNSAFE_componentWillReceiveProps(newProps) 废弃了
static getDerivedStateFromProps() 16.0+
shouldComponentUpdate()\

    shouldComponentUpdate(newProps, newState, newContext){
    console.log(this.props, this.state, this.context);//旧值
        在这个方法中,对比数据的新旧值,对render方法进行拦截,减少render的操作,可以优化react组件的性能
    }

render() 得到了新的dom
UNSAFE_componentWillUpdate() 废弃了
getSnapshotBeforeUpdate() 16.0+\

如果你在componentDidUpdate方法中有复杂的逻辑操作,数据处理可以放在getSnapshotBeforeUpdate中处理之后传给componentDidUpdate,而componentDidUpdate就只需要处理dom了    
参数列表是旧值 实现了这个函数,就必须实现componentDidUpdate

componentDidUpdate() //updated

    componentDidUpdate(oldProps, oldState, result)  result是getSnapshotBeforeUpdate中return的值

2.state发生变化,执行更新:
static getDerivedStateFromProps() 16.0+
shouldComponentUpdate()
render() 得到了新的dom
UNSAFE_componentWillUpdate() 废弃了
getSnapshotBeforeUpdate() 16.0+
componentDidUpdate()

如果执行了 强制更新 forceUpdate: 不询问,直接更新
static getDerivedStateFromProps() 16.0+
render() 得到了新的dom
UNSAFE_componentWillUpdate() 废弃了
getSnapshotBeforeUpdate() 16.0+
componentDidUpdate()

卸载

componentWillUnmount

react数据不可变性(时间旅行)

react中的数据(state)需要拥有不可变性

不可变性:一旦声明,设置了值,之后不能修改,这个值相当于一个快照,相当于一帧表示当前的的一个状态

之后如果需要修改,先将数据拷贝出来成为一个新的数据或引用类型,再修改。

虚拟dom

虚拟dom全部需要重新构建,然后再比较不同,发现不同的地方,再根据不同的虚拟dom构建真实dom,用真实的dom替换页面不同的地方

react数据发生变化的时候所有组件的rander函数都会被触发,构建虚拟dom进行比较
事实上明知道是没有修改的,++连虚拟dom的创建和比较也可以避免掉++\

 shouldComponentUpdate(newProps, newState){
    // console.log('旧值:', this.props, this.state);
    // console.log('新值:', newProps, newState);
    // 判断this.props和newProps是否不同
    // 判断this.state和newState是否不同
    // 判断引用地址一样不一样,如不一样就是改了,如一样就是没改
    浅比较,只比较props和state的第一层数据的值
    const result1 = this.compareData(newProps, this.props);
    const result2 = this.compareData(newState, this.state);
    return !(result1 && result2);
  }


 // 比较两个对象,如果都相同,那么返回值为true
  // 比较两个对象,如果不相同,那么返回值为false
  compareData(newVal, oldVal){
    let newKeys = Object.keys(newVal);
    let oldKeys = Object.keys(oldVal);
    let result = true;
    if(newKeys.length === oldKeys.length){
      //修改某个值
      // 删除一个,新增一个
      newKeys.forEach(key=>{
        if(newVal[key] !== oldVal[key]){
          result = false;
        }
      })
    }else{
      result = false;//新增了,删除了
    }
    return result;
  }

不可变对象的修改方式

this.setState({
    obj:{
        ...this.state.obj,
        b:3
    }
})

1.简化复杂的功能
2.跟踪数据的变化
3.确定React何时修改

PureComponen(它不止阻挡自己的更新,子组件的也会阻挡掉)

纯组件相对于Component组件,已经实现了上面的shouldComponentUpdata,不需要开发者实现

怎么实现:
就是比较state和props的新旧值,实现的是浅比较只比较第一层,只比较引用是否相等,不比较内容

react其他属性

setState

react是异步更新dom的
vue是同步更新dom的

异步更新数据和dom,如果setState之后,立即操作state,得不到新的值
需要在setState第二个参数的回调函数中操作,才是更新后的结果

this.setState({
    val:this.state.val+1   // 接下来会执行componentDidUpdate
    val2:this.state.val2 / this.state.val   //由于setState是异步更行,this.state.val并不能确定是初始值还是计算后的值,所以不建议这样使用(百分之99不会有问题会是初始值)
},()=>{
    ...
    //componentDidUpdate  执行完之后执行
});

异步计算的不确定性,提议这样写:

 this.setState((state, props)=>{
      return {
        val: state.val+1,
        val2: this.state.val2 / state.val
      }
    });

简化写法:
this.setState((state, props)=>({
  val: state.val+1,
  val2: this.state.val2 / state.val
}));
class属性
defaultProps

配置外部属性的props的默认值

App.defaultProps = {
  title: '我的react项目'
}

写在class里面:

 static defaultProps = {
    title: '我的react项目'
  }
displayName

配置组件的名字

App.displayName = 'Root';

写在class里面:

static displayName = 'Root';

react的高级指引

代码分割(模块/组件按需引入)

普通模块可以按需引入

只要支持es6模块化的环境都可以使用import按需引入

import('./utils/tools').then(({mapArray})=>{
      let newArr = mapArray(['a', 'b', 'c'], (item, index)=>(item+index));
      console.log(newArr);
    })

组件按需引入

这里有一个Box组件,我需要在App组件中懒加载这个Box组件

之前在vue中:

const Box=()=>import("./Box");

即可使用,vue中会自动帮你解析promise,但是在React中不行

在react中:

import("./math").then(math => {
  console.log(math.add(16, 26));
});

React.lazy 可以实现组件的懒加载,但是是react16.0之后新增的功能

const Box=React.lazy(()=>import("./Box"));
凡是懒加载的部分,都需要使用lazy

<React.Suspense fullback={<div>loading......</div>}>

凡是有懒加载组件的部分,都需要Suspense组件包裹,并且Suspense组件需要实现fallback属性
fallback的值,当Suspense组件识别到自己的子节点有懒加载的组件,
使用 fallback的结构 先替换组件所在位置,当组件加载出来了,再使用真正的组件。

</React.Suspense>

懒加载载入的组件不能是export const输出,必须使用export default

在react中使用scss直接安装node-scss,不需要配置,引用直接引用.scss

context

React.context

使用context的三个步骤

1.创建context

React.createContext({
    title:'my react project'  //设置默认值一般不需要设置
})

2.设置提供context

AppContext.Provider

 <AppContext.Provider value={{title: 'hello world'}}>
    <div className="foo">
      ...
    </div>
</AppContext.Provider>

3.使用context

1.contextType

设置了context的类型,该组件,会在自己的组件树一层一层向上找该类型的Provider,找到了该类型的Provider使用Provider提供的value数据,找不到,就使用该类型的默认值

Item.contextType=AppContext;

2.AppContext.Consumer

 <AppContext.Consumer>
      {(context)=>{
        return <mark>{context.title}</mark>
      }}
  </AppContext.Consumer>
错误边界

在vue中会使用errorCaptuer 捕获错误
在react中有两个 处理错误的方法,这两个方法只能在根文件中使用

getDeriveStateFromError

他的this指向组件class,不需要this就使用这个静态方法

static getDeriveStateFromError(error){
    1.显示错误提示界面
    2.收集错误,提交给后台
    return {
        isError:true
    }
}

componentDidCatch

需要使用this就是用这个,指向实例

componentDidCatch(error){
    // 1.显示错误提示界面
    // 2.收集错误,提交给后台
    this.setState({
      isError: true
    })
}

实际使用将error单独封装成一个组件,然后让error组件去包裹App
这个error的组件就是错误边界
Error.js

render(){
   console.log(this.props.children);
   if(!this.state.isError){
       //没有错
       return this.props.children;  //组件中包含的内容
   }else{
       return(
        <div>
           出错了
           <button onClick={this.goHomeAction.bind(this)}>回到首页</button>
        </div>
       )
   }
}

 goHomeAction(){
    this.setState({isError: false}, ()=>{
      //切换到首页
    })
  }

  componentDidCatch(){
    this.setState({isError: true});
  }

index.js 中 使用

<Error>
    <App/>
</Error>

refs和 DOM

ref的基本使用

ref中有设置多个同名,就会获取到最后的一个,不管是普通结构还是循环出来的结构(在vue中循环出来的结构会放在一个数组中)

如果想操作多个:

[1,2,3].map(item=>{
    <Box key={item} ref={"box-"+item}>
})

给普通标签设置ref,得到的使用dom对象,可以操作dom

react中操作ref是会影响性能的,他的ref是通过闭包来实现的
闭包嵌套得到的refs的这个对象,会消耗性能

解决:(推荐使用这种函数的形式操作ref,不要用上面的字符串的方式)

普通标签:

<h1 ref={
    (el)=>{
        console.log(el);
    }
}>app组件</h1>

组件:
<Box ref={
    (com)=>{
        console.log(com)
        this.box=com;     
    }
}></Box>

16.3+推出了另外一种形式

createRef

contructor(){
    this.el=createRef();
}
<h1 ref={this.el}>
componentDidMount(){
    this.el.current.style.color = 'red';
}

元素和组件使用方式是一样的

回调函数的方式和createRef这两个方法都可以,不要使用字符串的方式

ref的转发

在父组件上设置ref,要获取到上面的子元素/组件

注意

*函数式组件不能设置ref,ref也不能在函数式组件中设置*

React.forwardRef

在父组件中设置了ref给这个wrap组件

ref的转发,不在于设置的ref值是什么,关键在于设置了ref的组件内部,需要使用React.forwardRef()包裹函数式组件,函数式组件的参数第一个还是props,还多了第二个参数,是外部接收到的ref,就可以设置转发给内部的结构
Wrap.js

export default React.forwardRef(
    (props,ref)=>{   //props 会把ref给剔除掉
        return(
            <div>
                <h3 ref={ref}></h3>  //转发给了h3,外部获取的ref就不是wrap组件而是h3
            </div>
        )
    }
)
Fragment

Fragment 相当于 Vue中的tempale标签,不会在页面上渲染,是react的内置组件

<></>这样写是Fragment的糖语法,不需要引入Fragment

它也是16.0+的新属性,之前的写法

  render() {
    return [
      <h1 key="1">hello world</h1>,
      <h2 key="2">hello world</h2>,
      ...
    ]
  }
高阶组件

一般会用with开头 一个给普通组件增加功能的函数

本质上是一个函数

高阶组件内返回一个组件,接收到的参数需要有组件

返回的组件类型:函数式组件,React.forwardRef(()=>{});构建的组件,第二个参数是个对象

export default(Com)=>{
    return class widthTest extends Component(
        render(){
            return{
                <Com/>
            }
        }
    )
}

组件使用:
Foo.js

import {withTest} from '../HOC/withTest'
...
export default withTest(Foo);

使用场景:

  1. 统一的功能可以在高阶组件上实现
  2. 统一样式
  3. 共享数据

高阶组件有两个弊端:
1.传值问题props
2.ref选择问题

Portals

类似于Vue中的$mount 动态挂载

constructor(props) {
    super(props);
    this.el = document.querySelector('#modal-root');
  }
  
  render() {
    let dom = (
      <div id="modal" style={{width: '100px', height: '100px', background: 'red'}} onClick={this.tapAction.bind(this)}></div>
    )
    return ReactDOM.createPortal(
      dom,
      this.el
    );
  }
Profiler

测量树中这部分渲染所带来的开销

<Profiler id="app" onRender={this.renderCallback}>
//... 需要被检测性能的结构
</Profiler>




renderCallback(...rest){
    console.log(rest);
}
与第三方库协同

要确定在dom挂载完成再去操作

深入理解JSX

JSX类型不能使用表达式,处理方法,将组件在外面定义好组件,相当于Vue中的动态组件

表达式

true 在vue中是undifande

propTypes

进行props属性检查

需要先引入包,搭建脚手架的时候已经安装好了

import types from 'prop-types'


Model.propTypes/*固定字段*/={
    /*效验属性类型*/
    val:types.string,  //string,
    title:types.any.isRequired
    
    
    /*写一个必填,数字组成的数组或者字符串组成的数组,其他的格式自定义效验方式的*/
    test: types.arrayOf(types.oneOfType([
        types.number,
        types.string,
        function(){

    }
  ])).isRequired
}

在react中如何配置跨域?

creat-react-app 在react脚手架搭建中找解决方法

配置多个跨域:

src/setupProxy.js

const proxy = require('http-proxy-middleware');

module.exports = function(app) {

  app.use(
    '/ajax',
    proxy({
      target: 'http://m.maoyan.com',
      changeOrigin: true
    })
  );
};

eject 执行

调出webpack的配置环境,就可以自己添加修改配置

webpack resolve.alias 可以设置别名

npm run eject 执行完成后,找到新增进来的webpack.config.js

....
return{
    ...
    resolve:{
        ....
        alias:{
            {...},
            ...(modules.webpackAliases || {}),
                pages: path.resolve(__dirname, '../src/pages'),  //配置路径别名
            }
    }
}

配置完后即可使用

import Movie from 'pages/movie/movie/movie'
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值