react学习笔记(一)

安装node和create-react-app

node安装 略过
create-react-app

npm i -g create-react-app
cd xxx // 目录
npm start

这时候就生成了一个简单的react页面

发现问题:serviceWorker.js是啥

service worker是在后台运行的一个线程,可以用来处理离线缓存、消息推送、后台自动更新等任务。registerServiceWorker就是为react项目注册了一个service worker,用来做资源的缓存,这样你下次访问时,就可以更快的获取资源。而且因为资源被缓存,所以即使在离线的情况下也可以访问应用(此时使用的资源是之前缓存的资源)。注意,registerServiceWorker注册的service worker 只在生产环境中生效(process.env.NODE_ENV === ‘production’)

dependecies: 生产环境中需要的
devDependencies: 开发环境需要的

发现问题:哪些包应该放在dependecies中,哪些包应该放在devDependencies中

babel,webpack等放在dependecies中
react,vue等放在devDependencies

JSX

JSX即 js and xml,可以解析所有js语言和html标签,
解析器遇到< 当做xml来解析,遇到{}当做js来解析

React Dom使用camelCase来定义属性的名称,如className,onClick,以及在style中写的marginLeft等

<span style={{marginLeft:10+'px'}}>删除</span>

jsx可以防止xss攻击,React DOM在渲染所有输入内容前,默认会进行转义。

在编译时,babel会吧JSX转义成名为React.createElement()函数调用,这个函数会进行一些检查,防止编写错代码

这两种代码等效

// 写法1:
const element = (
  	<h1 className="test">
		hello
	</h1>
)

// 写法2:
const element = React.createElement(
	'h1',
	{className:'test'},
	hello
)

写法:

// JSX写法
class App extends Component{
  render(){
  	return{
  	  <ul className="test">
  	  	<li>item1</li>
  	  	<li>item2</li>
  	  </ul>
  	}
  }
}
// 不用JSX的写法
var child1 = React.createElement('li',null,"item1")
var child2 = React.createElement('li',null,"item2")
var root = React.createElement('ul',{className:'my-list'}.child1,child2)

// index.js
import App from ‘./App’

这里的App是自定义组件,必须要以大写字母来开头。

Fragment

类似于vue中的template,不需要标签,但是react中一定要用div包裹。

使用Fragment需要引用

元素渲染

“根” DOM 节点,因为该节点内的所有内容都将由 React DOM 管理。
React 只会更新改变的dom部分,其他部分不更新

组件与Props

定义组件的方式: 函数组件和class组件

React元素可以是用户自定义的组件:

const element = <Welcome name="Sara" />;

数据绑定,事件绑定

增加数据在construstor中增加
数据绑定和事件绑定写在JSX中

mport React,{Component,Fragment} from 'react'

class Xiaojiejie extends Component{
  // 这里的constructor是用来增加数据的
  constructor(props){
    super(props)
    this.state={
      inputValue: 'jsPang',
      list: []
    }
  }

  render(){
    return (
      <Fragment>
        <div>
          <input value={this.state.inputValue} onChange={this.inputChange.bind(this)}/>
          <button>增加服务</button>
        </div>
        <ul>
          <li>头部按摩</li>
          <li>精油推背</li>
        </ul>
      </Fragment>
    )
  }
  inputChange(e){
    console.log(e.target.value)
	this.setState({
	  inputValue: e.target.value
	})	
  }
}

export default Xiaojiejie

这时候,我们把数字绑定以及事件绑定做好了
下一步,

  1. 用循环的方式,把list队列中的事件渲染出来
  2. 通过事件改变list,在list中可以添加新的任务

react的循环怎么写

参考地址:react中的for循环
写法一(贴出部分代码)

constructor(props){
    super(props)
    this.state={
      inputValue: '',
      list: ['头部按摩','精油推背']
    }
  }

  render(){
    return (
      <Fragment>
        <div>
          <input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
          <button>增加服务</button>
        </div>
        <ul>
          {
            this.state.list.map((item, index) => {
              return <li key={item+index}>{item}</li>
            })
          }
        </ul>
      </Fragment>
    )
  }

写法二:

render(){
    return (
      <Fragment>
        <div>
          <input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
          <button>增加服务</button>
        </div>
        <ul>
          {
            this.insertStr()
          }
        </ul>
      </Fragment>
    )
  }

  insertStr(){
    let str = this.state.list.map((item, index) => {
      return <li key={item+index}>{item}</li>
    })
    console.log(str) // $$typeof: Symbol(react.element),key:精油推背1,props:{children:'精油推背'},ref:null,type:li
    return str
  }

写法三:

render(){
    return (
      <Fragment>
        <div>
          <input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
          <button>增加服务</button>
        </div>
        <ul>
          {
            this.insertStr()
          }
        </ul>
      </Fragment>
    )
  }

  insertStr(){
    let str = []
    for(let i=0; i<this.state.list.length; i++) {
      str.push(<li key={i}>{this.state.list[i]}</li>)
    }
    console.log(str) // $$typeof: Symbol(react.element),key:1,props:{children:'精油推背'},ref:null,type:li
    return str
  }

完成了循环渲染,下一步是添加,首先添加添加事件
1.

 <button onClick={this.addService.bind(this)}>增加服务</button>
...省略好几行...

addService(e){
   let myList = this.state.list
   myList = [...this.state.list, this.state.inputValue]
   this.setState({
     list:myList
   })
 }

注意:上面事件的写法,先用一个myList列表把要修改的state中的list保存起来,然后先去操作myList,之后再用setState方法把list赋值进去。

后续优化:
1.每次添加完,都让input框的内容置空
2.添加成功后,让input自动focus
3.添加删除按钮

1.setState里面让inputValue为""就可以了
2.暂时不知道怎么解决
3.在jsx中写行内style样式的写法

 <li key={item+index}>{item}<span style={{marginLeft:10+'px'}}>删除</span></li>

to-do基本完成:

render(){
    return (
      <Fragment>
        <div>
          <input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
          <button onClick={this.addService.bind(this)}>增加服务</button>
        </div>
        <ul>
          {
            this.state.list.map((item, index) => {
              return <li key={item+index}>
                      {item}
                      <span className='del' onClick={this.remove.bind(this,index)}>删除</span>
                     </li>
            })
          }
        </ul>
      </Fragment>
    )
  }

  inputChange(e){
    this.setState({
      inputValue:e.target.value
    })
  }

  addService(){
    let list = this.state.list
    list = [...this.state.list, this.state.inputValue]
    this.setState({
      inputValue:'',
      list
    })
  }
  
  remove(e){
    let list = this.state.list;
    list.splice(e,1);
    this.setState({
      list
    })
  }

组件分离:

将to-do中的service(头部按摩,精油推背)分离出来
1.新增一个service.js组件
在service的render中获取接收的参数

// service.js
render() {
    return (
    	<Fragment>
        <span dangerouslySetInnerHTML={{__html:this.props.item}}></span>
        <span className='del' onClick={this.props.remove}>删除</span>
       </Fragment>
    );
  }

在xiaojiejie.js中引用

// xiaojiejie.js
import myService from './service'
//省略代码...
render(){
  ...省略代码
  <ul>
  {
      this.state.list.map((item, index) => {
        return <li key={item+index} >
                <MyService remove={this.remove.bind(this,index)} item={item}></MyService>
                {/**
                 * 这里是之前的代码
                 *  <span dangerouslySetInnerHTML={{__html:item}}></span>
                 *  <span className='del' onClick={this.remove.bind(this,index)}>删除</span>
                 */}
               </li>
      })
    }
  </ul>
}
remove(e){
    let list = this.state.list;
    list.splice(e,1);
    this.setState({
      list
    })
  }
在vue中,删除是通过组件的$emit传回一个值给父元素,父元素来做删除,或是在组件中新增一个删除事件,然后删除。在react中,则是把父组件的事件传递给子组件,让子组件去调用,子组件往这个方法传参,在父组件中接收参数,来实现父子组件传递。

子组件向父组件传值

// 父组件
// 给子组件的属性deleteItem上绑定了自己的remove方法,这个方法有参数idx,用来接收子组件传递回来的参数
<MyService deleteItem={this.remove.bind(this)} index={index} key={item+index} item={item}></MyService>
...代码

remove(idx){
    let list = this.state.list;
    list.splice(idx,1);
    this.setState({
      list
    })
  }

// 子组件
render() {
    return (
       <Fragment>
        <span dangerouslySetInnerHTML={{__html:this.props.item}}></span>
        <span className='del' onClick={this.handleClick.bind(this)}>删除</span>
       </Fragment>
    );
  }
  handleClick(){
    // 调用父组件传递过来的方法,并且把indexsuoyi
    this.props.deleteItem(this.props.index)
  }

几个注意点:

1.jsx的注释写法

<div>
  {/**
    * 写注释需要用{}包住,其他和js中一样
  	*/}
  <input value={this.state.inputValue} onChange={this.inputChange.bind(this)} />
  <button onClick={this.addService.bind(this)}>增加服务</button>
</div>

2.如果想要实现类似v-html的效果,在input框中输入<h1>123</h1>,让123放大加粗,那要用dangerouslySetInnerHTML,让代码实现html格式的输出

  <ul>
    {
		this.state.list.map((item, index) => {
			return <li key={item+index} >
						<span dangerouslySetInnerHTML={{__html:item}}></span>
						<span className='del' onClick={this.remove.bind(this,index)}>删除</span>
					</li>
		})
	}
  </ul>

label for

在jsx中,label for要写成 <label htmlFor="xx">,避免和js中的for循环混淆

react插件

Simple React Snippets

快速引入:在vscode中输入imrc,就可以快速生成常用的import
输入cc,可以快速生成组件的基本代码

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值