欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

淺談Vue使用Cascader級(jí)聯(lián)選擇器數(shù)據(jù)回顯中的坑

 更新時(shí)間:2020年10月31日 15:34:51   作者:Raytheon107  
這篇文章主要介紹了淺談Vue使用Cascader級(jí)聯(lián)選擇器數(shù)據(jù)回顯中的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧

業(yè)務(wù)場(chǎng)景

由于項(xiàng)目需求,需要對(duì)相關(guān)類(lèi)目進(jìn)行多選,類(lèi)目數(shù)據(jù)量又特別大,業(yè)務(wù)邏輯是使用懶加載方式加載各級(jí)類(lèi)目數(shù)據(jù),編輯時(shí)回顯用戶選擇的類(lèi)目。

問(wèn)題描述

使用Cascader級(jí)聯(lián)選擇器過(guò)程中主要存在的應(yīng)用問(wèn)題如下:

1、由于在未渲染節(jié)點(diǎn)數(shù)據(jù)的情況下編輯時(shí)無(wú)法找到對(duì)應(yīng)的類(lèi)目數(shù)據(jù)導(dǎo)致無(wú)法回顯,如何自動(dòng)全部加載已選擇類(lèi)目的相關(guān)節(jié)點(diǎn)數(shù)據(jù);

2、提前加載數(shù)據(jù)后,點(diǎn)擊相應(yīng)父級(jí)節(jié)點(diǎn)出現(xiàn)數(shù)據(jù)重復(fù)等;

3、使用多個(gè)數(shù)據(jù)源相同的級(jí)聯(lián)選擇器,產(chǎn)生只能成功響應(yīng)一個(gè)加載子級(jí)節(jié)點(diǎn)數(shù)據(jù);

4、Vue中級(jí)聯(lián)選擇器相應(yīng)數(shù)據(jù)完成加載,依然無(wú)法回顯。

解決思路

Cascader級(jí)聯(lián)選擇器在需要回顯的節(jié)點(diǎn)數(shù)據(jù)都存在的情況下,方可完成回顯,首先想到的是把選中節(jié)點(diǎn)相關(guān)的數(shù)據(jù)全部獲取到即可,遍歷已選擇的節(jié)點(diǎn)數(shù)據(jù),遍歷加載相對(duì)應(yīng)的數(shù)據(jù)。(如果多個(gè)級(jí)聯(lián)選擇器使用同一個(gè)數(shù)據(jù)源,使用深拷貝將數(shù)據(jù)分開(kāi),避免產(chǎn)生影響)

由于是級(jí)聯(lián)的數(shù)據(jù)懶加載,需要每一級(jí)相應(yīng)的節(jié)點(diǎn)數(shù)據(jù)加載完進(jìn)行下一步,故使用ES6中的Promise,將子級(jí)節(jié)點(diǎn)數(shù)據(jù)加載封裝成一個(gè)Promise,待Promise執(zhí)行完成,對(duì)列表數(shù)據(jù)遍歷獲取完成后返回即可。

getChildrenList (fid, level = 0) {
 return new Promise((resolve, reject) => {
 API.getCategory({ fid: fid, level: level }).then(
  res => {
  if (res) {
  if (res.code === 0 && res.result) {
  resolve(res.result)
  }
  }
  }
 )
 })
 },
let twolist = this.getChildrenList(codeArr[0], 1)
let thirdlist = this.getChildrenList(codeArr[1], 2)
Promise.all([twolist, thirdlist]).then((data) => {
 ...
})

Vue2的雙向數(shù)據(jù)綁定使用ES2015中的Object.defineProperty(),該方法無(wú)法檢測(cè)到Array中的深層數(shù)據(jù)變化,需要使用$set來(lái)觸發(fā)列表數(shù)據(jù)的更新。

一個(gè)三級(jí)級(jí)聯(lián)選擇器,首先獲取全部一級(jí)類(lèi)目,二級(jí)類(lèi)目和三級(jí)類(lèi)目采用懶加載,獲取數(shù)據(jù)的步驟如下:

1、獲取全部一級(jí)類(lèi)目;

2、由于使用異步數(shù)據(jù)加載,使用Promise進(jìn)行數(shù)據(jù)請(qǐng)求;

3、根據(jù)已選擇的類(lèi)目獲取相關(guān)聯(lián)的二級(jí)類(lèi)目和三級(jí)類(lèi)目;

4、數(shù)據(jù)請(qǐng)求完成,使用$set觸發(fā)列表數(shù)據(jù)更新,在$nextTick中完成數(shù)據(jù)你回顯。

相關(guān)代碼

<template>
 <div>
 <el-cascader
 placeholder="請(qǐng)選擇所屬類(lèi)目"
 :options="categoryList"
 :show-all-levels="false"
 v-model="category"
 collapse-tags
 :props="{
 multiple: true,
 value: 'code',
 label: 'name',
 children: 'children',
 ...props,
 }"
 />
 <el-cascader
 placeholder="請(qǐng)選擇所屬類(lèi)目"
 :options="secondCategoryList"
 :show-all-levels="false"
 v-model="secondCategory"
 collapse-tags
 :props="{
 multiple: true,
 value: 'code',
 label: 'name',
 children: 'children',
 ...props,
 }"
 />
 </div>
</template>
 
<script>
export default {
 data () {
 return {
 categoryList: [],
 category: [],
 secondCategoryList: [],
 secondCategory: [],
 props: {
 lazy: true,
 // checkStrictly: true, // 父子級(jí)節(jié)點(diǎn)關(guān)聯(lián)
 async lazyLoad (node, reso) {
  const { level, data } = node
  if (data && data.children && data.children.length !== 0) {
  return reso(node)
  }
  if (data && data.leaf) {
  return reso([])
  }
  const lv3Code = data ? data.code : null
  setTimeout(() => {
  lv3Code && API.getCategory({ fid: lv3Code, level: level }).then(
  res => {
  if (res) {
   if (res.code === 0 && res.result) {
   const nodes = res.result.map(item => ({ leaf: level === 2, ...item, children: [] }))
   data.children = nodes
   reso(nodes)
   } else {
   reso([])
   }
  }
  }
  )
  }, 500)
 }
 }
 }
 },
 mounted () {
 this.getCategory()
 this.initData()
 },
 methods: {
 initData () {
 let _that = this
 異步獲取編輯數(shù)據(jù)。。。
 .then(result => {
 // 此處僅處理result中firstCategory和secondCategory均不為空的情況
 let firstTemp = _that.getCategoryListFormat(result.firstCategory, _that.categoryList)
 let secondTemp = _that.getCategoryListFormat(result.secondCategory, _that.secondCategoryList)
 let promiseArr = [firstTemp, secondTemp].filter(_ => _)
 Promise.all(promiseArr).then((formatRes) => {
  // 觸發(fā)列表數(shù)據(jù)響應(yīng)
  this.$set(_that.categoryList, formatRes[0].tragetCategoryList)
  this.$set(_that.secondCategoryList, formatRes[1].tragetCategoryList)
  _that.$nextTick(() => {
  // 數(shù)據(jù)加載完成后,在下一次循環(huán)中回顯
  _that.category = formatRes[0].category
  _that.secondCategory = formatRes[1].category
  })
 })
 })
 },
 getCategoryListFormat (categorySelectList, tragetCategoryList) {
 return new Promise((resolve, reject) => {
 const category = []
 let flag = 0
 let counter = categorySelectList.length
 
 categorySelectList.forEach(v => { // 遍歷已選擇節(jié)點(diǎn)數(shù)據(jù)
  const oneNode = v
  const twoNode = v.children
  const threeNode = v.children.children
  const codeArr = [oneNode.code, twoNode.code, threeNode.code]
  category.push(codeArr)
  twoNode.children = twoNode.children ? twoNode.children : []
  let twolist = this.getChildrenList(codeArr[0], 1)
  let thirdlist = this.getChildrenList(codeArr[1], 2)
  Promise.all([twolist, thirdlist]).then((data) => {
  let twochildren = data[0]
  let threechildren = data[1]
  threechildren = threechildren.map(item => ({ leaf: true, ...item })) // 三級(jí)節(jié)點(diǎn)設(shè)置成葉子節(jié)點(diǎn)
  twoNode.children = threechildren
  tragetCategoryList.forEach(w => { // 遍歷列表添加相應(yīng)節(jié)點(diǎn)數(shù)據(jù)
  if (w.code === oneNode.code) {
  if (!w.children) {
   w.children = twochildren
  }
  w.children.forEach(item => {
   if (item.code === twoNode.code) {
   item.children = twoNode.children
   }
  })
  }
  })
  flag++
  if (flag === counter) {
  resolve({ tragetCategoryList, category })
  }
  })
 })
 })
 },
 getChildrenList (fid, level = 0) {
 return new Promise((resolve, reject) => {
 API.getCategory({ fid: fid, level: level }).then(
  res => {
  if (res) {
  if (res.code === 0 && res.result) {
  resolve(res.result)
  }
  }
  }
 )
 })
 },
 getCategory(fid = 0, level = 0) {
 API.getCategory({ fid: fid, level: level })
 .then(
  res => {
  if (res) {
  if (res.code == 0 && res.result) {
  this.categoryList = this.deepClone(res.result);
  }
  }
  }
 )
 },
 deepClone (source) { // 深拷貝
 if (!source && typeof source !== 'object') {
 throw new Error('error arguments', 'shallowClone')
 }
 const targetObj = source.constructor === Array ? [] : {}
 Object.keys(source).forEach(keys => {
 if (source[keys] && typeof source[keys] === 'object') {
  targetObj[keys] = source[keys].constructor === Array ? [] : {}
  targetObj[keys] = deepClone(source[keys])
 } else {
  targetObj[keys] = source[keys]
 }
 })
 return targetObj
 }
 }
}
</script> 
<style lang="less" scoped> 
</style>

補(bǔ)充知識(shí):Ant Design 級(jí)聯(lián)選擇的一種寫(xiě)法

簡(jiǎn)單記錄類(lèi)似省、市、區(qū)或品牌、車(chē)系、車(chē)型等多級(jí)結(jié)構(gòu),級(jí)聯(lián)選擇添加并展示的一種寫(xiě)法:

import React from 'react';
import {Button, Form, message, Row, Tag,Select,Col} from 'antd';
import request from "../../../../utils/request";
const FormItem = Form.Item;
const Option = Select.Option;
 
class CarSeriesCascader extends React.Component {
 
 constructor(props) {
  super(props);
  this.state = {
   defaultBrandList:[],
   selectedCarModelList: props.carModelList ? props.carModelList : [],
   brandCode:null,
   carModelList:[],
   carId:null,
   modelCode:null,
   modelName:null
  }
 }
 
 componentDidMount() {
  let promise = request(`/car/getBrandList`);
  promise.then(result =>{
  if(result != null){
   this.setState({
   defaultBrandList:result
   });
  }else{
   message.error("獲取品牌數(shù)據(jù)失敗");
  }
  }).catch(err => {
   message.error("獲取品牌數(shù)據(jù)失敗");
  });
  // this.setState({
  // selectedCarModelList:(this.props.carModelList ? this.props.carModelList : [])
  // });
  this.handleChange(this.state.selectedCarModelList);
 }
 
 getLimitList = (selectedCarModelList) => {
  let limitList = selectedCarModelList.map((carModel,index) => {
   let limitItem = {};
   limitItem.modelName = carModel.modelName;
   limitItem.modelCode = carModel.modelCode;
   limitItem.carId = carModel.carId;
   return limitItem;
  });
  return limitList;
 } 
 
 addCarModel = () => {
  let addCarModel = {};
  let selectedCarModelList = this.state.selectedCarModelList;
  // 選中車(chē)型號(hào)
  if (this.state.carId !== null) {
   // 檢查車(chē)型是否已選中
   for (let index = this.state.selectedCarModelList.length - 1; index >= 0; index--) {
    let carModel = this.state.selectedCarModelList[index];
    if (carModel.carId == this.state.carId) {
     message.error("車(chē)型已在已選車(chē)型中");
     return;
    }
   }
   addCarModel.carId = this.state.carId;
   addCarModel.modelCode = this.state.modelCode;
   addCarModel.modelName = this.state.modelName;
   selectedCarModelList.push(addCarModel);
  } else {
   return;
  }
  this.handleChange(selectedCarModelList);
  this.setState({
   selectedCarModelList
  });
 }
 
 handleChange = (selectedCarModelList) => {
  if (this.props.onChange) {
   let limitList = this.getLimitList(selectedCarModelList);
   this.props.onChange(limitList);
  }
 }
 
 deleteTag = (limitCode) => {
  debugger
  let selectedCarModelList = this.state.selectedCarModelList;
  selectedCarModelList = selectedCarModelList.filter(carModel => !(carModel.modelCode === limitCode));
  this.handleChange(selectedCarModelList);
  this.setState({selectedCarModelList});
 }
 
 //品牌變化
 brandChange = (brandName) => {
 this.state.defaultBrandList.map((item, index) => {
  if (item.brandName == brandName) {
  let promise = request(`/car/getModelList?brandCode=` + item.brandCode);
  promise.then(result =>{
   if(result != null){
   this.setState({
    brandCode:item.brandCode,
    carModelList:result
   });
   }else{
   message.error("獲取車(chē)型數(shù)據(jù)失敗");
   }
  }).catch(err => {
   message.error("獲取車(chē)型數(shù)據(jù)失敗:");
  });
  }
 });
 }
 
 //車(chē)型變化
 modelChange = (modelName) => {
 this.props.form.setFieldsValue({modelName: null});
 let _this = this;
 this.state.carModelList.map((item, index) => {
  if (item.modelName == modelName) {
  console.log(item);
  this.setState({
  modelCode : item.modelCode,
  carId : item.carId,
  modelName : item.modelName
  });
  }
 });
 }
 
 render() {
  const {getFieldDecorator} = this.props.form;
  //品牌名稱(chēng)列表
  let allBrandListOption = this.state.defaultBrandList != null ? this.state.defaultBrandList.map((item, index) => {
  return <Option value={item.brandName} key={index}>{item.brandName}</Option>;
  }) : null;
 
  //車(chē)型名稱(chēng)列表
  let allModelListOption = this.state.carModelList != null ? this.state.carModelList.map((item, index) => {
  return <Option value={item.modelName} key={index}>{item.modelName}</Option>;
  }) : null;
 
  const {
   closable=true,
  } = this.props;
 
  const existCarModel = [];
  const limitList = this.getLimitList(this.state.selectedCarModelList);
  for (let index = limitList.length - 1; index >= 0; index--) {
   let limitItem = limitList[index];
   existCarModel.push(<Tag
    key={limitItem.modelCode}
    closable={closable}
    onClose={(e) => {
     e.preventDefault();
     this.deleteTag(limitItem.modelCode);
    }}
   >{limitItem.modelName}</Tag>);
  }
 
  return (
   <div>
    <Row>
     <FormItem >
      {getFieldDecorator('brandName', {
      rules: [{
       message: '請(qǐng)選擇品牌'
      }],
      })(
      <Select
       placeholder="品牌"
       dropdownMatchSelectWidth={false}
       onChange={this.brandChange}
       style={{ marginRight: 10, width: 100 }}>
       <Option value={null}>選擇品牌</Option>
       {allBrandListOption}
      </Select>
      )}
      {getFieldDecorator('modelName', {
      rules: [{
       message: '請(qǐng)選擇車(chē)型'
      }],
      })(
      <Select
       placeholder="車(chē)型"
       dropdownMatchSelectWidth={false}
       onChange={this.modelChange}
       style={{ marginRight: 10, width: 260 }}>
       <Option value={null}>選擇車(chē)型</Option>
       {allModelListOption}
      </Select>
      )}
      <Button type={"primary"} icon={"plus"} onClick={this.addCarModel}>添加車(chē)型</Button>
     </FormItem>
    </Row>
    <Row>
     {existCarModel}
    </Row>
   </div>
  )
 }
} 
export default Form.create()(CarSeriesCascader);

以上這篇淺談Vue使用Cascader級(jí)聯(lián)選擇器數(shù)據(jù)回顯中的坑就是小編分享給大家的全部?jī)?nèi)容了,希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • vue 之 css module的使用方法

    vue 之 css module的使用方法

    這篇文章主要介紹了vue 之 css module的使用方法,css module目的為所有類(lèi)名重新生成類(lèi)名,有效避開(kāi)了css權(quán)重和類(lèi)名重復(fù)的問(wèn)題,非常具有實(shí)用價(jià)值,需要的朋友可以參考下
    2018-12-12
  • vue-cli項(xiàng)目無(wú)法用本機(jī)IP訪問(wèn)的解決方法

    vue-cli項(xiàng)目無(wú)法用本機(jī)IP訪問(wèn)的解決方法

    今天小編就為大家分享一篇vue-cli項(xiàng)目無(wú)法用本機(jī)IP訪問(wèn)的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • axios攔截設(shè)置和錯(cuò)誤處理方法

    axios攔截設(shè)置和錯(cuò)誤處理方法

    下面小編就為大家分享一篇axios攔截設(shè)置和錯(cuò)誤處理方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2018-03-03
  • Vue-cli-webpack搭建斗魚(yú)直播步驟詳解

    Vue-cli-webpack搭建斗魚(yú)直播步驟詳解

    斗魚(yú)直播是比較火的直播視頻,想必大家都看過(guò)吧。這篇文章主要介紹了Vue-cli-webpack搭建斗魚(yú)直播步驟詳解,需要的朋友可以參考下
    2017-11-11
  • vue通過(guò)elementUI組件實(shí)現(xiàn)圖片預(yù)覽效果

    vue通過(guò)elementUI組件實(shí)現(xiàn)圖片預(yù)覽效果

    我們?cè)陂_(kāi)發(fā)中經(jīng)常會(huì)遇到通過(guò)點(diǎn)擊某個(gè)按鈕或者文字實(shí)現(xiàn)圖片的預(yù)覽功能,這里我們分別介紹vue2和vue3里面如何實(shí)現(xiàn)圖片預(yù)覽方法,需要的朋友可以參考下
    2023-09-09
  • Vue父子之間值傳遞的實(shí)例教程

    Vue父子之間值傳遞的實(shí)例教程

    這篇文章主要給大家介紹了關(guān)于Vue父子之間值傳遞的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Vue具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-07-07
  • vue-cli V3.0版本的使用詳解

    vue-cli V3.0版本的使用詳解

    這篇文章主要介紹了vue-cli V3.0版本的使用詳解,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-10-10
  • vue實(shí)現(xiàn)五子棋游戲

    vue實(shí)現(xiàn)五子棋游戲

    這篇文章主要為大家詳細(xì)介紹了vue實(shí)現(xiàn)五子棋游戲,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2020-05-05
  • vue中的生命周期及鉤子函數(shù)

    vue中的生命周期及鉤子函數(shù)

    這篇文章主要介紹了vue中的生命周期及鉤子函數(shù),Vue?實(shí)例有一個(gè)完整的生命周期,也就是從開(kāi)始創(chuàng)建、初始化數(shù)據(jù)、編譯模板、掛載?Dom、渲染,下面文章詳細(xì)介紹,需要的朋友可以參考一下
    2021-12-12
  • 淺談element中InfiniteScroll按需引入的一點(diǎn)注意事項(xiàng)

    淺談element中InfiniteScroll按需引入的一點(diǎn)注意事項(xiàng)

    這篇文章主要介紹了淺談element中InfiniteScroll按需引入的一點(diǎn)注意事項(xiàng),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-06-06

最新評(píng)論