信息发布→ 登录 注册 退出

利用Vue3实现拖拽定制化首页功能

发布时间:2026-01-11

点击量:
目录
  • 前期准备
  • 开始
    • 方法一
    • 方法二
    • 方案三
  • 最终实现结果
    • 总结

      前期准备

      • Vue3
      • Ts
      • VueDragable (4版本以上)
      • 期望 拖拽组件 组件可以按需加载导入

      开始

      首先呢,我们先看下VueDragable的文档效果

      文档的效果是这种基于列表的一个拖拽排序,那么回归到我们期望我们是想通过动态引入组件来进行拖拽排序,那么在完成拖拽定制化之前,首先要讲的是动态组件,在使用Vue2时候相信我们不陌生我们可以通过Component is来动态引入,如:

      <template>
        <div class="component-box">
           <component :is="xxx""/>          
        </div>
      </template>
      <script>
      import xxx from 'xxx.vue'
      export default{
          data(){
              return{
      
              }
          },
          components:{
              xxx
          }
      }
      </script>

      其中is的值就是我们在components中注册的组件,这样就能完成动态组件的注入,那么在Vue3中呢?尤其是在setup语法糖使用时候我们这样做就会导致无法识别组件,这是因为setup语法糖中我们可以直接引入组件后使用,并不需要通过在components中注册(默认帮我们完成了),那么我们真实的业务场景其实后台返给我们的数据是这个格式的:

      因此,我们的动态组件也需要做调整:

      <div class="component-box" v-for="element in xxx">
        <component :is="element.name" :key="element.name"/>
      </div>

      这时候我们的is绑定就并非一个组件的实例了,其实是一个字符串,如此一来,就会产生错误并且导致页面无法正常加载我们的组件,那么该怎么办呢?大傻在网上做了调研,有三种方法:

      方法一

      通过Vue3的defineAsyncComponent方法去完成动态加载组件,使其成为一个实例对象。

      import { defineAsyncComponent, ref } from 'vue'
      // 需要加载的组件集合
      const components = ref(new Map<string, any>())
      components.value.set(
        'test1',
        defineAsyncComponent(() => import('./test1.vue'))
      )
      components.value.set(
        'test2',
        defineAsyncComponent(() => import('./test2.vue'))
      )

      这样我们在取值时候可以通过get方法传入具体字符串拿到对应的组件

      方法二

      这个则是通过shallowRef 或者 markRaw 来进行代理,shallowRef是浅层代理,只去代理一层,而markRaw则是标记该属性永远不为响应式

      import { shallowRef, ref } from 'vue'
        import test1 from './test1.vue'
        import test2 from './test2.vue'
       
        //这里用ref的话,vue给出警告Vue接收到一个组件,该组件被制成响应对象。这可能会导致不必要的性能开销,应该通过将组件标记为“markRaw”或使用“shallowRef”而不是“ref”来避免。
        
        // 如果使用 markRaw 那么currentComp将不永远不会再成为响应式对象。 所以得使用 shallowRef
        let currentComp = shallowRef(test1)  
       currentComp.value
        // 切换组件
        const changeComp = () => {
          if(currentComp.value == test1) {
            currentComp.value = test2
          }else {
            currentComp.value = test1
          }
        }

      这种方法可行,但是不能传入字符串进行动态引入

      方案三

      双script标签完美解决

      <script lang="ts">
      import {
        Test1,
        Test2,
      } from './components/DragComponents'
      
      export default {
        components: {
          Test1,
          Test2,
        }
      }
      </script>
      <script setup lang="ts">
      const componentList = reactive([
        {
          name: 'Test1',
          title: '测试1',
          id: '1'
        },
        {
          name: 'Test2',
          title: '测试2',
          id: '2'
        }
      ])
      </script>

      这样我们可以直接去拿到后台数据进行处理。

      最终实现结果

      大傻最终呢,也是通过不断地爬坑去实现了这个拖拽效果,目前完成了横纵方向两种布局,待拓展的也就是,可定制宽高等等这些内容。有兴趣可以留言,大家一起交流。感兴趣的可以克隆下来试一试

      总结

      在线客服
      服务热线

      服务热线

      4008888355

      微信咨询
      二维码
      返回顶部
      ×二维码

      截屏,微信识别二维码

      打开微信

      微信号已复制,请打开微信添加咨询详情!