引文
我们的产品说: “ -- 这块我想做成拖拽的“
“ -- 好“
我们使用了sortTable.jssortablejs.github.io/Sortable/#s…,然后实现了一个这样的结果:
实现原理
const lista1 = document.getElementById('lista1');
const lista2 = document.getElementById('lista2');
Sortable.create(lista1, {
animation: 150,
chosenClass: "seleccionado",
// ghostClass: "fantasma"
dragClass: "drag",
onEnd: () => {
console.log('Se inserto un elemento');
},
group: "lista-personas",
store: {
// Guardamos el orden de la lista
set: (sortable) => {
const orden = sortable.toArray();
localStorage.setItem(sortable.options.group.name, orden.join('|'));
},
// Obtenemos el orden de la lista
get: (sortable) => {
const orden = localStorage.getItem(sortable.options.group.name);
return orden ? orden.split('|') : [];
}
}
});
Sortable.create(lista2, {
animation: 150,
chosenClass: "seleccionado",
// ghostClass: "fantasma"
dragClass: "drag",
onEnd: () => {
console.log('Se inserto un elemento');
},
group: "lista-personas",
store: {
// Guardamos el orden de la lista
set: (sortable) => {
const orden = sortable.toArray();
localStorage.setItem(sortable.options.group.name, orden.join('|'));
},
// Obtenemos el orden de la lista
get: (sortable) => {
const orden = localStorage.getItem(sortable.options.group.name);
return orden ? orden.split('|') : [];
}
}
});
常用的参数
// 动画的时间
animation: 200,
// 不需要进行拖动的元素
filter: ".ignore-elements"
// true时sortable对象不能拖放排序等功能,为false时为可以进行排序,相当于一个开关
disabled: !this.editable
// 被选中项的css 类名
chosenClass: "seleccionado"
// 正在被拖拽中的css类名
dragClass: "drag",
常用的方法
// 元素被选中
onChoose: function (/**Event*/evt) {
evt.oldIndex; // element index within parent
},
// 开始拖拽的时候
onStart: function (/**Event*/evt) {
evt.oldIndex; // element index within parent
},
// 结束拖拽
onEnd: function (/**Event*/evt) {
},
// 列表内元素顺序更新的时候触发
onUpdate: function (/**Event*/evt) {
// same properties as onEnd
},
// 列表的任何更改都会触发
onSort: function (/**Event*/evt) {
// same properties as onEnd
},
// 拖拽元素改变位置的时候
onChange: function(/**Event*/evt) {
evt.newIndex // most likely why this event is used is to get the dragging element's current index
// same properties as onEnd
}
文档很简洁,使用起来也很简单。但sortTable只是在当前的页面中能进行拖拽,如果,我想从这个浏览器窗口,拖动到另外一个浏览器窗口呢?
于是,发现了更有意思的东西。。。
transmat
跨越浏览器的边界,实现数据共享 前提 -- 浏览器版本:Chrome 91.0.4472.114
介绍
Transmat 是一个围绕 DataTransfer API 的小型库 ,它使用 drag-drop 和 copy-paste 交互简化了在 Web 应用程序中传输和接收数据的过程。
DataTransfer 对象用于保存拖动并放下(drag and drop)过程中的数据。它可以保存一项或多项数据,这些数据项可以是一种或者多种数据类型。
DataTransfer API 能够将多种不同类型的数据传输到用户设备上的其他应用程序,该 API 所支持的数据类型,常见的有这几种:text/plain、text/html 和 application/json 等。
实现原理
from
- 为
div#source元素添加了draggable 属性,该属性用于标识元素是否允许被拖动,它的取值为true或false。
<div id="source" draggable="true" tabindex="0">今天是我分享</div>
- 利用 transmat 这个库提供的
addListeners 函数为div#source元素,添加了transmit 的事件监听。 - 在对应的事件处理器中,我们先
创建了 Transmat 对象,然后调用该对象上的setData 方法设置不同 MIME 类型的数据。
媒体类型(通常称为 Multipurpose Internet Mail Extensions 或 MIME 类型 )是一种标准,用来表示文档、文件或字节流的性质和格式。
- text/plain:表示文本文件的默认值,一个文本文件应当是人类可读的,并且不包含二进制数据。
- text/html:表示 HTML 文件类型,一些富文本编辑器会优先从 dataTransfer 对象上获取text/html 类型的数据,如果不存在的话,再获取 text/plain 类型的数据。
- text/uri-list:表示 URI 链接类型,大多数浏览器都会优先读取该类型的数据,如果发现是合法的 URI 链接,则会直接打开该链接。如果不是的合法 URI 链接,对于 Chrome 浏览器来说,它会读取。
- text/plain 类型的数据并以该数据作为关键词进行内容检索。
- application/json:表示 JSON 类型,该类型对前端开发者来说,应该都比较熟悉了。
<script>
const { Transmat, addListeners, TransmatObserver } = transmat;
const source = document.getElementById("source");
addListeners(source, "transmit", (event) => {
const transmat = new Transmat(event);
transmat.setData({
"text/plain": "今天是我分享",
"text/html": `<h1>今天是我分享</h1>`,
"text/uri-list": "www.baidu.com",
"application/json": {
name: "分享会",
wechat: "semlinker",
},
});
});
</script>
to
<div id="target" tabindex="0">放这里</div>
我们利用 transmat 这个库提供的 addListeners 函数为 div#target 元素,添加了 receive 的事件监听。顾名思义,该 receive 事件表示接收消息。
在对应的事件处理器中,我们通过 transmat 对象的 hasType 方法过滤了 application/json 的消息,然后通过 JSON.parse 方法进行反序列化获得对应的数据,同时把对应 jsonString 的内容显示在 div#target 元素内。
const { Transmat, addListeners, TransmatObserver } = transmat;
const target = document.getElementById("target");
addListeners(target, "receive", (event) => {
const transmat = new Transmat(event);
// 判断是否含有"application/json"类型的数据
// 及事件类型是否为drop或paste事件
if (transmat.hasType("application/json")
&& transmat.accept()
) {
const jsonString = transmat.getData("application/json");
const data = JSON.parse(jsonString);
target.textContent = jsonString;
}
});