vue + elementUI组件重写

4,434 阅读2分钟

文件上传 upload

upload
- upload-list.vue 里面是文件上传成功后的文件列表
- upload.vue 里面是上传按钮
- index.vue 包括前2者的爹
要实现一个重试的作用,就是upload-list.vue点击重试,要通过Index.vue调用upload.vue的重写上传
1在upload-list.vue $emit('retry')
2.在index.vue里

retry () {
this.$refs['upload-inner'].upload(file.raw)
}

upload-inner就是index.vue渲染upload.vue的时候给他的dom名字
也就是子A用emit把事件散发到父B,然后父B把事件用ref传给了子B

表格 table

ele的列表源码可真复杂!看着仿佛是用vuex传递数据,有个tableStore对象,但其实不是的,只是个对象而已,用来管理祖孙三代的各种数据

<y-table>
<y-table-column></y-table-column>
</y-table>

写着写着出现了一个问题——一直不能跑到YTableColumn组件的方法里去(created, mounted,....),搞了一天
忽然想到 YTableColumn是依赖于YTable存在的,那肯定得在YTable需要有个slot,果然是少了这么一个插槽分发内容

jsx

ele源码用到了jsx语法,所以要配置.babelrc,然后安装transform-vue-jsx 插件

{
  "presets": [
    ["env", { "modules": false }],
    "stage-3"
  ],
  "plugins": ["transform-vue-jsx"]

}

render(h) + jsx

安装了jsx插件,就可以愉快的用render了

---摘自vue官网
类型:(createElement: () => VNode) => VNode
字符串模板的代替方案,允许你发挥 JavaScript 最大的编程能力。该渲染函数接收一个 createElement 方法作为第一个参数用来创建 VNode。
如果组件是一个函数组件,渲染函数还会接收一个额外的 context 参数,为没有实例的函数组件提供上下文信息。
Vue 选项中的 render 函数若存在,则 Vue 构造函数不会从 template 选项或通过 el 选项指定的挂载元素中提取出的 HTML 模板编译渲染函数。
beforeMount: 在挂载开始之前被调用:相关的 render 函数首次被调用。

ele源码里的render(h)方法里有个this._l(this.data, (row, $index) => [])
_l好像是个renderCell的方法,打断点的时候见过,无从查起(深入浅出vue里,_l指的renderList方法)

scoped slot(作用域插槽)

但是ele源码为啥要用jsx,而不用template呢,我猜想:
原因1:
template方式不能传递scoped slot(作用域插槽),组件嵌套组件时需要传递scopedSlot,Scoped Slot是在Vue 2.1引入的更进阶的功能,它是一种特殊类型的slot,用作使用一个(能够传递数据到)可重用模板替换已渲染元素。就是使用scoped slot能在插槽里自定义模板并且使用组件传递过来的context。这大大提高了组件开发的灵活性。
比如官网上的:

也可以通过 this.$scopedSlots 访问作用域插槽,得到的是一个返回 VNodes 的函数:
props: ['message'],
render: function (createElement) {
  // `<div><slot :text="message"></slot></div>`
  return createElement('div', [
    this.$scopedSlots.default({
      text: this.message
    })
  ])
}

原因2:
render允许你发挥 JavaScript 最大的编程能力,jsx的Babel 插件,用于在 Vue 中使用 JSX 语法,它可以让我们回到更接近于模板的语法上。总结一下就是用起来方便,而且提升编码能力

有个疑问

写在组件上的属性,依然会存在于组件渲染后?

<table-body
          :store="store"
          :style2="{
             width: bodyWidth
          }">
        </table-body>

style要是写对,就是这样的

父子

table.vue
...
table-body.js ---> // table.vue的vue实例(他prop的方法,属性)
  table() {
      return this.$parent;
    },

内部代码的实现

table.vue
<div class="el-table">
      <div class="hidden-columns" ref="hiddenColumns"><slot></slot></div> // table-column用slot放在这里面
     <table-body></table-body> // 内部获取父亲的实例包括columns,通过操作columns渲染自己的数据
</div>

未完待续...