前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >vue 拖动

vue 拖动

作者头像
tianyawhl
发布2021-05-18 10:52:48
1.7K0
发布2021-05-18 10:52:48
举报
文章被收录于专栏:前端之攻略

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

需要有几个vue 页面

1、home.vue

代码语言:javascript
复制
<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
复制
<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
复制
<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
复制
<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 删除。

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

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档