电脑知识|欧美黑人一区二区三区|软件|欧美黑人一级爽快片淫片高清|系统|欧美黑人狂野猛交老妇|数据库|服务器|编程开发|网络运营|知识问答|技术教程文章 - 好吧啦网

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

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

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

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

思路

對于動態(tài)生成組件來說每一次都要是生成全新的一個組件,那么就可以把 組件放進函數(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) { // 使用傳進來的組件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 這個拖拽庫進行拖拽和數(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中, // 如果渲染了就不能再往進添加子元素了。 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位置進行修改放到中間。 // 將最后的組件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)生成組件的需求的詳細內(nèi)容,更多關(guān)于vue拖拽動態(tài)生成組件的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Vue
相關(guān)文章:
主站蜘蛛池模板: 定时排水阀/排气阀-仪表三通旋塞阀-直角式脉冲电磁阀-永嘉良科阀门有限公司 | 济南拼接屏_山东液晶拼接屏_济南LED显示屏—维康国际官网 | 吸污车_吸粪车_抽粪车_电动三轮吸粪车_真空吸污车_高压清洗吸污车-远大汽车制造有限公司 | 水冷式工业冷水机组_风冷式工业冷水机_水冷螺杆冷冻机组-深圳市普威机械设备有限公司 | 柴油机_柴油发电机_厂家_品牌-江苏卡得城仕发动机有限公司 | 西子馋火锅鸡加盟-太原市龙城酉鼎餐饮管理有限公司 | 派财经_聚焦数字经济内容服务平台 | 加盟店-品牌招商加盟-创业项目商机平台| 电动球阀_不锈钢电动球阀_电动三通球阀_电动调节球阀_上海湖泉阀门有限公司 | 布袋除尘器|除尘器设备|除尘布袋|除尘设备_诺和环保设备 | 复合土工膜厂家|hdpe防渗土工膜|复合防渗土工布|玻璃纤维|双向塑料土工格栅-安徽路建新材料有限公司 | 沈阳缠绕膜价格_沈阳拉伸膜厂家_沈阳缠绕膜厂家直销 | 祝融环境-地源热泵多恒系统高新技术企业,舒适生活环境缔造者! | 北京银联移动POS机办理_收银POS机_智能pos机_刷卡机_收银系统_个人POS机-谷骐科技【官网】 | 成都网站建设制作_高端网站设计公司「做网站送优化推广」 | 福建珂朗雅装饰材料有限公司「官方网站」 | 多功能三相相位伏安表-变压器短路阻抗测试仪-上海妙定电气 | 预制围墙_工程预制围墙_天津市瑞通建筑材料有限公司 | 3A别墅漆/3A环保漆_广东美涂士建材股份有限公司【官网】 | 步入式高低温测试箱|海向仪器| 西门子伺服控制器维修-伺服驱动放大器-828D数控机床维修-上海涌迪 | 丹佛斯压力传感器,WISE温度传感器,WISE压力开关,丹佛斯温度开关-上海力笙工业设备有限公司 | 液氮罐_液氮容器_自增压液氮罐-北京君方科仪科技发展有限公司 | 广州办公室设计,办公室装修,写字楼设计,办公室装修公司_德科 | 成都网站建设制作_高端网站设计公司「做网站送优化推广」 | 预制舱-电力集装箱预制舱-模块化预制舱生产厂家-腾达电器设备 | 淄博不锈钢无缝管,淄博不锈钢管-鑫门物资有限公司 | 翅片管散热器价格_钢制暖气片报价_钢制板式散热器厂家「河北冀春暖气片有限公司」 | 集装箱标准养护室-集装箱移动式养护室-广州璟业试验仪器有限公司 | 播音主持培训-中影人教育播音主持学苑「官网」-中国艺考界的贵族学校 | 合同书格式和范文_合同书样本模板_电子版合同,找范文吧 | 汝成内控-行政事业单位内部控制管理服务商| 贝朗斯动力商城(BRCPOWER.COM) - 买叉车蓄电池上贝朗斯商城,价格更超值,品质有保障! | 武汉高低温试验机-现货恒温恒湿试验箱-高低温湿热交变箱价格-湖北高天试验设备 | 脱硝喷枪-氨水喷枪-尿素喷枪-河北思凯淋环保科技有限公司 | 真空搅拌机-行星搅拌机-双行星动力混合机-广州市番禺区源创化工设备厂 | 科箭WMS仓库管理软件-TMS物流管理系统-科箭SaaS云服务 | 北京亦庄厂房出租_经开区产业园招商信息平台| 耐酸泵,耐酸泵厂家-淄博华舜耐腐蚀真空泵| 海峰资讯 - 专注装饰公司营销型网站建设和网络营销培训 | 顶呱呱交易平台-行业领先的公司资产交易服务平台 |