色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

vue 實現(xiàn)拖拽動態(tài)生成組件的需求

瀏覽:101日期:2022-09-30 11:06:27
產(chǎn)品需求

開完產(chǎn)品需求會議,遇到了一個需求,首先頁面分成兩欄布局,左側(cè)展示數(shù)據(jù)組件,支持拖拽排序,點擊按鈕清除組件。右側(cè)支持將組件的縮略圖拖拽至左側(cè)生成一個新的組件。

思路

對于動態(tài)生成組件來說每一次都要是生成全新的一個組件,那么就可以把 組件放進(jìn)函數(shù)當(dāng)中 return。在JSX中調(diào)用函數(shù),每次調(diào)用函數(shù)都會返回一個全新的組件。這對React來說非常簡單,但是對于Vue來說,直接將組件返回是不可能的。盡管這個 return 寫法不適合Vue,但是我們不可否認(rèn),思路是非常正確的,所以我們應(yīng)該考慮一個別的寫法。至于動態(tài)的生成組件,我們必須以數(shù)據(jù)來驅(qū)動組件的生成。對于拖拽組件的排序,直接使用拖拽庫就OK了!!

面臨的問題 拖拽庫的選擇 如何生成組件 以數(shù)據(jù)驅(qū)動動態(tài)生成組件 拖拽庫的選擇

拖拽庫在這里我選擇的是項目中存在的一個拖拽庫 Vue.Draggable 點這里鏈接查看 Start 14.9K 蠻不錯的。如果你們的Vue項目中沒有用到這個拖拽庫,你們可以自行參考本片文章的設(shè)計思路。

如何生成組件

在這里我使用的是 Vue.extend() 不清楚如何使用的小伙伴請在官方文檔中查看過后再來學(xué)習(xí)這篇文章 Vue.extend 。 接下來我們創(chuàng)建一個js文件,用來書寫創(chuàng)建組件的代碼。

生成組件

/* generateComponents.js 文件名 */import Vue from 'vue';// 想要動態(tài)生成的組件,先引入這個文件。import components1 from './components/TestCom1.vue';import components2 from './components/TestCom2.vue';// 將組件的名稱和組件做一個對應(yīng)Mapconst comMap = { components1, components2,};// 接收生成組件需要的組件名稱,和想要傳遞給組件的// props, 和 事件const ReturnNewCom = function ({ props, on }) { const { comItem: { name }, } = props; const newComponent = Vue.extend({ render(createElement) { // 使用傳進(jìn)來的組件name來決定渲染哪一個組件。 return createElement(comMap[name], {props,on, }); }, }); return new newComponent();};export default ReturnNewCom;組件

在這里我們書寫兩個組件,用來演示這個Demo,分別為components1.vue,components2.vue。

/*components1.vue*/<template> <div class='widget-wrapper'> <header class='header'>{{ comDetail.name }}--{{ comDetail.id }}</header> <h1>查詢條件:{{ queryObj }}</h1> <button @click='handleDelete'>清除</button> </div></template><script>export default { data() { return { comDetail: this.comItem, _queryObj: this.queryObj, }; }, props: { comItem: { type: Object, default() {return { id: 0, name: '',}; }, }, queryObj: { // 可以接收父組件傳遞的曬選條件,必須是Object type: Object, default() {// 定義默認(rèn)的查詢條件。return { num: 0,}; }, }, }, watch: { comItem(val) { this.comDetail = val; return val; }, queryObj(val) { this._queryObj = val; return val; }, }, created() { console.log('data -> this.comItem', this.comItem); }, methods: { handleDelete() { // 刪除組件方法 this.$el.remove(); // 調(diào)用父組件的函數(shù)。修改父組件中的 leftComList 數(shù)組的數(shù)據(jù)。 this.$emit('handleDelete', this.comDetail); }, },};</script><style scoped>.widget-wrapper { background: #ff7b7b; border-radius: 12px; overflow: hidden; width: 200px;}.header { height: 50px; padding: 0 15px;}</style>

其實components2.vue文件中的代碼和components1.vue文件的代碼類似,唯一不同的地方就是背景顏色不一樣。

以數(shù)據(jù)驅(qū)動動態(tài)組件的生成

接下來就得使用Vue.Draggable 這個拖拽庫進(jìn)行拖拽和數(shù)據(jù)的修改。 我們可以直接在App.vue文件中直接書寫。

/* App.vue */<template> <div class='dragCom'> <h1>{{ leftComList }}</h1> <button @click='queryObj.num++'>改變查詢條件</button> <div class='body'> <div class='left'><draggable :list='leftComList' :group='’people’'> <div ref='comBody' v-for='({ name, id }, index) in leftComList' :key='id' > <!-- 循環(huán) leftComList 數(shù)組,利用數(shù)據(jù)來渲染組件, 將動態(tài)生成的數(shù)組添加到這個DOM元素當(dāng)中。 --> {{ handleAddCom({props: { comItem: { name, id }, queryObj },index, }) }} </div></draggable> </div> <div class='right'><draggable :list='rightComList' :group='{ name: ’people’, pull: ’clone’, put: false }' :clone='handleCloneDog'> <div v-for='element in rightComList' :key='element.id'> {{ element.name }} </div> <!-- 右側(cè)的 卡片 數(shù)據(jù), rightComList 數(shù)組對象中的name就對應(yīng)了generateComponents.js 中的ComMap中的屬性 --></draggable> </div> </div> </div></template><script>import draggable from 'vuedraggable';import CreateCom from './generateComponents';export default { components: { draggable, }, data() { return { rightComList: [{ id: Math.random(), name: 'components1',},{ id: Math.random(), name: 'components2',}, ], leftComList: [], // 存儲驅(qū)動動態(tài)生成組件的數(shù)據(jù)。 comMap: new Map(), // 主要的作用就是用來記錄 // 組件有沒有渲染到 這個DOM中, // 如果渲染了就不能再往進(jìn)添加子元素了。 queryObj: {// 主要的作用就是向子組件傳遞查詢條件num: 0, }, }; }, beforeDestroy() { // 清除 記錄 的數(shù)據(jù) this.comMap.clear(); }, methods: { handleAddCom({ index, on = {}, props = { comItem: { name: '', id: 0 } } }) { const {comItem: { id }, } = props; this.$nextTick(() => {// 獲取該節(jié)點的子節(jié)點的長度const childNodesLength = this.$refs.comBody[index].childNodes.length;// 獲取comBody 這個DOM 數(shù)組的長度const comLine = this.$refs.comBody.length;if (!this.comMap.get(id)) { // 如果沒有渲染過組件 // 1. 調(diào)用 CreateCom 方法 創(chuàng)建組件。 并傳遞 props 和 事件 const com = CreateCom({ props, on: { handleDelete: this.handleDeleteCom, ...on, }, }); // 2. 生成組件 com.$mount(); if (childNodesLength === 2) { // 如果要添加到兩個組件中間。那么就將新生成的組件DOM位置進(jìn)行修改放到中間。 // 將最后的組件DOM添加到正確的位置 this.$refs.comBody.splice( index, 0, this.$refs.comBody[comLine - 1] ); } // 3. 將生成的組件添加到改DOM中。 this.$refs.comBody[index].appendChild(com.$el); // 4. 記錄該組件實現(xiàn)了渲染。 this.comMap.set(id, true);} else { // 該位置的組件已經(jīng)渲染,不需要再次渲染直接返回 return;} }); }, handleDeleteCom({ id }) { // 傳遞給子組件刪除的方法,根據(jù)組件的id來刪除數(shù)據(jù) const index = this.leftComList.findIndex((item) => item.id === id); if (~index) {// 如果存在這個id的組件,就刪除this.leftComList.splice(index, 1); } }, handleCloneDog(item) { // 給 leftComList 數(shù)組添加數(shù)據(jù) return {...item,id: Math.random(), }; }, },};</script><style>.dragCom { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; margin-top: 60px;}.body { width: 100%; height: 800px; display: flex; justify-content: space-between;}.left { flex: 1; height: 800px; border: 1px solid pink;}.right { width: 20%; height: 800px;}.card { height: 50px; background-color: #40cec7; margin: 12px 0; font-size: 12px; line-height: 50px; cursor: pointer;}.comCard { margin: 12px; display: inline-block;}</style>

這樣就實現(xiàn)了動態(tài)的組件渲染和拖拽排序。

效果

vue 實現(xiàn)拖拽動態(tài)生成組件的需求

源碼

想要嘗試的同學(xué)可以自行下載本文的代碼源碼github

以上就是vue 實現(xiàn)拖拽動態(tài)生成組件的需求的詳細(xì)內(nèi)容,更多關(guān)于vue拖拽動態(tài)生成組件的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 国产国语在线播放视频 | 国产精品亚洲一区二区三区 | 不卡一级毛片免费高清 | 久草视频中文在线 | 91久久香蕉国产线看观看软件 | 国产爽的冒白浆的视频高清 | 国产精品美女一区二区三区 | 中文字幕在线看视频一区二区三区 | 三级全黄a | 手机国产精品一区二区 | 黄色毛片视频校园交易 | 国产午夜亚洲精品理论片不卡 | 最新福利片v国产片 | 亚洲综合色一区二区三区另类 | 国内主播福利视频在线观看 | 九九精品激情在线视频 | 亚洲一区免费在线观看 | 精品手机在线 | 久久99久久精品视频 | 中文字幕日韩欧美一区二区三区 | 美女与男人对肌免费网站 | 亚洲欧美一区二区三区不卡 | 亚洲成人性视频 | 成 人 黄 色 免费播放 | 国产亚洲精品xxx | 久久久久欧美精品网站 | 国产免费播放一区二区 | 亚洲日韩精品欧美一区二区 | 日韩高清免费观看 | 日韩激情无码免费毛片 | 亚洲国产欧美在线人成精品一区二区 | 中文字幕日韩精品亚洲七区 | 九九久久国产精品 | 日本欧美不卡一区二区三区在线 | 久久精品爱国产免费久久 | 精品视频自拍 | 成人免费xxxxx在线视频 | 亚洲一级毛片在线播放 | 亚洲综合久久久久久888 | 国产高清免费 | 中文字幕一区二区小泽玛利亚 |