vue组件页面生成实现尝试

962 阅读1分钟

页面生成实现路程

  • 在写 v-html渲染组件问题 的时候就是我想尝试实现页面的生成,但是当时技术还是不行没实现成功,现在有点效果了,记录一下过程

第一步也就是生成一个页面,如下图 image.png

  • 刚开始我是将组件和页面分开,页面是生成个数组结果的对象,组件是直接挂载,页面数组如下:
[{
  content: [
      {
        tag:"span",
        content:"n你好"
      }
  ]
  style"text-align:center"
  tag"div"
}]

/* 数组对象转化字符串 
[
  tag:,
  style,
  content
]*/
function arrChangeStr(arr) {
  let str = ""
  arr.forEach(e => {
    if (Array.isArray( e.content)) {
      str += `<${e.tag} style="${e.style}">${arrChangeStr(e.content)}</${e.tag}>`
    } else {
      str += `<${e.tag} style="${e.style}">${e.content}</${e.tag}>`
    }

  })
  return str
}
// <div style="text-align:center"> <span>n你好</span></div>

然后就是每次点击左边的元素时,找到对应的数组的结点,对数组进行修改,再调用arrChangeStr转化为字符串,v-html 渲染

/* 反推找到DOM节点对应的数组位置 */
function backFind(el) {
  let result = "";
  console.log(el.className);
  
  if (el.parentNode && el.className.indexOf("viewShowPage")==-1 && el.className.indexOf("view")==-1) {
    console.log(el.parentNode.children);
    
    [...el.parentNode.children].forEach((e, i) => {
      if (e == el) 
           result= backFind(el.parentNode)+","+i
          
      }
    })
  }
  return result
}
  • 但是后面发现,当组件挂载的时候,每次数组更新组件会消失重新挂载,这就需要每次挂载结点id的保存,并且每次都重新挂载,比较麻烦,而且最后生成代码也比较难搞,所以放弃这个方式,直接将arrChangeStr转化为字符串的dom直接挂载,这也就是源码。
  • 然后就是对vue组件进行二次封装,将所有属性,尽量一次性数据解决,只需要传一个数据就可以,实现所有效果,这个就要是有人有想法的话,可以帮忙写一写🙏 😀,给个例子:
  <div>
    <div v-for="(item) in radioLists" :key="item.label">
      <el-radio-group v-model="radio" :size="item.size">
        <el-radio
          v-if="!item.type||item.type!=='button'"
          :disabled="item.disabled"
          :border="item.border"
          :size="item.size"
          :label="item.label"
        >{{item.name}}</el-radio>

        <el-radio-button
          v-else
          :disabled="item.disabled"
          :size="item.size"
          :label="item.label"
        >{{item.name}}</el-radio-button>
      </el-radio-group>
    </div>
  </div>
</template>

<script>
export default {
  name: "",
  props: {
    radioList: {
      default: [
        {
          name: "备选框", /单选框名字
          label: "1", //v-model 对应的值  唯一
          disabled: false,  //禁用
          border: false,  // 边框
          size: "small",  //
          type: "button"  //组件的显示类型
        }
      ],
      type: Array
    }
  },
  data() {
    return {
      radio: "1",
      radioLists: null
    };
  },
  created() {
    this.radioLists = this.radioList;
    console.log(this.radioList);
  },
  Mounted() {
    console.log(this.radioList);
  },
  watch: {
    radioList: {
      handler(oldval) {
        this.radioLists = oldval;
        console.log(this.radio);
      }
    }
  }
};
</script>

<style  scoped>
</style>

这里面 只需传radioList 数组就行, 当然还差change 的方法,这个先放一放。