Vue框架怎么制作拖拽并生成组件的功能
Admin 2022-07-16 群英技术资讯 1740 次浏览
本篇内容介绍了“Vue框架怎么制作拖拽并生成组件的功能”的有关知识,在实际项目的操作过程或是学习过程中,不少人都会遇到这样的问题,接下来就让小编带大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!开完产品需求会议,遇到了一个需求,首先页面分成两栏布局,左侧展示数据组件,支持拖拽排序,点击按钮清除组件。右侧支持将组件的缩略图拖拽至左侧生成一个新的组件。
对于动态生成组件来说每一次都要是生成全新的一个组件,那么就可以把 组件放进函数当中 return。在JSX中调用函数,每次调用函数都会返回一个全新的组件。这对React来说非常简单,但是对于Vue来说,直接将组件返回是不可能的。尽管这个 return 写法不适合Vue,但是我们不可否认,思路是非常正确的,所以我们应该考虑一个别的写法。至于动态的生成组件,我们必须以数据来驱动组件的生成。对于拖拽组件的排序,直接使用拖拽库就OK了!!
拖拽库在这里我选择的是项目中存在的一个拖拽库 Vue.Draggable 点这里链接查看 Start 14.9K 蛮不错的。如果你们的Vue项目中没有用到这个拖拽库,你们可以自行参考本片文章的设计思路。
在这里我使用的是 Vue.extend() 不清楚如何使用的小伙伴请在官方文档中查看过后再来学习这篇文章 Vue.extend 。 接下来我们创建一个js文件,用来书写创建组件的代码。
/* generateComponents.js 文件名 */
import Vue from "vue";
// 想要动态生成的组件,先引入这个文件。
import components1 from "./components/TestCom1.vue";
import components2 from "./components/TestCom2.vue";
// 将组件的名称和组件做一个对应Map
const 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() {
// 定义默认的查询条件。
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();
// 调用父组件的函数。修改父组件中的 leftComList 数组的数据。
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文件的代码类似,唯一不同的地方就是背景颜色不一样。
接下来就得使用Vue.Draggable 这个拖拽库进行拖拽和数据的修改。 我们可以直接在App.vue文件中直接书写。
/* App.vue */
<template>
<div class="dragCom">
<h1>{{ leftComList }}</h1>
<button @click="queryObj.num++">改变查询条件</button>
<div class="body">
<div class="left">
<draggable class="left" :list="leftComList" :group="'people'">
<div
ref="comBody"
v-for="({ name, id }, index) in leftComList"
:key="id"
class="comCard"
>
<!-- 循环 leftComList 数组,利用数据来渲染组件,
将动态生成的数组添加到这个DOM元素当中。 -->
{{
handleAddCom({
props: { comItem: { name, id }, queryObj },
index,
})
}}
</div>
</draggable>
</div>
<div class="right">
<draggable
class="dragArea"
:list="rightComList"
:group="{ name: 'people', pull: 'clone', put: false }"
:clone="handleCloneDog"
>
<div class="card" v-for="element in rightComList" :key="element.id">
{{ element.name }}
</div>
<!-- 右侧的 卡片 数据, rightComList 数组对象中的name就对应了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: [], // 存储驱动动态生成组件的数据。
comMap: new Map(), // 主要的作用就是用来记录
// 组件有没有渲染到 class="comCard" 这个DOM中,
// 如果渲染了就不能再往进添加子元素了。
queryObj: {
// 主要的作用就是向子组件传递查询条件
num: 0,
},
};
},
beforeDestroy() {
// 清除 记录 的数据
this.comMap.clear();
},
methods: {
handleAddCom({ index, on = {}, props = { comItem: { name: "", id: 0 } } }) {
const {
comItem: { id },
} = props;
this.$nextTick(() => {
// 获取该节点的子节点的长度
const childNodesLength = this.$refs.comBody[index].childNodes.length;
// 获取comBody 这个DOM 数组的长度
const comLine = this.$refs.comBody.length;
if (!this.comMap.get(id)) {
// 如果没有渲染过组件
// 1. 调用 CreateCom 方法 创建组件。 并传递 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. 记录该组件实现了渲染。
this.comMap.set(id, true);
} else {
// 该位置的组件已经渲染,不需要再次渲染直接返回
return;
}
});
},
handleDeleteCom({ id }) {
// 传递给子组件删除的方法,根据组件的id来删除数据
const index = this.leftComList.findIndex((item) => item.id === id);
if (~index) {
// 如果存在这个id的组件,就删除
this.leftComList.splice(index, 1);
}
},
handleCloneDog(item) {
// 给 leftComList 数组添加数据
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>
这样就实现了动态的组件渲染和拖拽排序。
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:mmqy2019@163.com进行举报,并提供相关证据,查实之后,将立刻删除涉嫌侵权内容。
猜你喜欢
nodejs火了的原因:1、Node在服务端和客户端都是使用JS,开发人员在各层上只需使用一门语言;2、Node容易学会,对于开发者来说易转型;3、支持NoSQL数据库;4、有很好的IDE和代码编辑器支持;5、代码托管服务支持广泛等。
Events是Node中的一个很重要的核心模块,Stream,网络,文件系统统统都是继承自这个模块。Streams模块就是继承自EventEmitter,所以说弄明白Events模块,特别是EventEmitter对象,对于理解Node中的很多模块都是有好处的。Stream非常擅长处理数据,无论是读,写或者是转换。比如,你可以用Stream接收数据库中的数据,将其流出到csv的流中,导出成
不通过路由的情况下, 怎么懒加载一个angular模块,并动态创建其中声明的组件?下面本篇文章给大家介绍一下方法,希望对大家有所帮助!
这篇文章主要为大家详细介绍了微信小程序实现登录界面,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
Node中怎么操作文件?下面本篇文章带大家聊聊怎么使用Nodejs读写文件,希望对大家有所帮助!
成为群英会员,开启智能安全云计算之旅
立即注册Copyright © QY Network Company Ltd. All Rights Reserved. 2003-2020 群英 版权所有
增值电信经营许可证 : B1.B2-20140078 粤ICP备09006778号 域名注册商资质 粤 D3.1-20240008