ant-design-vue 遇到的問題和常見場景的實現(xiàn)

1绪商、select/datepicker/asacader 組件菜單框顯示時苛谷,滾動頁面,菜單框不隨父元素滾動格郁,而是根據(jù)body頁面滾動

原因: ant默認(rèn)append到body
解決: 通過組件的屬性getXxxContainer 修改渲染的父元素

  <template>
    <a-select
      v-decorator="['highestEdu']"
      class="highestEdu"
      placeholder="請選擇最高學(xué)歷"
      :getPopupContainer="() => doc.getElementsByClassName('highestEdu')[0]">
      <a-select-option
        v-for="edu in eductionOptions"
        :value="edu"
        :key="edu"> {{ edu }}</a-select-option>
    </a-select>
  </template>
  <script>
    export default {
      data () {
        return {
            doc: document
        }
     }
    }
    // 自定義封裝級聯(lián)組件遇到直接父組件綁定class無效或直接級聯(lián)組件綁定class腹殿,會出現(xiàn)菜單項一點就消失的問題,需要包裹一層div綁定
// provinceCity.js
  <template>
    <div :class="popupContainer">
      <a-cascader
        :options="provinceCity"
        :placeholder="placeholder"
        v-model="city"
        @change="handleCascader"
        :getPopupContainer="getPopupContainer"></a-cascader>
    </div>
  </template>
  <script>
    export default {
      props: {
        value: { type: Array },
        placeholder: {
          type: String
        },
        popupContainer: {
          type: String
        }
      },
      methods: {
        getPopupContainer () {
          return document.getElementsByClassName(this.popupContainer)[0]
        }  
      }
    </script>
 // form.vue
  <ProvinceCity
    v-decorator="['nativePlace']"
    placeholder="請選擇籍貫"
    popupContainer="nativePlace"
    @emitCascader="handleNativePlaceChange"/>

!!! 全局化配置

  <a-config-provider :getPopupContainer="getPopupContainer">
      <router-view style="min-width: 992px;"/>
   </a-config-provider>
  // script
  methods: {
    getPopupContainer (triggerNode) {
      // 觸發(fā)節(jié)點 指某個頁面的select例书,tooltip锣尉,menu等含彈框顯示的組件,這些組件顯示下拉框會觸發(fā)該方法决采,不包括datapicker自沧,可全局配置
      return triggerNode
    }
  }

2、ant 內(nèi)引入moment树瞭,日期均返回moment

頁面使用直接引入moment暂幼、不需要npm i

  import moment from 'moment'  

moment組件值轉(zhuǎn)化

  this.form.date.format('YYYY-MM-DD')

3、form表單里upload選擇xlsx文件(只選擇一份移迫,后選擇的會覆蓋前選擇文件)旺嬉,最后提交上傳(整個form表單form-data處理)

// http.js
postByForm (url, params) {
    return this.Axios.post(url, params, {
      headers: {
        'Content-type': 'multipart/form-data'
      }
    }).catch(e => {
      return Promise.reject(new ApiError(
        'network error', -1
      ))
    })
  }

// apis.js 
// 所有傳的參數(shù)formData化
export async function updateMultiMember ({accountID, upload}) {
  const formData = new FormData()
  upload.forEach((file) => {
    formData.append('upload[]', file)
  })
  formData.append('accountID', accountID)
  formData.append('appkey', Global.appkey)
  formData.append('channel', Global.channel)
  formData.append('chainTokenArray[]', [Global.chainToken])
  let res = await saveAgents(formData)
  return res
}

// upload.vue
<template>
  <ContentWithFooter
    @emitCommit="handleUpload">
      <a-form
        class="multi-upload-form"
        :form="multiForm">
        <a-form-item
          v-bind="formItemLayout"
          label="選擇文件">
          <a-upload
            accept='.xlsx'
            name="upload"
            :remove="handleRemove"
            :beforeUpload="beforeUpload"
            v-decorator="['upload',{
              valuePropName: 'fileList',
              getValueFromEvent: normFile,
              rules: [{required: true, message: '請選擇文件'}]
            }]">
            <a-button>上傳文件</a-button>
          </a-upload>
        </a-form-item>
      </a-form>
  </ContentWithFooter>
</template>
<script>
import { Utils } from '@/common'
import ContentWithFooter from '@/components/content-with-footer'
export default {
  name: 'member-multi',
  components: { ContentWithFooter },
  data () {
    return {
      formItemLayout: Utils.setFormLayout(2, 22),
      multiForm: this.$form.createForm(this),
      fileList: []
    }
  },
  methods: {
    handleRemove (file) {
      const index = this.fileList.indexOf(file)
      const newFileList = this.fileList.slice()
      newFileList.splice(index, 1)
      this.fileList = newFileList
    },
    beforeUpload (file) {
      this.fileList = [file]
      return false  // return false 實現(xiàn)手動上傳
    },
    handleUpload () {
      this.multiForm.validateFields((err, values) => {
        if (!err) {
          // 這邊出現(xiàn)一個就是,直接傳values.upload,會出現(xiàn)類型錯誤厨埋,雖然打印出來的東西一樣邪媳,但不再是File類型
          this.$emit('emitMultiFormSubmit', {upload: this.fileList})
        }
      })
    },
    normFile (e) {
      if (Array.isArray(e)) {
        return e
      }
      // return e && e.fileList 
      return e && [e.file]  // 如果單單一個upload組件,不在form表單里,則直接beforeUpload方法里this.fileList = [file]則會實現(xiàn)替換文件雨效,只顯示一條記錄的動態(tài)效果迅涮,但form表單里需要在這個方法里設(shè)置
    }
  }
}

單純的upload組件流程都是正常的:

  • 上傳后返回的文件類型是正常的File類型
  • beforeUpload或者change事件里直接代碼this.fileList = [file]都可以實現(xiàn)選擇文件后 上傳列表永遠(yuǎn)只顯示最后選擇的文件

但是,放入form表單徽龟,不再是uplaod組件上:fileList="fileList"叮姑,而是通過

  v-decorator="['upload',{  // form表單項屬性
     valuePropName: 'fileList',  // 表示upload組件的fileList屬性
     getValueFromEvent: normFile, // 表示upload組件的fileList屬性的值
     rules: [{required: true, message: '請選擇文件'}]
   }

綁定獲取值,這時會出現(xiàn)2個問題

  • 一般form表單處理据悔,都是在this.multiForm.validateFields ((err, values) => {} 表單校驗通過后传透,直接取values里對應(yīng)的表單項值,但這邊取upload极颓,會出現(xiàn)類型由File變?yōu)镺bject朱盐,導(dǎo)致后端無法解析,下圖可見(前者upload綁定值菠隆,后者form取form表單項綁定值兵琳,雖然瀏覽器控制臺打印出來看上去一樣,但是類型變了:Ь丁G !一定要注意):
image.png

然后就是上傳列表永遠(yuǎn)只顯示最后選擇的文件這個過渡效果破衔,需要在form表單項的v-decorator里配置getValueFromEvent: normFile

  normFile (e) {
      if (Array.isArray(e)) {
        return e
      }
      // return e && e.fileList 
      return e && [e.file]  // 如果單單一個upload組件清女,不在form表單里,則直接beforeUpload方法里this.fileList = [file]則會實現(xiàn)替換文件运敢,只顯示一條記錄的動態(tài)效果校仑,但form表單里需要在這個方法里設(shè)置
    }
  }

4忠售、需要form colomu布局传惠,但每項row

image.png
 <a-form :form="basicForm">
    <a-form-item
      label="姓名"
      v-bind="formItemLayout">
      <a-input
        v-decorator="[
          'name',
          {
            rules: [{required: true, message: '請輸入姓名'}]
          }]"
        placeholder="請輸入姓名"/>
    </a-form-item>
 </a-form>
<script>
  const FORMLAYOUTITEM = {
    labelCol: { span: 2 },
    wrapperCol: { span: 8 }
  }

  export default {
     data () {
        formItemLayout: FORMLAYOUTITEM 
     }
  }

5、table列表分頁實現(xiàn)

<a-table
  :columns="columns"
  :dataSource="tableData"
  :loading="isTableLoading"
  :rowKey="record => record.id" 
  :pagination="pagination" // 分頁配置
  @change="handleTableChange"/> // 分頁稻扬、排序卦方、篩選變化時觸發(fā)

  <script>
    export default {
      data () {
          return {
            pagination: {
              showSizeChanger: true, // 顯示當(dāng)前頁顯示幾條
              total: 0,
              pageSize: 10,
              current: 1
            },
        }
      }
    }
  methods: {
    handleTableChange (pagination) {
      this.pagination.current = pagination.current
      this.pagination.pageSize = pagination.pageSize
      this.getLists()
    }
  }

6、form+table form搜索條件變化泰佳,table分頁當(dāng)前頁參數(shù)重置

image.png

實現(xiàn):通過ant form創(chuàng)鍵的時候設(shè)置onValuesChange這個optionmemberQueryForm: this.$form.createForm(this, {onValuesChange: this.onFormValuesChange}) form任一表單項的值發(fā)生變化時的回調(diào)

7盼砍、menu 頁面刷新,保留點擊狀態(tài) + 路由跳轉(zhuǎn)逝她,菜單項選中項狀態(tài)

<template>
  <div>
    <a-menu
      theme="dark"
      mode="inline"
      @openChange="onOpenChange"
      width="auto"
      :openKeys="openKeys"
      :selectedKeys="selectedKey"
      :defaultSelectedKeys="selectedKey">
      <a-sub-menu
        v-if="item.child"
        v-for="item of sidebars"
        :key="item.key">
        <template slot="title">{{ item.name }}</template>
        <a-menu-item
          v-for="subItem of item.child"
          :key="subItem.key"
          @click="$router.push({name:subItem.key})">{{ subItem.name }}</a-menu-item>
      </a-sub-menu>
      <a-menu-item
        v-if="!item.child"
        v-for="item of sidebars"
        :key="item.key"
        @click="$router.push({name:item.key})">{{ item.name }}</a-menu-item>
    </a-menu>
  </div>
</template>
<script>
import { SIDERBARS } from '@/const'
export default {
  name: 'Sidebar',
  data () {
    return {
      sidebars: [],
      allSubmenuKeys: [],
      openKeys: [], // 展開父菜單項
      selectedKey: [] // 選中子菜單項
    }
  },
  created () {
    // 頁面刷新 菜單項激活狀態(tài)
    this.updateSidebars()
  },
  watch: {
    '$route.name': function () {
    // 路由跳轉(zhuǎn) 菜單項激活狀態(tài)
      this.updateSidebars()
    }
  },
  methods: {
    onOpenChange (openKeys) {
      // 只展示當(dāng)前父級菜單
      const lastOpenKey = openKeys.find(key => this.openKeys.indexOf(key) === -1)
      if (this.allSubmenuKeys.indexOf(lastOpenKey) === -1) {
        this.openKeys = openKeys
      } else {
        this.openKeys = lastOpenKey ? [lastOpenKey] : []
      }
    },
    updateSidebars () {
      let that = this
      if (this.$route.path.indexOf('admin') !== -1) {
        this.sidebars = SIDERBARS.admin
      } else if (this.$route.path.indexOf('operation') !== -1) {
        this.sidebars = SIDERBARS.operation
      } else {
        this.sidebars = SIDERBARS.hr
      }
      _.forEach(this.sidebars, function (val, ind) {
        that.allSubmenuKeys.push(val.key)
      })
      if (this.$route.meta.parent) {
        this.openKeys = [this.$route.meta.parent]
      }
      if (this.$route.name) {
        this.$set(this, 'selectedKey', [this.$route.name])
      }
    }
  }
}
</script>

8浇坐、form表單編輯狀態(tài)初始化 通過配置mapPropsToFields

let options = info.chainOrgName ? {
      mapPropsToFields: () => {
        return {
          chainOrgName: this.$form.createFormField({
            value: info.chainOrgName
          }),
          orgDomain: this.$form.createFormField({
            value: info.orgDomain
          }),
          description: this.$form.createFormField({
            value: info.description
          })
        }
      }
    } : {}
    this.nodeForm = this.$form.createForm(this, options)
  },
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市黔宛,隨后出現(xiàn)的幾起案子近刘,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件觉渴,死亡現(xiàn)場離奇詭異介劫,居然都是意外死亡,警方通過查閱死者的電腦和手機案淋,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門座韵,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人踢京,你說我怎么就攤上這事誉碴。” “怎么了漱挚?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵翔烁,是天一觀的道長。 經(jīng)常有香客問我旨涝,道長蹬屹,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任白华,我火速辦了婚禮慨默,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘弧腥。我一直安慰自己厦取,他們只是感情好,可當(dāng)我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布管搪。 她就那樣靜靜地躺著虾攻,像睡著了一般。 火紅的嫁衣襯著肌膚如雪更鲁。 梳的紋絲不亂的頭發(fā)上霎箍,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音澡为,去河邊找鬼漂坏。 笑死,一個胖子當(dāng)著我的面吹牛媒至,可吹牛的內(nèi)容都是我干的顶别。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼拒啰,長吁一口氣:“原來是場噩夢啊……” “哼驯绎!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起谋旦,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤剩失,失蹤者是張志新(化名)和其女友劉穎骗随,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體赴叹,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡鸿染,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了乞巧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片涨椒。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖绽媒,靈堂內(nèi)的尸體忽然破棺而出蚕冬,到底是詐尸還是另有隱情,我是刑警寧澤是辕,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布囤热,位于F島的核電站,受9級特大地震影響获三,放射性物質(zhì)發(fā)生泄漏旁蔼。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一疙教、第九天 我趴在偏房一處隱蔽的房頂上張望棺聊。 院中可真熱鬧,春花似錦贞谓、人聲如沸限佩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽祟同。三九已至,卻和暖如春理疙,著一層夾襖步出監(jiān)牢的瞬間晕城,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工沪斟, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留广辰,地道東北人暇矫。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓主之,卻偏偏與公主長得像,于是被迫代替她去往敵國和親李根。 傳聞我的和親對象是個殘疾皇子槽奕,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,979評論 2 355