react 基础 学习

react 基础 学习

1、环境配置

初始化项目。npm init 生成package.json

npm install xx 可以生存package-lock.json 和 node_modules 文件

// 渲染react元素
ReactDOM.render(
  title,
  document.getElementById('root')
)
// 第一个参数:要渲染的React元素
//第二个参数:Dom对象,用于指定渲染到页面中到位置

初始化脚手架

npx create-react-app my-app

扩充小知识:

ReactDom用于渲染Web页面,ios和安卓用的react-native里面的东西

2、JSX

2.1、Jsx介绍

因为React.createElement 十分繁琐,便引出了JSX。

JSX JavaScript XML:表示在Js代码中写HTML格式的代码。

JSX是react的核心内容。

JSX表示在JS代码中写HTML结构,是React申明式的体现

const title = <h1>i use jsx </h1>;
ReactDOM.render(title, document.getElementById("root"));

为什么脚手架可以使用JSX语法。==> 使用babel/present-react编译过后,才能在浏览器中使用。

2.2、JSX的基本使用

1、React元素的属性名使用驼峰命名法

2、特殊属性名 class - >ClassName 、 for ->HtmlFor 、 tabindex -> tabInDex

const title = <h1 className = "hello">i use jsx </h1>;

3、没有React子节点的元素可以单闭合标签

const title = <h1 className = "hello">i use jsx  <span/></h1>;

4、推荐使用小括号包裹JSX,从而避免Js中的自动插入分号陷阱

const dv = (
  <div>hello jsx </div>
)

3、 JSX中使用JavaScript表达式

Jsx中嵌入js表达式

  • 数据存储在js中
  • 语法:
const name = 'hujesse'
const dv = (
  <h1> hello,{name}</h1>
)

4、条件渲染

1 、 逻辑与运算符
const showLoading = (isLoading) => {
  return isLoading && (<div>Loading</div>);
};
2、if-else
const showLoading = (isLoading)=>{
  if (isLoading){
    return <div> loading</div>
  }
  return <div>success</div>
}
3、三元表达式
const showLoading = (isLoading) => {
  return isLoading?(<div>Loading</div>):(<div>Success</div>)
};

5、Arrow function

普通的function(){}和箭头函数的区别在于this的指向不同,其他一样

6、 JSX的列表渲染

const songs = [
  { id: 1, name: "gang" },
  { id: 2, name: "no-flex-zone" },
  { id: 3, name: "flecRoom" },
];
const list = (
  <ul>
    {songs.map((item) => (
      <li key={item.id}>{item.name}</li>
    ))}
  </ul>
);
ReactDOM.render(list, document.getElementById("root"));

注意点:避免使用索引号作为key,而应该使用唯一的属性比如id

7、JSX的样式处理

1、行内样式

const list = <h1 style={{ color: "red" }}>Jsx的样式处理</h1>;

2、使用类名className( 推荐

import "./index.css";
const list = <h1 className="title">Jsx的样式处理</h1>;

8、组件

8.1、组件介绍

使用React就是在使用组件。

组合多个组件实现完整的页面功能。(可复用、独立、可组合)

8.2、组件二种创建方式

1、函数式组件

约定:1)大写字母开头 2)必须有返回值

function Hello() {
  return <div>这是函数式组件普通方法形式</div>;
}
const Hello2 = () => <div>这是函数式组件ArrowFun形式</div>;

ReactDOM.render(<Hello2 />, document.getElementById("root"));

2、类式组件

约定:1)大写字母开头、 2)继承React.Component、 3)提供render()方法 、4)render方法必须有返回值

class Hello3 extends React.Component {
  render() {
    return <div>这是我的第一个类组件</div>;
  }
}
ReactDOM.render(<Hello3 />, document.getElementById("root"));
8.2.1、组件定义抽离为Js文件

.. 没啥好说的

8.3、React事件处理
1、事件绑定

语法:on+事件名称 = 「事件处理程序」 onClick

注意:React事件采用驼峰命名法 比如:onFocus.

export default class Hello extends Component {
  handleClick() {
    return () => {
      console.log("单击");
    };
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick()}>clike me</button>
      </div>
    );
  }
}

上面和下面需要注意⚠️!!! 因为{} 前套的js表达式会立马执行

export default class Hello extends Component {
  handleClick() {
    console.log("单击");
  }
  render() {
    return (
      <div>
        <button onClick={this.handleClick}>clike me</button>
      </div>
    );
  }
}
2、事件对象
export default class Hello extends Component {
  handleClick(e) {
    //这里我们拿到了事件对象叫 ‘e’
    // 阻止浏览器的默认行为
    e.preventDefault();
    console.log("点击我不跳转");
  }
  render() {
    return (
      <div>
        <a href="www.google.com" onClick={this.handleClick}>
          clike me
        </a>
      </div>
    );
  }
}
8.4、有状态组件和无状态组件
  • 函数组件又叫做无状态组件,类组件又叫有状态组件
  • 状态(state)即数据
  • 函数组件没有自己的状态,只负责数据展示(静)
  • 类组件有自己的状态,负责更新UI, 让页面动起来
8.5、组件中的state和setState()

状态(state)即数据,是组件内部的私有数据,只能在组件内部使用。

写法一:

export default class Hello extends Component {
  constructor(){
    this.state = {
      count:0,
    }
  }

写法二:

export default class Hello extends Component {
  state = {
    count: 0,
  };

小案列:计数器

export default class Hello extends Component {
  state = {
    count: 0,
  };
  render() {
    return (
      <div>
        <h1
          onClick={() => {
            this.setState({ count: this.state.count + 1 });
          }}
        >
          {this.state.count}
        </h1>
      </div>
    );
  }
}
8.6、事件绑定this指向

同上计数器,需要修改this的指向.

希望:this指向组件实例(render方法中的this即为组件实例)

使用箭头函数修改this

export default class Hello extends Component {
  state = {
    count: 0,
  };
  fun = () => {
    this.setState({ count: this.state.count + 1 });
  };
  render() {
    return (
      <div>
        <h1 onClick={this.fun}>{this.state.count}</h1>
      </div>
    );
  }
}

8.7、表单处理

1、受控组件(受react控制)

定义:HTML中的表单元素是可输入的,也就是有自己的可变状态(input)

而React中可变状态一般保存在state中,并且只能通过setState()修改

React将state与表单元素值value绑定在一起,由state的值来控制表单元素的值

文本框 富文本 下拉 复选框

export default class Hello extends Component {
  state = {
    txt: "",
    fullTxt: "",
    city: "",
    isChecked: false,
  };
  handleChange = (e) => {
    const target = e.target;
    const value = target.type === "checkbox" ? target.checked : target.value;
    const name = target.name;
    // [name] 等同于把name字符串变成变量名了
    this.setState({ [name]: value });
  };
  render() {
    return (
      <div>
        <input
          name="txt"
          type="text"
          value={this.state.txt}
          onChange={this.handleChange}
        />
        {/* 富文本框 */}
        <textarea
          name="fullTxt"
          value={this.state.fullTxt}
          onChange={this.handleChange}
        ></textarea>
        {/* 下拉框 */}
        <select
          value={this.state.city}
          onChange={this.handleChange}
          name="city"
        >
          <option value="bj">北京</option>
          <option value="sz">深圳</option>
          <option value="gz">广州</option>
        </select>
        {/* 复选框 */}
        <input
          name="isChecked"
          type="checkbox"
          checked={this.state.isChecked}
          onChange={this.handleChange}
        />
      </div>
    );
  }
}

2、非受控组件

说明:借助于ref获取值,但是直接操作了dom,不推荐使用。

8.8、总结

react完全利用js语言的能力创建组件,这就是react的思想

8.9、小案列:展示 嘿嘿嘿🤤,我的小案例🤤
export default class Hello extends Component {
  state = {
    comments: [
      { id: 1, name: "jack", content: "hi" },
      { id: 2, name: "dick", content: "hol" },
      { id: 3, name: "hoe", content: "hoe" },
    ],
    userName: "",
    content: "",
  };
  renderList = () => {
    const { comments } = this.state;
    if (comments.length === 0) {
      return <div className="no-comment">暂无评论</div>;
    }
    return (
      <ul>
        {comments.map((item) => (
          <li key={item.id}>
            <h3>评论人:{item.name}</h3>
            <p>{item.content}</p>
          </li>
        ))}
      </ul>
    );
  };
  handleChange = (e) => {
    const { name, value } = e.target;
    this.setState({ [name]: value });
  };
  addComment = () => {
    const { comments, userName, content } = this.state;
    // 非空判断
    if (userName.trim() === "" || content.trim() === "") {
      alert("请输入");
      return;
    }
    const lastComment = comments[comments.length - 1]; //取出最后一个元素
    const newComnets = [
      ...comments,
      { id: lastComment.id + 1, name: userName, content: content },
    ];
    this.setState({ comments: newComnets });
    // 清空文本框
    this.setState({
      userName: "",
      content: "",
    });
  };
  render() {
    return (
      <div className="app">
        <div>
          <input
            type="text"
            className="user"
            placeholder="plz input ur name"
            name="userName"
            value={this.state.userName}
            onChange={this.handleChange}
          />
          <br />
          <textarea
            className="content"
            id=""
            cols="30"
            rows="10"
            value={this.state.content}
            name="content"
            onChange={this.handleChange}
          ></textarea>
          <br />
          <button onClick={this.addComment}>发表评论</button>
        </div>
        {this.renderList()}
      </div>
    );
  }
}

9、组件通信

介绍:多个组件之间不可避免的要共享某些数据

9.1、组件的props

组件是封闭的,要接受外部数据应该通过props来实现

props是只读的

接受数据:类组件通过this.props接受数据,函数组件通过参数props接受数据

可以传递字符串,对象,数组,函数,jsx表达式 etc

9.2、组件通讯的三种方式

1、父向子:props

2、子向父:利用回调函数,夫提供回调,子组件调用,将要传递的数据作为回调的参数

class Parent extends React.Component {
  getMsg = (msg) => {
    console.log("getMsg" + msg);
  };
  render() {
    return (
      <div className="parent">
        父组件
        <Child getMsg={this.getMsg} />
      </div>
    );
  }
}

class Child extends React.Component {
  handleClick = () => {
    this.props.getMsg("ahah");
  };
  render() {
    return (
      <div className="child">
        子组件
        <button onClick={this.handleClick}>clickMe</button>
      </div>
    );
  }
}
ReactDOM.render(<Parent />, document.getElementById("root"));

3、兄弟之间组件通信

把二个兄弟之间的状态提升到父组件中,由后者进行管理。

class Counter extends React.Component {
  // 提供共享状态
  state = {
    count: 0,
  };
  handleChange = () => {
    this.setState({ count: this.state.count + 1 });
  };
  render() {
    return (
      <div>
        <Child1 count={this.state.count} />
        <Child2 handleChange={this.handleChange} />
      </div>
    );
  }
}

const Child1 = (props) => {
  return <h1>计数器 {props.count}</h1>;
};

const Child2 = (props) => {
  return <button onClick={() => props.handleChange()}>+1</button>;
};
ReactDOM.render(<Counter />, document.getElementById("root"));
9.3、Context

调用步骤:

1、调用React.createContext()创建Provider(提供数据)和Consumer(消费数据)二个组件。

const {Provider,Consumer} = React.createContext()

2、使用Provider组件作为父组件

<Provider>
  <div className="App">
    <Child1/>
  </div>
</Provider>

3、设置value属性,表示要传递的数据

<Provider value="pink">
  <div>
    <Node />
  </div>
</Provider>

4、调用Consumer组件接受数据

const Child = (props) => {
  return (
    <Consumer>
      {(data) => {
        return <span>我是子节点接受的数据 -- {data}</span>;
      }}
    </Consumer>
  );
};

整体:

const { Provider, Consumer } = React.createContext();
export default class App extends Component {
  render() {
    return (
      <Provider value="pink">
        <div>
          <Node />
        </div>
      </Provider>
    );
  }
}
const Node = (props) => {
  return (
    <div>
      <SubNode />
    </div>
  );
};
const SubNode = (props) => {
  return (
    <div>
      <Child />
    </div>
  );
};
const Child = (props) => {
  return (
    <Consumer>
      {(data) => {
        return <span>我是子节点接受的数据 -- {data}</span>;
      }}
    </Consumer>
  );
};
ReactDOM.render(<App />, document.getElementById("root"));

10、props深入

10.1、props.children属性

props可以传递任意值!!

props.children 是双标签组件中插槽中的值

const App = (props) => {
  return (
    <div>
      <h1>组件标签的子节点:</h1>
      {props.children}
    </div>
  );
};
const Test = () => {
  return (
    <div>
      <button>我是button</button>
    </div>
  );
};
ReactDOM.render(
  <App>
    <p>我是插槽中的子节点</p>
    <Test />
  </App>,
  document.getElementById("root")
);

10.2 props 校验

不想说 没必要

10.3 props默认值
App.defaultProps = {
  pageSize:10
}

11、组件的生命周期

定义:组件从被创建到挂载到页面中运行,再到组件不用时卸载的过程。

钩子函数:生命周期的每一个阶段总是伴随着一些方法调用,这些方法就是生命周期的钩子函数。

只有类组件才有生命周期

11.1、生命周期的三个阶段

1、创建时候

2、更新时候

3、卸载时候

组件从页面消失。

12、react路由

Router组件:包裹整个应用,一个React应用只需要使用一次

二个常用Router:HashRouter 和 BrowserRouter

前者格式为:localhost:3000/#/first 有个‘ # ’

后者格式为:localhost:3000/first

编程式导航:this.props.history.push('/home')

posted @ 2021-11-02 11:36  能借我十块钱吗  阅读(29)  评论(0编辑  收藏  举报