0
点赞
收藏
分享

微信扫一扫

Spring之Bean生命周期源码解析

求阙者 2023-06-28 阅读 64

目录

一、效果展示

二、代码分析

2.1、两栏布局、表格编写与课程卡片

2.2、初始化数据与渲染

2.3、拖拽卡片到表格,进行插入

2.4、自定义指令进行删除

一、效果展示

二、代码分析

主页面代码:

<template>
  <div class="board">
    <div class="left">
      <CoursePerson
        v-for="({ name }, k) in datas.courses"
        :key="k"
        :courseName="name"
        :courseKey="k"
        @handleDragEnd="handleDragEnd"
      ></CoursePerson>
    </div>
    <div class="right" @dragover="handleDragOver" @dragenter="handleDragEnter">
      <table border="1">
        <tr>
          <th>时间段 / 星期</th>
          <th v-for="(w, i) in datas.weekday" :key="i">{{ w }}</th>
        </tr>
        <tr v-for="(t, i) in datas.time_slot" :key="i">
          <th>{{ t }}</th>
          <td v-for="n in 7" :key="n" :data-weekday="n" :data-time-slot="i">
            <template v-if="cellData[`${n}-${i}`]">
              <CoursePerson
                :courseName="datas.courses[cellData[`${n}-${i}`]].name"
                :courseKey="cellData[`${n}-${i}`]"
                v-CoursePanel="{ cellData, n, timeSlot: i }"
              ></CoursePerson>
            </template>
          </td>
        </tr>
      </table>
    </div>
  </div>
</template>

<script>
import CoursePerson from "@/components/CoursePerson.vue";
export default {
  components: {
    CoursePerson,
  },
  directives: {
    // 定义名为CoursePanel的指令,指向一个配置对象
    CoursePanel: {
      bind(el, bindings) {
        const oRemoveBtn = el.querySelector(".remove-btn");
        const { cellData, n, timeSlot } = bindings.value;
        oRemoveBtn.addEventListener("click", handleRemovePanel, false);
        function handleRemovePanel() {
          delete cellData[`${n}-${timeSlot}`];
        }
      },
    },
  },
  data() {
    return {
      datas: {
        weekday: [
          "星期一",
          "星期二",
          "星期三",
          "星期四",
          "星期五",
          "星期六",
          "星期日",
        ],
        time_slot: [
          "08:00-08:50",
          "09:00-09:50",
          "10:00-10:50",
          "11:00-11:50",
          "14:00-14:50",
          "15:00-15:50",
          "16:00-16:50",
          "17:00-17:50",
        ],
        courses: {
          chinese: {
            name: "语文",
            teachers: ["张三", "李四"],
          },
          math: {
            name: "数学",
            teachers: ["张二", "李五"],
          },
          english: {
            name: "英语",
            teachers: ["张3", "李2"],
          },
        },
      },
      cellData: {
        "1-1": "chinese",
        "2-5": "math",
        "3-3": "english",
      },
      targetCell: null,
    };
  },
  methods: {
    handleDragOver(e) {
      e.preventDefault();
    },
    handleDragEnter(e) {
      e.preventDefault();
      const tar = e.target;
      const tagName = tar.tagName.toLowerCase();
      this.targetCell = tagName != "td" ? null : tar;
    },
    handleDragEnd(e) {
      if (this.targetCell) {
        const weekday = this.targetCell.dataset.weekday;
        const timeSlot = this.targetCell.dataset.timeSlot;
        const prop = `${weekday}-${timeSlot}`;
        if (!this.cellData[prop]) {
          //给表格中没有坐标的课程
          const key = e.dataset.key;
          this.$set(this.cellData, prop, key); //借助$set赋值,更新视图
          // this.cellData[prop] = key; //赋值(vue2赋值视图不更新)
        }
      }
    },
  },
};
</script>

<style lang='less' scoped>
.board {
  position: relative;
  .left {
    position: absolute;
    top: 0;
    left: 0;
    width: 300px;
    height: 100%;
  }
  .right {
    width: 100%;
    height: 800px;
    padding-left: 300px;
    box-sizing: border-box;
    table {
      width: 100%;
      border-collapse: collapse;
      table-layout: fixed;
      td {
        height: 60px;
        text-align: center;
      }
    }
  }
}
</style>

卡片组件代码:

<template>
  <!-- draggable="true"  该盒子可被拖动 -->
  <div
    class="course-panel"
    draggable="true"
    @dragstart="handleDragStart"
    @dragend="handleDragEnd"
    :data-key="courseKey"
  >
    <h1>{{ courseName }}</h1>
    <span class="remove-btn">x</span>
  </div>
</template>

<script>
export default {
  props: ["courseName", "courseKey"],
  methods: {
    handleDragStart(e) {
      const tar = e.target;
      tar.style.opacity = ".6";
    },
    handleDragEnd(e) {
      const tar = e.target;
      tar.style.opacity = "1";
      this.$emit("handleDragEnd", tar);
    },
  },
};
</script>

<style lang='less' scoped>
.course-panel {
  position: relative;
  width: 100px;
  height: 60px;
  background-color: goldenrod;
  margin: 10px auto;
  padding: 10px;
  box-sizing: border-box;
  cursor: move;
  h1 {
    font-size: 20px;
    text-align: center;
  }
  .remove-btn {
    position: absolute;
    top: 0px;
    right: 10px;
  }
}
</style>

2.1、表格编写与课程卡片

  静态页面主要采用两栏布局。左侧为卡片组件,右侧为表格。

2.2、初始化数据与渲染

  td是单元格,现在里面是一个7X7的表格,想要将指定课程的卡片渲染上去,我们可以借助cellData变量里的值,类似二维数组,我们找到坐标,就可以渲染上去。

2.3、拖拽卡片到表格,进行插入

  拖拽效果:draggable="true"  意味着该盒子可被拖动,包括很多事件,比如:dragstart、dragend、dragover、dragenter等。

  插入实现:看似是将左侧的卡片拖进去,实则是在进入表格时(拖拽结束)进行了数据的改动,就是给cellData这个对象里继续增加一个属性和属性值,达到插入效果。vue2里直接复制,视图不会变化,可以通过$set进行视图更新this.$set(this.cellData, prop, key);

2.4、自定义指令进行删除

  本例中通过视图中  v-CoursePanel="{ cellData, n, timeSlot: i }",结合directives里的CoursePanel指令进行表格内卡片的删除。这里的删除指删除表格内的任意卡片,而不能删除左侧的原始卡片。所以组件结合自定义指令去进行删除操作。

  现在它删除有个bug,点击x删除,需要再次拖拽(添加)时,才会看到删除的卡片效果,尚待完善。。。

举报

相关推荐

0 条评论