mini-react

## 在页面实现 app ```js console.log('main.js') const dom = document.createElement('div') dom.id = 'app' const rootEl = document.querySelector('#root') rootEl.append(dom) const textNode = document.createTextNode('') textNode.nodeValue = 'hello' dom.append(textNode)

vdom js object

type props children

const el = {
  type: 'div',
  props: {
    children: [
      {
        type: 'TEXT_ELEMENT',
        props: {
          nodeValue: 'app',
          children:[]
        }
      }
    ]
  }
}
//promote
const el = {
  type: 'div',
  props: {
    children: [textEL]
  }
}
const textEL = {
  type: 'TEXT_ELEMENT',
  props: {
    nodeValue: 'app',
    children: []
  }
}

修改抽离一小部分

const textEL = {
  type: 'TEXT_ELEMENT',
  props: {
    nodeValue: '🦋app',
    children: []
  }
}
const el = {
  type: 'div',
  props: {
    id:'app',
    children: [textEL]
  }
}

const dom = document.createElement(el.type)
dom.id = el.props.id
const rootEl = document.querySelector('#root')
rootEl.append(dom)

const textNode = document.createTextNode('')
textNode.nodeValue = textEL.props.nodeValue
dom.append(textNode)

动态创建DOM

function createTextNode (text) {
  return {
    type: 'TEXT_ELEMENT',
    props: {
      nodeValue: text,
      children: []
    }
  }
}

function createElement (type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children
    }
  }
}
const textEl = createTextNode('🦋app')
const App = createElement('div', { id: 'app' }, textEl)

const dom = document.createElement(App.type)
dom.id = App.props.id
const rootEl = document.querySelector('#root')
rootEl.append(dom)

const textNode = document.createTextNode('')
textNode.nodeValue = textEl.props.nodeValue
dom.append(textNode)

创建render函数

function createTextNode (text) {
  return {
    type: 'TEXT_ELEMENT',
    props: {
      nodeValue: text,
      children: []
    }
  }
}

function createElement (type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children
    }
  }
}
/**
 *
 * @param {*} el
 * @param {*} container
 * 1. 创建 element
 *
 * 2. props
 * 3. append
 */
function render (el, container) {
  const dom = el.type === 'TEXT_ELEMENT' ? document.createTextNode('') : document.createElement(el.type)
  //props  id class 遍历
  Object.keys(el.props).forEach(key => {
    if(key!=="children"){
      dom[key] = el.props[key]
    }
  })
  const children = el.props.children
  children.forEach(child => {
    render(child, dom)
  })

  container.append(dom)
}
const textEl = createTextNode('🦋app')
const App = createElement('div', { id: 'app' }, textEl)

render(App, document.querySelector('#root'))
  • 优化
...
function createElement (type, props, ...children) {
  return {
    type,
    props: {
      ...props,
      children: children.map(child => typeof child === 'object' ? child : createTextNode(child))
    }
  }
}
...
const App = createElement('div', { id: 'app' }, '🦋app')
...

任务调度器

let taskId = 1
function workLoop(deadline) {
  taskId++

  let shouldYield = false
  while(!shouldYield) {
    console.log('taskId', taskId)
    shouldYield = deadline.timeRemaining() < 1
  }
  console.log('workLoop', deadline)
  requestIdleCallback(workLoop)
}
requestIdleCallback(workLoop)
  • 使用 requestIdleCallback API 来确保任务在浏览器空闲时执行,不会阻塞主线程
  • 通过 deadline.timeRemaining() 来检查剩余时间,确保不会占用太多时间
  • 实现了持续运行的工作循环,每次循环都会增加任务ID
  • 当剩余时间不足1毫秒时,会暂停当前循环,等待下一次空闲时间
## fiber