React元素只读性
let element = { name: '邓立' }
Object.freeze(element)
element.sex = '男'
console.log(element);
- Object.freeze()原理
Object.defineProperties(Object, 'freeze', {//数据劫持
value: function (obj) {
var i;
for (i in object) {//遍历属性和方法
if (Object.hasOwnProperty(i)) {
Object.defineProperty(obj, i, {//数据劫持
writable: false//把所有属性改为不可修改 只读
})
}
}
Object.seal(obj)//让此对象不能添加额外的属性
}
})
Object.defineProperties
方法直接在一个对象上定义新的属性或修改现有属性,并返回该对象。Object.defineProperties | MDNhasOwnProperty()
方法会返回一个布尔值,指示对象自身属性中是否具有指定的属性(也就是,是否有指定的键)。hasOwnProperty() | MDNObject.seal()
方法封闭一个对象,阻止添加新属性并将所有现有属性标记为不可配置。当前属性的值只要原来是可写的就可以改变。Object.seal() | MDN
JSX转换
- 源代码
import React from 'react';
function App() {
return <p>Hello World</p>;
}
- React16 转换
import React from 'react';
function App() {
return React.createElement('p', null, 'Hello world');
}
- React17 转换
import {jsx as _jsx} from 'react/jsx-runtime';
function App() {
return _jsx('p', { children: 'Hello world' });
}
- 想使用之前的方式转换需要在
package.json
里设置
"scripts": {
"start": "set DISABLE_NEW_JSX_TRANSFORM=true&&react-scripts start",
"build": "set DISABLE_NEW_JSX_TRANSFORM=true&&react-scripts build",
"test": "set DISABLE_NEW_JSX_TRANSFORM=true&&react-scripts test",
"eject": "set DISABLE_NEW_JSX_TRANSFORM=true&&react-scripts eject"
},
React源码解析
页面结构
import React from './react'
import ReactDOM from 'react-dom'
/**
* React 自定义组件
* 1.自定义的组件首字母大写;
* 2.组件使用前先定义
* 3.组件需要返回并且只能返回一个根元素
* @param {*} props
*/
function ReactTest(props) {
return (<div className='title' style={{ background: 'pink', color: 'purple' }}>
<span>{props.name}</span>
</div>)
}
ReactDOM.render(
<ReactTest name='前端了了liaoliao' />,
document.getElementById('root')
);
效果展示
React之createElement源码分析
/**
*
* @param {*} type 元素类型
* @param {*} config 元素配置
* @param {*} children 子类信息
*/
function createElement(type, config, children) {
let props = { ...config }
if (arguments.length > 3) {
//截取有效数据
children = Array.prototype.slice.call(arguments, 2)
}
props.children = children
return {
type,
props
}
}
const React = { createElement }
export default React
ReactDOM之render源码分析
/**
* 1.把vdom(虚拟DOM)变成真实DOM dom
* 2.把虚拟DOM上的属性更新(同步)到dom上
* 3.把此虚拟DOM的儿子们也都变成真实DOM挂载到自己的dom上dom.appendChlid
* 4.把自己挂载到容器上
* @param {*} vdom 要渲染的虚拟DOM
* @param {*} container 要把虚拟DOM转换真实DOM并插入到容器中去
*/
function render(vdom, container) {
const dom = createDOM(vdom)
container.appendChild(dom)
}
/**
* 把虚拟DOM变成真实DOM
* @param {*} vdom
*/
function createDOM(vdom) {
//如果是数字或者字符串,就直接返回文本节点
if (typeof vdom === 'number' || typeof vdom === 'string') {
return document.createTextNode(vdom)
}
//否则就是一个虚拟DOM对象,即React元素
let { type, props } = vdom
let dom = null
if (typeof type === 'function') {//自定义函数组件
return momentFunctionComponent(vdom)
} else {
if (type) {//原生
dom = document.createElement(type)
}
}
//使用虚拟DOM的属性更新刚创建出来的真实DOM的属性
updateProps(dom, props)
//在这里处理props.children属性
if (props && props.children) {
if (typeof props.children === 'string' || typeof props.children === 'number') {
//如果只有一个子类,并且是数字或者字符串
dom.textContent = props.children
} else if (typeof props.children === 'object' && props.children.type) {
//如果只有一个子类,并且是虚拟dom元素
render(props.children, dom)
//如果是数组
} else if (Array.isArray(props.children)) {
reconcileChildren(props.children, dom)
} else {
document.textContent = props.children ? props.children.toString() : ''
}
}
// vdom.dom = dom
return dom
}
/**
* 把一个类型为自定义函数组件的虚拟DOM转换为真实DOM并返回
* @param {*} vdom 类型为自定义函数组件的虚拟DOM
*/
function momentFunctionComponent(vdom) {
let { type: FunctionComponent, props } = vdom
let renderVdom = FunctionComponent(props)
return createDOM(renderVdom)
}
/**
* 遍历数组
* @param {*} childrenVdom 子类们的虚拟dom
* @param {*} parentDOM 父类的真实DOM
*/
function reconcileChildren(childrenVdom, parentDOM) {
for (let i = 0; i < childrenVdom.length; i++) {
let childVdom = createDOM(childrenVdom[i])
render(childVdom, parentDOM)
}
}
/**
* 使用虚拟DOM的属性更新刚创建出来的真实DOM的属性
* @param {*} dom 真实DOM
* @param {*} newProps 新属性对象
*/
function updateProps(dom, newProps) {
for (let key in newProps) {
if (key === 'children') continue;
if (key === 'style') {
let styleObj = newProps.style
for (let attr in styleObj) {
dom.style[attr] = styleObj[attr]
}
} else {//js支持dom.title='设置'
dom[key] = newProps[key]
}
}
}
const ReactDOM = { render }
export default ReactDOM
项目地址github
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!