语法规则:
## JSX的由来
React为了方便View层组件化。承载了构建HTML结构化页面的职责。从这点上来看,React与其他JavaScript模板语言有着许多异曲同工之处,但不同之处在于React是通过创建与更新虚拟元素(virtual element)来管理整个Virtual DOM的。
JSX将HTML语法直接加入到JavaScript代码中,再通过翻译器转换成**纯JavaScript**。在实际开发中,JSX在产品打包阶段都已经编译成纯JavaScript了,不会带来副作用,反而让代码更加直观并易于维护。
JSX的官方定义是**类XML语法的ECMAScript扩展**。它完美地利用了JavaScript自带的语法和特性。并使用大家熟悉的HTML语法来创建虚拟元素。
----
## JSX的基本语法
1、单个根元素
2、标签一定要闭合
3、自定义标签(组件)首字母需要大写
4、注释使用js注释
5、class属性,需要改为className
6、for属性,需要改为htmlFor
7、一些特性,需要使用表达式的方式来写false或者true,不然都会渲染成true
8、属性值,要使用表达式,只需要用**{}**替换**""**即可
9、html类容转义,需要使用dangerouslySetInnerHTML属性
```html
<divdangerouslySetInnerHTML={{__html:content}}></div>
```
组件的使用:
创建一个function 把内容return 出去
importReactfrom'react';
importReactDOMfrom'react-dom';
//创建组件一定要runter出去
constWelcome =function() {
//单行组件如果需要渲染多行的组件需要用一个括号包括起来
// return <div>我是welcome组件</div>
//定义一个变量渲染在组件中
consth3 =<h3>我是子组件的h3我要渲染在页面上</h3>
//如果定义的是一个字符串渲染在页面为一个html
consth4 ='<h4>我又来了</h4>'
return(
<divid="box"className="list">
<h2>我是老李创建的组件</h2>
<div>老李创造了我这个子组件</div>
<labelhtmlFor="username">用户名</label>
<inputtype="text"id="username"/>
<inputtype="radio"checked={false}/>
{h3}
<divdangerouslySetInnerHTML={{__html: h4}}>
</div>
</div>
)
}
ReactDOM.render(
<div>
<h1>我的天我老李自己配置的</h1>
<div>我的天</div>
<Welcome></Welcome>
</div>,
document.getElementById('app')
)
案例:Todolist 组件应用
// TodoList.js 的demo
importReactfrom'react';
importReactDOMfrom'react-dom';
importTodofrom'./Todo';
//定义一个组件
ReactDOM.render(
<Todo></Todo>,
document.getElementById('app')
)
组件代码
//这个是react组件
importReactfrom'react';
//主要在跟组件上需要引入react-dom
// class类的方法定义组件
classTodoextendsReact.Component{
//定义数据(state状态)
constructor(props) {
//一定要调用super
//作用是保证this指向正确,在构造函数中写在最前面。
super(props);
//定义数据
this.state = {
inputVal:'我的天',
list:[]
}
}
// render函数来定义组件内容
// render函数需要return的才是组件的模板内容
// return一大段模板的时候需要用小括号包括起来
render() {
return(
<div>
{/*在input属性上定义的数据,同时还需要定义一个onchange事件绑定的是一个方法这个方法写在模板同级上*/}
{/*请注意方法上this指向的问题需要改变this指向*/}
<inputtype='text'value={this.state.inputVal}onChange={this.handleChange.bind(this)}/>
<buttononClick={this.addTodo.bind(this)}>添加</button>
<ul>
{
this.state.list.map((item,index)=>{
return<likey={index}>{item}</li>
})
}
</ul>
</div>
)
}
//触发input响应的一个方法
handleChange(e) {
//如果需要改变状态,需要this.setState({})
// console.log(e.target.value)
this.setState({
inputVal: e.target.value
})
}
addTodo() {
// let list = this.state.list;
// list.push(this.state.inputVal)
letnewlist =[...this.state.list,this.state.inputVal]
this.setState({
// list:list
list:newlist,
inputVal:''
})
}
}
//暴露组件
exportdefaultTodo
组件类型
#组件
<imgsrc="./img/component.jpg"/>
----
##定义组件
####无状态的纯模板组件
```js
importReactfrom'react';
constApp =function(props) {
return(
<div>
hello world
</div>
)
}
exportdefaultApp;
```
####类的方式
>通过ES6中的class来继承React中的Component。
```js
importReact, { Component }from'react';
classAppextendsComponent {
render() {
return(
<div>
hello world
</div>
);
}
}
exportdefaultApp;
```
----
##使用组件
```js
// 1.引入
importAppfrom'./App';
// 2.使用ReactDOM.render渲染
ReactDOM.render(<App/>, document.getElementById('root'));
```
----
##组合组件
```js
ReactDOM.render(
<div>
<Component1/>
<Component2/>
</div>,
document.getElementById('root')
);
```
----
##组件嵌套
```js
// com1.js
classCom1extendsComponent {
render() {
return(
<div>我是com1组件</div>
)
}
}
// com2.js
importCom1from'./com1.js';
classCom2extendsComponent {
render() {
return(
<div>
<h1>我是com2组件</h1>
<Com1/>
</div>
)
}
}
```
案例:子组件传值到父组件,子组件修改传递到父组件
1.创建一个跟组件
//如果用这种引入方式就需要在下面用React.Component
// import React from 'react';
importReact,{ Component }from'react';
importTodofrom'./component/Todo';
// import TodoItem from './component/TodoItem'
classAppextendsComponent{
render() {
return<Todo></Todo>
}
}
exportdefaultApp
2.根组件下引入子组件
父组件传值给子组件,在子组件中渲染
importReactfrom'react';
importTodoItemfrom'./TodoItem'
classTodoextendsReact.Component{
constructor(props) {
super(props);
this.state = {
inputVal:'',
list:[]
}
}
render () {
letinputVal =this.state.inputVal
return(
<div>
<inputtype="text"value={inputVal}onChange={this.change.bind(this)}/>
<buttononClick={this.addTodo.bind(this)}>添加</button>
{/*传值给TodoItem传递方法*/}
<TodoItemTodoItem={this.state.list}TodoList={this.deleteItem.bind(this)}></TodoItem>
</div>
)
}
//添加
addTodo(){
letnewList = [...this.state.list,this.state.inputVal]
this.setState ({
list:newList,
inputVal:''
})
}
//删除
/**
*
*@param{Number} index下标
*/
deleteItem(index) {
//删除某一项
//不能直接删除需要通过父级改变通过父级的方法传递给子组件
letnewList =this.state.list
newList.splice(index,1)
this.setState({
list: newList
})
}
//获取input框value值
change(e){
this.setState({
inputVal:e.target.value
})
}
}
exportdefaultTodo
3.子组件调用父组件的方法
importReact,{Component}from'react';
classTodoItemextendsComponent {
render() {
//获取父级的值是一个大对象
// console.log(this.props)
return(
<ul>
{
this.props.TodoItem.map((item, index)=>{
return(
<likey={index}>
{item}
<spanonClick={this.deleteTodo.bind(this,index)}>×</span>
</li>
)
})
}
</ul>
)
}
deleteTodo(index){
console.log('我是儿子的删除事件,我要调用父组件的删除的方法');
// console.log(this.props.TodoList);
console.log(index)
this.props.TodoList(index)
}
}
exportdefaultTodoItem