##JSX
在jsx里面写 style 样式 需要 写成对象的形式才可以
不能直接写 clsaa 需要写成 className
//js代码 转换为 jsx 代码
class App extends PureComponent {
render() {
return (
<div className="title">
// {} 内可以写任意javascript代码
</div>
);
}
}
export default App;
jsx javascript and xml(html)
1:ReactDOM.render(
最外层只能有一个根节点,document.getElementById(‘root’));
2:<></> fragment空标记,即使是空标签,也可以作为容器把一堆内容包裹起来
3:动态绑定数据通过{},大括号内放js表达式(js表达式:执行代码有返回的结果),
=> 可以直接放数组,把数组内的每一项呈现出来
=> 一般情况下不能直接渲染对象
=> 如果渲染的是jsx的虚拟DOM对象,可以直接渲染
4:设置行内样式必须是 style={{color: ‘red’…}},设置样式类名需要使用的是className = ‘类名’
5:jsx中进行的判断一般都是通过三元运算符来完成
6:jsx中遍历数组的每一项。动态绑定多个jsx元素,一般都是基于数组中的MAP来实现的(MAP迭代数组的同时,支持返回值)
7:jsx具备过滤效果(过滤非法内容),有效防止xss攻击
虚拟DOM
// 创建虚拟DOM的2种方式
// 1:纯JS(一般不用)
let element = React.createElement('h1', {id:'myTitle'}, title)
// 2:JSX:
<h1 id='myTitle'>{title}</h1>
jsx虚拟DOM渲染为真实DOM的原理和步骤
1: 基于babel-preset-react-app把jsx语法变为React.createElement的模式
=> 每遇到标签元素都要React.createElement
=> 前两个参数是固定的,标签名,属性,第三个以及以后的参数都是子元素
=> 传递了属性,第二个参数是一个对象(包含了属性的信息),没有传递属性则写null
ReactDOM.render(<>
帅子
</>,document.getElementById('root')
);
转换为
// 标签名,属性,第三个以及以后的参数都是子元素
React.createElement('div',null,'帅子')
2: 基于React.createElement方法执行,创建虚拟DOM对像
=> 首相是一个对象
=> type 存储的是标签名
=> props属性: 没有传递任何属性,也没有任何子元素,其为空对象。把传递给createElement的属性,都赋值给props,如果有子元素,则新增一个children属性,可能是一个值也有可能是一个数组
React.createElement = function(type,props,...children){
let jsxObj = {
type,
props:{}
}
// 如果传递了属性把传递的属性放置到jsxObj的props中
if( props != null ){
// 基于ES6实现浅克隆
jsxObj.props = {...props}
}
// 如果传递了子元素,则把值赋予给jsxObj.props.children即可
if(children.length != 0){
if(children.length === 1)){
jsxObj.props.children = children[0]
}else{
jsxObj.props.children = children
}
}
return jsxObj;
}
3:基于React.render()把创建的虚拟对象渲染到页面上指定的容器中
=> React.render([JSX-DOM],[container],[callback])
=> [callback]渲染触发回调函数,这里获取到真实的DOM节点内容
React.render = functiion render(jsxOBJ, container, callback){
let {type, props} = jsxOBJ
if(typeof type === 'string' ){
let Element = document.creatElement(type)
// 给创建的DOM设置属性
for(let key in props){
// 判断是否有这个属性 如果没有就跳过本次循环
if(!props.hasOwnProperty(key)) break;
// 处理样式行行内样式
if(key === 'className'){
element.setAttribute('class',props[key])
continue;
}
// 处理style样式
if(key === 'style'){
let styOBJ = props['style']
for(let attr in styOBJ){
// 判断是否有这个属性 如果没有就跳过本次循环
if(!styOBJ.hasOwnProperty(key)) break;
element.style[attr] = styOBJ[attr]
}
continue;
}
// 处理children
if(key === 'children'){
// 同一为数组
let children = props['children']
// 判断是否是数组
if(!Array.isArray(children)){
children = [children]
}
// 循环子元素
children.forEach(item => {
// 如果是文本,直接创建文本节点赋值给Element即可,如果是新的虚拟DOM对象,则在需要重复调用render方法,把新创建的DOM对象增加给element(递归)
if(typeof item === 'strinf'){
element.appenchild(document.createTextNode(item))
return;
}else{
render(item, Element)
}
})
}
}
container.appendchild(element)
// 触发回调函数
callback && callback()
}
}