类 jsx简单实现(一)

类jsx 实现(一)

这是第一次在掘金上发表文章,一些概念就不说了自己上主题。

最近面试经常问的问题 比如:讲一下vue原理,react原理,或者什么是虚拟dom。说实话我不知道怎么回答。源码我还没看,最多百度或者掘金上搜索看看,没深入研究就感觉很难回答,所有在这里我自己用自己的方放实现一下(可能代码有很多bug)

代码已经写了一部分就先上代码后面边写代码边写文章 (  全角加空格怎么都没空格啊)
首先看一下Bable转化成React.createElement模式

QQ截图20210526153215.png

const testEle = '<div class="swrap">我是你大哥<span>李白</span></div>' //转化jsx例子
let rule = /(.*?)(<\w+.*?>)(.*)(<\/\w+>)(.*?)$/;  //html标签分解
let tagR = /<\/(\w+)/;//标签
let classR = /class="(\w+)"/;//class
let idR = /id="(\w+)"/;//id
const changeEleDeepToJsx = function (ele, lastResult) {//html深度转化jsx数据
  let result = [];
  var sliceEle = ele.match(rule)
  if (sliceEle === null) {
    return
  }

  console.log(sliceEle[2])
  let tag = sliceEle[4].match(tagR) && sliceEle[4].match(tagR)[1]  //获取标签
  let classAid = {  //class和id
    class: sliceEle[2].match(classR) && sliceEle[2].match(classR)[1],
    id: sliceEle[2].match(idR) && sliceEle[2].match(idR)[1],
  }
  let content = sliceEle[3] // 该父标签下的所有内热

  // result.push(sliceEle[1])
  result.push(tag)
  result.push(classAid)
  // result.push([contentEle]) //内部元素 

  if (sliceEle[5]) {
    result.push(sliceEle[5])
  }

  if (lastResult) {
    if (sliceEle[1]) { //标签前面有文字等内容
      lastResult.splice(2, 0, sliceEle[1])
      lastResult.splice(3, 0, result)
    } else {
      lastResult.splice(3, 0, result)
    }
  }
  if (content) {
    changeEleDeepToJsx(content, result)
  }
  return lastResult ? lastResult : result
}
let jsxResult = changeEleDeepToJsx(testEle)
console.log(jsxResult) 
复制代码

运行后的结果如下:

QQ截图20210526153944.png

接下来写 createElement方法,发现应该传5个参数(不考虑多元素问题)而且还有多个子元素问题,代码进行优化,5个参数改下传值就好

QQ截图20210526161412.png

createElement 方放简单实现

  createElement([tag, ciObj, content1, childNode, content2]) {
    console.log(ciObj)
    if (!ciObj) {  //有问题的
      return ''
    }
    return `
       <${tag} class='${ciObj && ciObj.class}' id='${ciObj && ciObj.id}'>
         ${content1}
         ${this.createElement.bind(this, childNode)()}
         ${content2}
       </${tag}>
      `
  }
}
let react = new React()
let jsx = react.createElement(jsxResult)
console.log(jsx)

复制代码

QQ截图20210526164146.png

先实验一下,新建html文件

<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>
<style>
  * {
    margin: 0;
    padding: 0;
  }

  .swrap {
    background: #409EFF;
   padding: 10px;
  }

  .swrap a{
    cursor: pointer;
    color: #FFF;
  }
</style>

<body>
  <div id="root"></div>
</body>

<script type="module">
  import { changeEleDeepToJsx, jsx } from './jsx2.js'
  let render = function () {
    return (
      ' <div class="swrap">{{name}}<span>你的<a>大哥</a></span>啊</div>'
    )
  }
  console.log(changeEleDeepToJsx(render()))
  //虚拟dom模拟
  /* 
  
  */
  document.getElementById('root').innerHTML = render()
</script>

</html>



**  js  **
const testEle = '<div class="swrap">我是<span>你的<a>大哥<a></span>啊</div>'
let rule = /(.*?)(<\w+.*?>)(.*)(<\/\w+>)(.*?)$/;
let tagR = /<\/(\w+)/;//标签
let classR = /class="(\w+)"/;//class
let idR = /id="(\w+)"/;//id
const changeEleDeepToJsx = function (ele, lastResult) {//html深度转化jsx数据
  let result = [];
  var sliceEle = ele.match(rule)
  if (sliceEle === null) { //没有子元素
    console.log(ele, 57)
    lastResult.splice(3, 0, '')
    lastResult.splice(2, 0, ele)
    return
  }

  let tag = sliceEle[4].match(tagR) && sliceEle[4].match(tagR)[1]  //获取标签
  let classAid = {  //class和id
    class: sliceEle[2].match(classR) && sliceEle[2].match(classR)[1] || '',
    id: sliceEle[2].match(idR) && sliceEle[2].match(idR)[1] || '',
  }
  console.log(classAid)
  let content = sliceEle[3] // 该父标签下的所有内热

  // result.push('')
  result.push(tag)
  result.push(classAid)
  // result.push([contentEle]) //内部元素 
  // if (sliceEle[5]) {
  result.push(sliceEle[5])
  // }


  if (lastResult) {
    //   if (sliceEle[1]) { //标签前面有文字等内容

    //     lastResult.splice(3, 0, result)
    //   } else {
    lastResult.splice(2, 0, sliceEle[1])
    lastResult.splice(3, 0, result)
    // }

  }
  if (content) {
    changeEleDeepToJsx(content, result)
  }
  return lastResult ? lastResult : result
}
let jsxResult = changeEleDeepToJsx(testEle)
console.log(jsxResult)

class React {
  createElement([tag, ciObj, content1, childNode, content2]) {
    console.log(ciObj)
    if (!ciObj) {  //有问题的
      return ''
    }
    return `
       <${tag} class='${ciObj && ciObj.class}' id='${ciObj && ciObj.id}'>
         ${content1}
         ${this.createElement.bind(this, childNode)()}
         ${content2}
       </${tag}>
      `
  }
}
let react = new React()
let jsx = react.createElement


console.log(jsx)
export {changeEleDeepToJsx,jsx}

复制代码

写到这里发现还有像这个符号{{}}的监听啥的还没写,还是无法测试。

总结一下

一、实现html转化成数组结构,数组结构转化为html格式,转化数组结构暂时没实现多个子元素情况
二、vue react 是转化成树结构的,下一篇先实现树的
三、js代码没封装好,写了个function 和 class类
四、markdown不熟悉文章写的烂的要死

© 版权声明
THE END
喜欢就支持一下吧
点赞0 分享