Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >vue 拖动

vue 拖动

作者头像
tianyawhl
发布于 2021-05-18 02:52:48
发布于 2021-05-18 02:52:48
1.9K00
代码可运行
举报
文章被收录于专栏:前端之攻略前端之攻略
运行总次数:0
代码可运行

需求:有2个模板,可以切换模板,组件拖动到一个模板中并预览页面,左边是组件列表,右边是可选择的模板

需要有几个vue 页面

1、home.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <div class="container">
    <div @dragstart="handleDragStart" style="float:left;">
      <div v-for="(item,index) in componentList" :key="index" draggable :data-index="index">
        <i class="fa fa fa-bar-chart"></i>
        <span>{{item.label}}</span>
      </div>
    </div>
    <div style="margin-left:150px;">
      <div class="template">
        选择模板
        <el-button @click="selectTemplate(1)">模板1</el-button>
        <el-button @click="selectTemplate(2)">模板2</el-button>
      </div>
      
      <component v-if="currentEditeTemplate" :is="currentEditeTemplate" :currentTemplate="currentTemplate" :componentList="componentList"></component>
      <div v-else style="height:200px;border:1px solid #ccc;">未选择模板</div>
    </div>
  </div>
</template>

<script>

export default {
  name: "home",
  data() {
    return {
      currentTemplate:"",
      currentEditeTemplate:"",
      newCom: {},
      componentList: [
        {
          component: "v-button",
          label: "按钮",
          propValue: "按钮",
          icon: "el-icon-edit",
          animations: [],
          events: {},
          style: {
            // width: "100px",
            // height: "100px",
            fontSize: 14,
            background: "red",
            fontWeight: 500,
            lineHeight: "",
            letterSpacing: 0,
            textAlign: "",
            color: ""
          }
        },
        {
          component: "v-small-button",
          label: "小型按钮",
          propValue: "小型按钮",
          icon: "el-phone",
          animations: [],
          events: {},
          style: {
            // width: "50px",
            // height: "50px",
            fontSize: 14,
            background: "green",
            fontWeight: 500,
            lineHeight: "",
            letterSpacing: 0,
            textAlign: "",
            color: ""
          }
        }
      ]
    };
  },

  methods: {
    selectTemplate(val){
       if(val ==1){
         this.currentTemplate = "1"
         this.currentEditeTemplate = ()=>import("./EditeTemplate1")
       }else{
         this.currentTemplate = "2"
         this.currentEditeTemplate = ()=>import("./EditeTemplate2")
       }
    },
   
    handleDragStart(e) {
      e.dataTransfer.setData("index", e.target.dataset.index);
      console.log(e.target.dataset.index);
    }
  }
};
</script>

2、2个模板编辑页面 EditeTemplate1.vue 与 EditeTemplate2.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
  <div class="container">
      <div class="editeArea">
        编辑模板1
          <div
            @drop="handleDrop"
            @dragover="handleDragover"
            @click="deselectCurComponent"
            style="border:1px solid red;margin-top:20px;height:150px;"
          >
            <div>
              <el-button @click="delTopCom">删除</el-button>
            </div>
            <component :is="componentData.top.component" :propValue="componentData.top.propValue"></component>
          </div>
          <div
            @drop="handleDrop1"
            @dragover="handleDragover1"
            @click="deselectCurComponent1"
            style="border:1px solid green;margin-top:20px;height:150px;"
          >
            <div>
              <el-button @click="delTopComBottom">删除</el-button>
            </div>
            <component :is="componentData.bottom.component" :propValue="componentData.bottom.propValue"></component>          
          </div>
          <el-button @click="saveTemplateData">保存模板</el-button>
          <el-button @click="previewPage">预览</el-button>
      
    </div>
  </div>
</template>

<script>
import VButton from "@/components/VButton.vue";
import VSmallButton from "@/components/VSmallButton.vue";
export default {
  name: "home",
  props:{currentTemplate:String,componentList:Array},
  components: { VButton, VSmallButton },
  data() {  
    return {
      newCom: {},
      componentData: {
        top: {},
        bottom: {}
      }
    };
  },

  methods: {
    saveTemplateData() {
      // let templateData = {
      //   componentData1: this.componentData,
      //   otherComponentData1: this.otherComponentData
      // };
      // this.$set(this.newCom, "componentData1", templateData.componentData1);
      // this.newCom = Object.assign({}, this.newCom, templateData);
    },
    // handleDragStart(e) {
    //   e.dataTransfer.setData("index", e.target.dataset.index);
    //   console.log(e.target.dataset.index);
    // },
    handleDrop(e) {
      console.log("drop");
      e.preventDefault();
      e.stopPropagation();
      this.componentData.top = this.componentList[
        e.dataTransfer.getData("index")
      ];
    },
    handleDragover(e) {
      console.log("handleDragover");
      event.preventDefault(); // 如果不写,不会触发drop事件
    },
    deselectCurComponent() {
      console.log("click");
    },

    // 下面的放置区域
    handleDrop1(e) {
      console.log("drop111");
      e.preventDefault();
      e.stopPropagation();
      this.componentData.bottom = this.componentList[
        e.dataTransfer.getData("index")
      ];    
    },
    handleDragover1(e) {
      console.log("handleDragover111");
      event.preventDefault(); // 如果不写,不会触发drop事件
    },
    deselectCurComponent1() {
      console.log("click");
    },
    delTopCom() {
      this.componentData.top = {};
    },
    delTopComBottom() {
      this.componentData.bottom = {};
    },

    previewPage() {
      alert("preview");
      sessionStorage.setItem("componentData",JSON.stringify(this.componentData))
      let currentMenuVideo = this.currentMenuVideo;
      //在新窗口中打开
      const { href } = this.$router.resolve({
        path: "/preview",
        query:{currentTemplate:this.currentTemplate}
      });
      window.open(href, "_blank");
    }
  }
};
</script>

3、preview.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
    <div>
      <component :is="currentTemplate" :componentData="componentData"></component>     
    </div>
</template>

<script>
// import Edit from "@/components/Edit.vue";
// import VButton from "@/components/VButton.vue";
// import VSmallButton from "@/components/VSmallButton.vue";
export default {
  name: "home",
  // components: { VButton, VSmallButton},
  data() {
    return {
      currentTemplate:null,
      newCom: {},
      componentData: {}    
    };
  },
  mounted(){
    let componentData = JSON.parse(sessionStorage.getItem("componentData"))
    this.componentData = componentData
    let currentTemplate = this.$route.query.currentTemplate
   
    this.currentTemplate = ()=>import(`./previewTemplate${currentTemplate}.vue`)  
  },
  methods: {
    saveTemplateData() {
      // let templateData = {
      //   componentData1: this.componentData,
      //   otherComponentData1: this.otherComponentData
      // };
      // this.$set(this.newCom, "componentData1", templateData.componentData1);
      // this.newCom = Object.assign({}, this.newCom, templateData);
    }
  }
};
</script>

4、预览模板previewTemplate1.vue与previewTemplate1.vue

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
<template>
    <div>
      <div
        style="border:1px solid red;margin-top:20px;height:150px;"
      >       
        <component :is="componentData.top.component" :propValue="componentData.top.propValue"></component>
      </div>
      <div        
        style="border:1px solid green;margin-top:20px;height:150px;"
      >     
        <component :is="componentData.bottom.component" :propValue="componentData.bottom.propValue"></component>       
      </div>
    </div>
</template>

<script>
// import Edit from "@/components/Edit.vue";
import VButton from "@/components/VButton.vue";
import VSmallButton from "@/components/VSmallButton.vue";
export default {
  name: "home",
  props:{componentData:Object},
  components: { VButton, VSmallButton},
  data() {
    return {
      // newCom: {},


      // otherComponentData: []
    };
  },
  mounted(){
 
  },
  methods: {
    
  }
};
</script>

总结:原理是根据 dragstart拖动组件并传值,drop时获取传过来的值,并把传过来的组件保存起来,根据选中的编辑模板与选中的组件,动态渲染预览界面(编辑模板与预览模板是对应的)

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
可视化拖拽组件库一些技术要点原理分析
为了让本文更加容易理解,我将以上技术要点结合在一起写了一个可视化拖拽组件库 DEMO:
谭光志
2020/12/22
2K0
可视化拖拽组件库一些技术要点原理分析
VisualDrag低代码拖拽模板
因此得研究实现一个拖拽生成低代码平台,通过查询了各种资料,找到了以下比较合适的开源的低代码平台:
不愿意做鱼的小鲸鱼
2022/11/22
1.8K0
VisualDrag低代码拖拽模板
【Vue3+TypeScript】CRM系统项目搭建之 — 登录注册页【部分操作界面搭建】
在使用第三方组件库的时候,可以不要一开始就把所有属性添加进去,而是可以使用最原始的状态,之后慢慢添加属性上去,这样会更加容易去理解组件库的设计,当然也可以多去想想它的底层会是如何设计的。
HelloWorldZ
2024/03/20
2360
【Vue3+TypeScript】CRM系统项目搭建之 — 登录注册页【部分操作界面搭建】
【愚公系列】《循序渐进Vue.js 3.x前端开发实践》070-商业项目:电商后台管理系统实战(商品管理模块的开发)
在电商平台中,商品管理模块是连接商家与消费者的重要桥梁。它不仅承担着商品信息的录入、修改与删除等基本功能,还涉及到库存管理、价格调整、上下架操作等多项关键任务。一个高效的商品管理模块能够帮助商家轻松管理各种商品,提高销售效率,并确保用户获得准确的信息。
愚公搬代码
2025/06/03
1700
【愚公系列】《循序渐进Vue.js 3.x前端开发实践》070-商业项目:电商后台管理系统实战(商品管理模块的开发)
组件左右拖动
<template> <div> <div style="display:flex;overflow:hidden;"> <div class="left" style="width:300px;margin-right:20px;" ref="leftRef"> <ul @dragstart="handleDragStart"> <li v-for="(item,index) in componentsList" :key="index"
tianyawhl
2022/05/06
2.2K0
【愚公系列】《循序渐进Vue.js 3.x前端开发实践》044-Element Plus入门
在现代前端开发中,用户界面的设计和体验越来越受到重视。为了提高开发效率和界面美观性,使用 UI 组件库已成为许多开发者的首选。Element Plus 作为一款基于 Vue 3 的组件库,为开发者提供了丰富而灵活的 UI 组件,帮助我们快速构建高质量的应用界面。
愚公搬代码
2025/06/02
1960
【愚公系列】《循序渐进Vue.js 3.x前端开发实践》044-Element Plus入门
Vue3+Element-plus前端学习笔记-巨长版
「写好的代码」:Lvan826199/mwj-vue3-project: vue3-vite构建的一个前端模版 (github.com)
梦无矶小仔
2024/03/25
8910
Vue3+Element-plus前端学习笔记-巨长版
Vue cli入门 原
最近看到一个vue cli入门的例子,写的非常详细,对入门vue cli很有帮助,原文链接
tianyawhl
2019/04/04
5420
Vue cli入门
                                                                            原
Vue实现在线文档预览
本次实现的文档预览的类型有:docx, xlsx, pptx, pdf,以及纯文本、代码文件和各种图片、视频格式的在线预览
不愿意做鱼的小鲸鱼
2023/07/09
4.5K0
Vue实现在线文档预览
vue2.0+Element-ui实战案例
我们将会选择使用一些 vue 周边的库vue-cli, vue-router,axios,moment,Element-ui搭建一个前端项目案例,后端数据接口,会使用json-server快速搭建一个本地的服务,方便对数据的增删改查,
小周sir
2019/09/23
2.4K0
vue2.0+Element-ui实战案例
可视化拖拽组件库一些技术要点原理分析(四)
本文是可视化拖拽系列的第四篇,比起之前的三篇文章,这篇功能点要稍微少一点,总共有五点:
谭光志
2022/09/20
1.4K0
可视化拖拽组件库一些技术要点原理分析(四)
vue-router(element侧导栏,子组件内容切换,不传参)使用的详细步骤
淼学派对
2023/10/14
6350
vue-router(element侧导栏,子组件内容切换,不传参)使用的详细步骤
Vue 组件实战
在Vue中我们可以使用插值来展示数据,插值的普通函数,只要页面一刷新,函数就会重新运算,不管和函数有关没关的值都会变,函数也会重新计算,导致运行效率降低;
HammerZe
2022/05/09
9290
Vue 组件实战
前端里的拖拖拽拽了解一下?
拖拽交互常见于各种前端编辑器里,而“编辑器”是一个集成前端技术能力的综合性工程,其中就会涉及到各种形式的拖拽交互,因为“拖拽”是提升用户体验的重要交互方式,所以需要对拖拽的交互效果做各种定制化,作为开发者理应熟练掌握“拖拽”的使用!
小东同学
2022/07/29
5.3K1
前端里的拖拖拽拽了解一下?
VUE Cookbook 系列:实现可配置组合表单
本案例将会讲解如何使用 vue.js + ElementUI 开发一个简单的 可配置组合表单 Demo。
IMWeb前端团队
2019/12/03
1K0
vue动态组件的用法
今天写一篇关于vue组件的扩展用法, 之前将一些基本用法已经写过了,没有看过的可以自行找一下,今天要写的是一片关于vue 官方给的动态组件的一种用法,其实这个用法的使用场景使用基本组件也是可以胜任的,只是既然有这样一种写法的存在,我们还是需要实现一下,网上呢关于他的用法写的也有很多,我一般写的文章都是最基础的使用方法,没有一些花里胡哨的写法,所以很容易看得明白!废话不多说,上代码
何处锦绣不灰堆
2020/10/26
8740
vue动态组件的用法
useDrop vue 拖拽hook
使用例子 <style> *{ margin: 0; padding: 0; } li{ list-style: none; } #app { font-family: Avenir, Helvetica, Arial, sans-serif; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-align: center; color: #2c3e50; m
copy_left
2020/04/30
6310
vite vue3 pwa 更新提醒
vite-plugin-pwa插件启用pwa后默认会在后台自动更新应用,并在关闭所有已开启的页面并重新打开后激活 通过此方法可以以消息方式提醒用户手动刷新激活更新应用
路过君
2023/10/19
8290
vite vue3 pwa 更新提醒
Vue(下)
日常开发中,通常设置一个app组件作为主组件(相当于单文件组件的App.vue):
十玖八柒
2022/08/01
2.3K0
Vue(下)
使用Vue写一个登录页面
3.根据npm run dev 命令启动,启动完成之后会有个链接,访问链接就直接可以看到下面页面:
全栈程序员站长
2022/08/31
2.1K0
使用Vue写一个登录页面
相关推荐
可视化拖拽组件库一些技术要点原理分析
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验