ant design vue 中Upload组件如何自定义文件列表的样式

ant design vue 中Upload组件如何自定义文件列表的样式

    • 问题
    • 历程
    • UploadList 组件源码
    • h() 方法
    • 实现

问题

  • 技术:vueant design vue
  • 在开发项目的时候呢,遇到这样一个需求:就是在展示文件列表的时候,需要使用小图标标明该文件的类型
  • 实现类似下图的效果:
    在这里插入图片描述

历程

  • 首先当前还是仔细去研究官方文档啦
  • 不幸的是,官方文档并未给出相应的案例
  • 有点麻爪,然后向领导反映:“能不能用文字代替呀”,领导人给我一张图:
    ant design vue 中Upload组件如何自定义文件列表的样式_第1张图片
  • 经过对官方文档仔细的阅读,依旧咩有发现领导给的案例,想想可能是真滴没有,因为领导之前是用 reactant designreact 的支持是相当成熟的,而 ant design vue 才发布没多长时间呢,这个案例的写法呢,也是典型的 JSX 语法
  • 继续研究官方文档,Upload 组件其实是有一个 showUploadList 的属性的,从命名可以看出,应该是控制文件列表是否展示的,再看看官方文档的解释:
    在这里插入图片描述
  • 没错了,所以现在就有一个简单的思路,不使用默认的文件列表展示,我们重新自定义,简单来说,就是设置 showUploadList = "flase"。之前使用 element-ui 的时候,对默认的文件列表样式做过重构,主要就是在 beforeUpload 的时候进行初始化,监听 on-progress 事件,获取文件上传的进度,然后将这些数据按照UI在页面上展示出来就可以了。需要注意的是,修改和删除 vue 实例 data 里面的 Object 属性,需要使用 this.$setthis.$delete
    • ant design vueUpload 组件里呢,我们就需要监听组件的 change 事件,file 里面的 percent 属性,就是上传文件的进度啦
      ant design vue 中Upload组件如何自定义文件列表的样式_第2张图片
  • 仔细的捋了捋之后,发现这种实现其实是有点丢了西瓜捡了芝麻的,因为自定义的话。
    • 这里的文件列表展示除了每一项有小图标,其他样式其实跟默认样式是一毛一样的,所以自定义样式基本跟 UploadList 有90%保持一致呢。
    • 无论是照猫画虎,还是复制粘贴,都是显得很是冗余
    • 而且,上传文件的进度条,加载动效等可能都要复刻进去
    • 花费这么大功夫只搞这么一个小功能,想想真滴是有些得不偿失呢
  • 接下来,我又到 Github 上看有没有人提过相关的 issue ,结果还是一无所获
  • 哎,只能去看看源码了

UploadList 组件源码

  • 源码链接
  • 这里着重看看 UploadList 中有关 file.name 的部分。因为含有 file.name 字段的就是有关文件名的展示。
const preview = file.url
        ? [
            <a
              target="_blank"
              rel="noopener noreferrer"
              class={
     listItemNameClass}
              title={
     file.name}
              {
     ...linkProps}
              href={
     file.url}
              onClick={
     e => this.handlePreview(file, e)}
            >
              {
     file.name}
            </a>,
            downloadOrDelete,
          ]
        : [
            <span
              key="view"
              class={
     `${
       prefixCls}-list-item-name`}
              onClick={
     e => this.handlePreview(file, e)}
              title={
     file.name}
            >
              {
     file.name}
            </span>,
            downloadOrDelete,
          ];
  • 官方 UploadList 的实现使用的是 JSX 用法,所以,根据 JSX 语法的特性,某种意义上说, { file.name } 应该是可以作为一个组件出现的
  • 上面我们知道 file.name 可以是一个组件。但是在我这个项目要实现的话,可能也需要对原有的代码进行 JSX 语法的重构,这个任务也是相对比较重的
  • 有没有更简单的方法呢?
    • 其实在项目中我们引用第三方包或者插件的时候,它都是以 javascriptES5) 的形式出现的
    • 所以可以再看看 node_moudles 目录下该组件的源码
var preview = file.url ? [h(
        'a',
        (0, _babelHelperVueJsxMergeProps2['default'])([{
     
          attrs: {
     
            target: '_blank',
            rel: 'noopener noreferrer',

            title: file.name
          },
          'class': listItemNameClass }, linkProps, {
     
          attrs: {
     
            href: file.url
          },
          on: {
     
            'click': function click(e) {
     
              return _this2.handlePreview(file, e);
            }
          }
        }]),
        [file.name]
      ), downloadOrDelete] : [h(
        'span',
        {
     
          key: 'view',
          'class': prefixCls + '-list-item-name',
          on: {
     
            'click': function click(e) {
     
              return _this2.handlePreview(file, e);
            }
          },
          attrs: {
     
            title: file.name
          }
        },
        [file.name]
      ), downloadOrDelete];
  • 不难看出,这里的 file.name 是作为 h() 方法的第三个参数的首元素出现的
  • h() 方法又是个什么玩意呢?
    • 从代码本身看,它是 render() 方法的第一个参数
      ant design vue 中Upload组件如何自定义文件列表的样式_第3张图片

h() 方法

  • 上节说过,h()render() 方法的第一个参数
  • 了解过 vue 同学应该都知道,render() 其实就是 vue 实例的渲染函数,它比模板更接近编译器,简单来说,它可以通过 javascript 来创建你的 HTML
  • 渲染函数官方文档链接
  • h() 方法还有另一种我们熟悉的写法 createElement()
    ant design vue 中Upload组件如何自定义文件列表的样式_第4张图片
  • createElement 亦即 h 参数
// @returns {VNode}
createElement(
  // {String | Object | Function}
  // 一个 HTML 标签名、组件选项对象,或者
  // resolve 了上述任何一种的一个 async 函数。必填项。
  'div',

  // {Object}
  // 一个与模板中 attribute 对应的数据对象。可选。
  {
     
    // (详情见下一节)
  },

  // {String | Array}
  // 子级虚拟节点 (VNodes),由 `createElement()` 构建而成,
  // 也可以使用字符串来生成“文本虚拟节点”。可选。
  [
    '先写一些文字',
    createElement('h1', '一则头条'),
    createElement(MyComponent, {
     
      props: {
     
        someProp: 'foobar'
      }
    })
  ]
)
  • 上节提到,file.name 是作为 h() 方法的第三个参数的首元素出现的
  • 仔细观察,h 方法的第三个参数,它支持的类型有两种 String | Array,而在 UploadList 的源码,它正式作为 Array 类型出现的
    ant design vue 中Upload组件如何自定义文件列表的样式_第5张图片
  • Array 即数组中数组元素的类型可以是:VNodes | 文本虚拟节点
    ant design vue 中Upload组件如何自定义文件列表的样式_第6张图片
  • 综上所述,我们不难得出结论:file.name 的值可以是一个 VNode类型的虚拟节点

实现

  • 有了思路实现就简单了,在需要自定义的地方使用 createElement方法创建相应的 VNode 即可代码如下:
export default {
     
	created () {
     
	    console.log(this.$route.params.enterpriseId)
	    // 获取当前 vue 实例的渲染函数
	    const h = this.$createElement
	    filesData.financial_statements = filesData.financial_statements.map(item => ({
     
	      ...item,
	      name: h('span', null, [
	        item.name,
	        h('img', {
     
	          attrs: {
      src: require('@/assets/sheet_types/audit_sheet.png') },
	          class: {
      'sheet-type-img': true }
	        })
	      ])
	    }))
	    this.enterprise = {
      ...this.enterprise, ...filesData }
	    this.enterprise.id = this.$route.params.enterpriseId
	  }
}
.sheet-type-img {
     
  width: 20px;
  height: 20px;
  margin: 0px 10px;
}
  • 这样修改之后呢,浏览器控制台会有下图的情况:
    ant design vue 中Upload组件如何自定义文件列表的样式_第7张图片
  • 看了看是 warn 的程度,不影响程序正常运行哦
  • 最终效果
    在这里插入图片描述

转载请注明出处!!!

你可能感兴趣的:(ant,design,vue,踩坑记录,javascript,css,vue.js,html,前端)