Vue项目内嵌Html页面,并且可以操作Dom节点进行拖拽排序
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试静态页面title>
head>
<body>
<div class="menu_list">
<div class="menu_wp" style="background: #f00">111div>
<div class="menu_wp" style="background: #ff0">222div>
<div class="menu_wp" style="background: #0ff">333div>
<div class="menu_wp" style="background: #00f">444div>
div>
body>
<style>
.menu_wp {
width: 100px;
height: 100px;
}
style>
html>
<template>
<div class="home">
<div class="left">
<iframe id="iFrame" :src="src" frameborder="0" style="width: 100%; height: 100%" />
div>
<button @click="handleSubmit">点击获取页面数据排序button>
div>
template>
<script>
export default {
name: 'HomeView',
data () {
return {
src: ''
}
},
components: {
},
mounted () {
this.src = '../../page.html';
this.$nextTick(() => {
const iframe = window.frames['iFrame']
const handleLoad = () => {
setTimeout(() => {
const Do = (iframe.contentWindow || iframe.contentDocument)
let menus = Do.document.getElementsByClassName('menu_wp')
for(var i = 0; i < menus.length; i++) {
menus[i].setAttribute('draggable', true)
menus[i].setAttribute('sort', i)
}
this.drag(Do.document)
}, 500)
}
iframe.addEventListener('load', handleLoad, true)
})
},
methods: {
drag (doc) {
// 获取列表dom
let list = doc.querySelector('.menu_list');
// 创建cruentItem存放将要拖动的元素
let cruentItem
list.mousedown = e => {
e.preventDefault();
}
// 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
list.ondragover = e => {
e.preventDefault();
}
// 拖动开始
list.ondragstart = e => {
// 此处使用setTimeout延迟被拖动的原始元素的样式
setTimeout(() => {
e.target.classList.add("moving");
},0)
// 存储被拖动元素
cruentItem = e.target;
// 拖动时默认行为是复制,此处可以改为移动
e.dataTransfer.effectAllowed = 'move';
}
// 拖动中
list.ondragenter = e => {
// 阻止默认事件,否则元素会先回到拖动开始时的位置,再到拖动结束的位置
e.preventDefault();
// 拖动事件期间排除被拖动元素自身,以及事件代理对象ul
if(e.target == cruentItem || e.target == list) {
return;
}
// list.children获取的是类数组,类数组没有数组的方法,所以要通过Array.from转换为真正的数组
let itmeList = Array.from(list.children);
// 获取当前拖动元素位置的下标
let tiemListIndex = itmeList.indexOf(cruentItem);
// 获取当前拖动元素所移动到的位置的元素的下标
let targetIndex = itmeList.indexOf(e.target);
// 如果当前拖动元素下标小于目标元素下标说明是往下移动,否则网上移动
if (tiemListIndex < targetIndex) {
console.log('往下移动');
// 当前拖动元素插入到目标元素前面,且nextElementSibling目标元素的下一个兄弟元素
list.insertBefore(cruentItem, e.target.nextElementSibling)
} else {
console.log('往上移动');
list.insertBefore(cruentItem, e.target)
}
}
// 拖动结束
list.ondragend = e => {
// 结束后移除虚线样式
e.target.classList.remove('moving')
}
},
handleSubmit() {
const iframe = window.frames['iFrame']
const Do = (iframe.contentWindow || iframe.contentDocument)
let menus = Do.document.getElementsByClassName('menu_wp')
let sortArr = []
for(var i = 0; i < menus.length; i++) {
const sort = menus[i].getAttribute('sort')
sortArr.push(sort)
}
console.log("排序后的顺序 ==>>", sortArr)
}
}
}
script>
<style scoped>
.left {
margin: 0 auto;
width: 50%;
height: 1000px;
border: 1px solid #000;
}
.moving {
background-color: transparent;
color: transparent;
border: 1px dashed black;
}
style>
DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>测试静态页面title>
head>
<body style="zoom: 50%;">
<div class="fixpage" style="background: rgb(255, 175, 175)"><div>固定页1div>div>
<div class="activepage 111" style="background: rgb(255, 255, 195)">动态页2div>
<div class="activepage 222" style="background: rgb(176, 255, 255)">动态页3div>
<div class="activepage 333" style="background: rgb(186, 186, 255)">动态页4div>
<div class="activepage 444" style="background: #fbc2ff">动态页5div>
<div class="activepage 555" style="background: #bbffbf">动态页6div>
<div class="activepage 666" style="background: #ffc6d7">动态页7div>
body>
<style>
.activepage {
width: 2480px;
height: 3508px;
font-size: 300px;
-webkit-user-drag: none;
}
.fixpage {
width: 2480px;
height: 3508px;
font-size: 300px;
-webkit-user-drag: none;
}
body::-webkit-scrollbar { width: 0 !important }
.moving,
.selected {
border: 21px solid rgb(255, 81, 0) !important;
box-sizing: border-box;
}
style>
html>
<template>
<div class="home">
<div class="left">
<iframe id="iFrame" ref="iFrame" :src="src" frameborder="0" style="width: 100%; height: 100%" />
div>
<button @click="handleSubmit">点击获取页面数据排序button>
div>
template>
<script>
export default {
name: 'AboutView',
data () {
return {
src: '',
iframe: {},
ratioNum: 100,
parentClassName: 'drag-box',
selectedClassName: 'selected'
}
},
components: {
},
mounted () {
this.demo();
},
methods: {
demo() {
this.src = '../../drag-mul.html'
this.$nextTick(() => {
const iframe = window.frames['iFrame']
const handleLoad = () => {
setTimeout(() => {
const Do = (iframe.contentDocument || iframe.contentWindow.document )
// 计算缩放比例
this.getRatio({Do, offsetWidth: (iframe.offsetWidth - 84 / 100)})
// 在报告页面外包裹一层拖拽层
this.appendDragBox({Do})
// 监听拖拽动作
this.drag({Do})
}, 500)
}
iframe.addEventListener('load', handleLoad, true)
})
},
// 计算缩放比例
getRatio({Do, offsetWidth}) {
var ratioNum = offsetWidth / 2480;
ratioNum = parseInt(ratioNum * 100) < 100 ? parseInt(ratioNum * 100) : 100;
Do.querySelector('body').style = `zoom:${ratioNum}%`
this.ratioNum = ratioNum
},
// 在每一页的报告页面外包裹一层拖拽层
appendDragBox({Do}) {
let bodyNode = Do.querySelector('body')
let divs = bodyNode.children
let newNode = Do.createElement('div');//添加元素
newNode.style = `padding: ${21*100 / this.ratioNum}px 0;border: 21px solid #000;box-sizing: border-box; width: auto;`
newNode.classList.add('drag-box')
for(var i = 0; i < divs.length; i++) {
let div = divs[i]
if(div.className.indexOf('fixpage') > -1 || div.className.indexOf('activepage') > -1) {
// 判断是否为报告页
let elem = newNode.cloneNode(true)
elem.setAttribute('draggable', true)
elem.setAttribute('sort', i)
elem.appendChild(div.cloneNode(true))
div.parentNode.replaceChild(elem, div)
}
}
},
// 多选拖拽
drag ({Do}) {
// 获取列表dom
let list = Do.querySelector('body');
// 创建cruentItem存放将要拖动的元素
let cruentItem, cruentItemList, dragIsSelect
// 点击选择
list.onclick = (e) => {
console.log("点击 ==>> ", e)
// 此处判断是否所选元素是否被选中
if(e.target.closest('.drag-box').className.indexOf('selected') > -1) {
e.target.closest('.drag-box').classList.remove("selected");
} else {
e.target.closest('.drag-box').classList.add("selected");
}
}
// 当某被拖动的对象在另一对象容器范围内拖动时触发此事件
list.ondragover = e => {
e.preventDefault();
}
// 拖动开始
list.ondragstart = e => {
console.log('拖动开始', e)
// 判断当前元素是否被选中,若未被选中,则原来选中的元素(们)清空选中样式
const selectedItems = Array.from(list.getElementsByClassName('selected'))
dragIsSelect = selectedItems.includes(e.target);
if(!dragIsSelect) {
// 拖拽的元素不在选中的元素们中,则清空选中元素(们)的样式
setTimeout(() => {
e.target.closest('.drag-box').classList.add("moving");
},0)
// 存储被拖动元素
cruentItem = e.target;
// 拖动时默认行为是复制,此处可以改为移动
e.dataTransfer.effectAllowed = 'move';
selectedItems.map(item => {
item.classList.remove('selected')
})
} else {
cruentItem = e.target;
cruentItemList = selectedItems
}
}
// 拖动中
list.ondragenter = e => {
console.log('拖动中', e)
// 阻止默认事件,否则元素会先回到拖动开始时的位置,再到拖动结束的位置
e.preventDefault();
if(!dragIsSelect) {
// 拖动事件期间排除被拖动元素自身,以及事件代理对象ul
if(e.target.closest('.drag-box') == cruentItem || e.target == list) {
return;
}
} else {
// 拖动事件期间排除被拖动元素自身,以及事件代理对象ul
if(cruentItemList.includes(e.target.closest('.drag-box')) || e.target == list) {
return;
}
}
// list.children获取的是类数组,类数组没有数组的方法,所以要通过Array.from转换为真正的数组
let itmeList = Array.from(list.children);
// 获取当前拖动元素位置的下标
let tiemListIndex = itmeList.indexOf(cruentItem);
// 获取当前拖动元素所移动到的位置的元素的下标
let targetIndex = itmeList.indexOf(e.target.closest('.drag-box'));
if(!dragIsSelect) {
// 如果当前拖动元素下标小于目标元素下标说明是往下移动,否则往上移动
if (tiemListIndex < targetIndex) {
console.log('往下移动');
// 当前拖动元素插入到目标元素前面,且nextElementSibling目标元素的下一个兄弟元素
list.insertBefore(cruentItem, e.target.closest('.drag-box').nextElementSibling)
} else {
console.log('往上移动');
list.insertBefore(cruentItem, e.target.closest('.drag-box'))
}
} else {
// 如果当前拖动元素下标小于目标元素下标说明是往下移动,否则往上移动
for(var i = 0; i < cruentItemList.length; i++) {
if (tiemListIndex < targetIndex) {
console.log('往下移动', e.target.closest('.drag-box').nextElementSibling);
if(i === 0) {
// 当前拖动元素插入到目标元素前面,且nextElementSibling目标元素的下一个兄弟元素
list.insertBefore(cruentItemList[i], e.target.closest('.drag-box').nextElementSibling)
} else {
list.insertBefore(cruentItemList[i], cruentItemList[i - 1].nextElementSibling)
}
} else {
console.log('往上移动', e.target.closest('.drag-box'));
list.insertBefore(cruentItemList[i], e.target.closest('.drag-box'))
}
}
}
}
// 拖动结束
list.ondragend = e => {
console.log("拖拽结束 ==>> ", e)
// 结束后移除虚线样式
if(!dragIsSelect) {
e.target.closest('.drag-box').classList.remove('moving')
}
}
},
handleSubmit() {
const iframe = window.frames['iFrame']
const Do = (iframe.contentDocument || iframe.contentWindow.document )
let bodyNode = Do.querySelector('body')
let divs = bodyNode.children
let sortArr = []
for(var i = 0; i < divs.length; i++) {
let div = divs[i]
if(div.getAttribute('draggable')) {
// 判断是否为报告页
const sort = div.getAttribute('sort')
sortArr.push(sort)
}
}
console.log("排序后的顺序 ==>>", sortArr)
}
}
}
script>
<style scoped>
.left {
float: left;
box-sizing: border-box;
padding: 10px;
width: 200px;
height: calc(100vh - 78px);
border: 1px solid #000;
}
.right {
float: right;
}
.left iframe {
/* 隐藏滚动条 */
scrollbar-width: none; /* firefox */
-ms-overflow-style: none; /* IE 10+ */
}
.left iframe::-webkit-scrollbar {
display: none; /* Chrome Safari */
}
style>
简单用原生js做了一个demo,代码还不够优美。
参考文献:《原生Javascript实现拖拽排序》