Heim > Web-Frontend > js-Tutorial > Hauptteil

js steuert das Ziehen von Dateien und ruft den Drag-Inhalt ab

小云云
Freigeben: 2018-02-23 14:52:08
Original
1797 Leute haben es durchsucht

Wenn ein Benutzer eine Datei auf ein Element des Browsers zieht, kann js die mit dem Ziehen verbundenen Ereignisse überwachen und die Ziehergebnisse verarbeiten. In diesem Artikel werden einige Probleme im Zusammenhang mit dem Ziehen von Dateien behandelt, aber auch nicht behandelt viele Probleme bezüglich der Kompatibilität.

Drag-Ereignisse

<code><span style="font-size: 14px;">js</span>jsDie Ereignisse, die Drag & Drop überwachen können, sind<span style="font-size: 14px;">drag</span><span style="font-size: 14px;">drag</span><span style="font-size: 14px;">dragend</span>, dragend<span style="font-size: 14px;">dragenter</span>, <code><span style="font-size: 14px;">dragexit(没有浏览器实现)</span> dragenter, <span style="font-size: 14px;">dragleave</span><span style="font-size: 14px;">dragexit (keine Browser-Implementierung)</span><span style="font-size: 14px;">dragover</span>, dragleave<span style="font-size: 14px;">dragstart</span>, <code><span style="font-size: 14px;">drop</span>Dragover,

<p>Dragstart<span style="font-size: 14px;"></span></p> , <span style="font-size: 14px;">dragenter(文件拖拽进)</span><code><span style="font-size: 14px;">drop</span><span style="font-size: 14px;">dragover(文件拖拽在悬浮)</span>, Einzelheiten finden Sie im MDN. <span style="font-size: 14px;">dragleave(文件拖拽离开)</span>Zu den Ereignissen im Zusammenhang mit dem Ziehen von Dateien gehören unter anderem <code><span style="font-size: 14px;">drop(文件拖拽放下)</span>dragenter (Einziehen von Dateien)
, dragover (Dateien ziehen, um sie zu schweben)<div class="code" style="position:relative; padding:0px; margin:0px;"><pre class="brush:php;toolbar:false">&lt;span style=&quot;font-size: 14px;&quot;&gt;var dropEle = document.querySelector('#dropZone');&lt;br&gt;dropEle.addEventListener('drop', function (e) {&lt;br&gt;    // &lt;br&gt;}, false);&lt;br&gt;&lt;br&gt;document.addEventListener('drop', function (e) {&lt;br&gt;    // &lt;br&gt;}, false);&lt;br&gt;&lt;/span&gt;</pre><div class="contentsignin">Nach dem Login kopieren</div></div>

, dragleave (Dateien ziehen, um sie zu verlassen)

, drop (Dateien per Drag & Drop ziehen) <code><span style="font-size: 14px;">drop</span>. Drag-Ereignisse können an bestimmte DOM-Elemente oder an die gesamte Seite gebunden werden. <span style="font-size: 14px;">dragenter</span><span style="font-size: 14px;">dragover</span>Standardverhalten verhindern<span style="font-size: 14px;">dragleave</span>Im Allgemeinen müssen wir nur die Geschäftslogik für die Handhabung von Drag-and-Drop-Dateien in

drop

Ereignis ist in Ordnung, warum müssen Sie

dragenter

, Dragover

<span style="font-size: 14px;">dropZone.addEventListener("dragenter", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragover", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragleave", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>    // 处理拖拽文件的逻辑<br>}<br></span>
Nach dem Login kopieren
,

<span style="font-size: 14px;">Dragleave</span><span style="font-size: 14px;">dragenter</span>Was ist mit diesen drei Ereignissen?

Denn wenn Sie eine Datei in einen Browser ziehen, der keine Ziehereignisse verarbeitet, öffnet der Browser die Datei. Wenn Sie beispielsweise ein Bild ziehen, öffnet der Browser dieses Bild und ziehen Sie eine PDF-Datei ohne PDF-Reader in den Browser, und der Browser öffnet die PDF-Datei.

Wenn der Browser die gezogene Datei öffnet, springt die Seite weg. Wir hoffen, die gezogene Datei zu erhalten, anstatt die Seite wegspringen zu lassen. Wie oben erwähnt, ist es das Standardverhalten des Browsers, die gezogene Datei zu öffnen. Wenn wir dieses Standardverhalten verhindern müssen, müssen wir es im oben genannten Fall verhindern. <code><span style="font-size: 14px;">drop</span>tatsächlich blockiert

<p>dragenter<span style="font-size: 14px;"></span></p> weder das Standardverhalten noch löst es den Browser aus, die Datei zu öffnen , Um Kompatibilitätsprobleme zu vermeiden, die bei einigen Browsern auftreten können, verhindern alle Ereignisse im Drag-Zyklus das Standardverhalten und verhindern das Sprudeln von Ereignissen. <span style="font-size: 14px;">e.dataTransfer</span><span style="font-size: 14px;">DataTransfer</span>Holen Sie sich die gezogene DateiWir werden sie in Drop ablegen Das Ereignisobjekt im Rückruf dieses Ereignisses kann das Dateiobjekt abrufen. Im Ereignisobjekt ist ein e.dataTransfer ein solches Attribut, es ist ein DataTransfer Daten vom Typ haben die folgenden Attribute
属性 类型 说明
<span style="font-size: 14px;">dropEffect</span> String 用来hack某些兼容性问题
effectAllowed String 暂时不用
<span style="font-size: 14px;">files</span> FileList 拖拽的文件列表
<span style="font-size: 14px;">items</span> DataTransferItemList 拖拽的数据(有可能是字符串)
types Array 拖拽的数据类型 该属性在Safari下比较混乱

<span style="font-size: 14px;">Chrome</span>中我们用<span style="font-size: 14px;">items</span>对象获得文件,其他浏览器用<span style="font-size: 14px;">files</span>获得文件,主要是为了处理拖拽文件夹的问题,最好不允许用户拖拽文件夹,因为文件夹内可能还有文件夹,递归上传文件会很久,如果不递归查找,只上传目录第一层级的文件,用户可能以为上传功能了,但是没有上传子目录文件,所以还是禁止上传文件夹比较好,后面我会说要怎么处理。

Chrome获取文件

<span style="font-size: 14px;">dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>    <br>    var df = e.dataTransfer;<br>    var dropFiles = []; // 存放拖拽的文件对象<br>    <br>    if(df.items !== undefined) {<br>        // Chrome有items属性,对Chrome的单独处理<br>        for(var i = 0; i < df.items.length; i++) {<br>            var item = df.items[i];<br>            // 用webkitGetAsEntry禁止上传目录<br>            if(item.kind === "file" && item.webkitGetAsEntry().isFile) {<br>                var file = item.getAsFile();<br>                dropFiles.push(file);<br>            }<br>        }<br>    }<br>}<br></span>
Nach dem Login kopieren

其他浏览器获取文件

这里只测试了Safari,其他浏览器并没有测试,不过看完本文一定也有思路处理其他浏览器的兼容情况。

<span style="font-size: 14px;">dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>    <br>    var df = e.dataTransfer;<br>    var dropFiles = []; // 存放拖拽的文件对象<br>    <br>    if(df.items !== undefined) {<br>        // Chrome拖拽文件逻辑<br>    } else {<br>        for(var i = 0; i < df.files.length; i++) {<br>            dropFiles.push(df.files[i]);<br>        }<br>    }<br>}<br></span>
Nach dem Login kopieren

由于<span style="font-size: 14px;">Safari</span>没有<span style="font-size: 14px;">item</span>,自然也没有<span style="font-size: 14px;">webkitGetAsEntry</span>,所以在Safari无法确定拖拽的是否是文件还是文件夹。

非Chrome内核浏览器判断目录的方法

浏览器获取到的每个file对象有四个属性:<span style="font-size: 14px;">lastModified</span><span style="font-size: 14px;">name</span><span style="font-size: 14px;">size</span><span style="font-size: 14px;">type</span>,其中<span style="font-size: 14px;">type</span>是文件的<span style="font-size: 14px;">MIME Type</span>,文件夹的<span style="font-size: 14px;">type</span>是空的,但是有些文件没有<span style="font-size: 14px;">MIME Type</span>,如果按照<span style="font-size: 14px;">type</span>是否为空判断是不是拖拽的文件夹的话,会误伤一部分文件,所以这个方法行。

那么还有什么方法可以判断呢,思路大概是这样子的,用户拖拽的文件和文件夹应该是不一样的东西,用<span style="font-size: 14px;">File API</span>操作的时候应该会有区别,比如进行某些操作的时候,文件就能够正常操作,但是文件夹就会报错,通过错误的捕获就能够判断是文件还是文件夹了,好我们根据这个思路来写一下。

<span style="font-size: 14px;">dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br><br>    var df = e.dataTransfer;<br>    var dropFiles = [];<br>    <br>    if(df.items !== undefined){<br>        // Chrome拖拽文件逻辑<br>    } else {<br>        for(var i = 0; i < df.files.length; i++){<br>            var dropFile = df.files[i];<br>            if ( dropFile.type ) {<br>                // 如果type不是空串,一定是文件<br>                dropFiles.push(dropFile);<br>            } else {<br>                try {<br>                    var fileReader = new FileReader();<br>                    fileReader.readAsDataURL(dropFile.slice(0, 3));<br><br>                    fileReader.addEventListener('load', function (e) {<br>                        console.log(e, 'load');<br>                        dropFiles.push(dropFile);<br>                    }, false);<br><br>                    fileReader.addEventListener('error', function (e) {<br>                        console.log(e, 'error,不可以上传文件夹');<br>                    }, false);<br><br>                } catch (e) {<br>                    console.log(e, 'catch error,不可以上传文件夹');<br>                }<br>            }<br>        }<br>    }<br>}, false);<br></span>
Nach dem Login kopieren

上面代码创建了一个<span style="font-size: 14px;">FileReader</span>实例,通过这个实例对文件进行读取,我测试读取一个1G多的文件要3S多,时间有点长,就用<span style="font-size: 14px;">slice</span>截取了前3个字符,为什么是前3个不是前2个或者前4个呢,因为代码是我写的,我开心这么写呗~

如果<span style="font-size: 14px;">load</span>事件触发了,就说明拖拽过来的东西是文件,如果<span style="font-size: 14px;">error</span>事件触发了,就说明是文件夹,为了防止其他可能的潜在错误,用<span style="font-size: 14px;">try</span>包起来这段代码。

三方应用的一点点小hack

经过测试发现通过<span style="font-size: 14px;">Mac</span><span style="font-size: 14px;">Finder</span>拖拽文件没有问题,但是有时候文件并不一定在<span style="font-size: 14px;">Finder</span>中,也可能在某些应用中,有一个应用叫做<span style="font-size: 14px;">圈点</span>,这个应用的用户反馈文件拖拽失效,去看了其他开源文件上传的源码,发现了这样一行代码:

<span style="font-size: 14px;">dropZone.addEventListener("dragover", function (e) {<br>    e.dataTransfer.dropEffect = 'copy'; // 兼容某些三方应用,如圈点<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br></span>
Nach dem Login kopieren

需要把<span style="font-size: 14px;">dropEffect</span>置为<span style="font-size: 14px;">copy</span>,上网搜了下这个问题,源码文档中也没有说为什么要加这个,有兴趣的同学可以找一下为什么。

可以拿来就用的代码

由于用了<span style="font-size: 14px;">FileReader</span>去读取文件,这是一个异步IO操作,为了记录当前处理了多少个文件,以及什么时候触发拖拽结束的回调,写了一个<span style="font-size: 14px;">checkDropFinish</span>的方法一直去比较处理的文件数量和文件总数,确定所有文件处理完了后就去调用完成的回调。

另外,我在最后调试异步处理的时候,用的断点调试,发现断点调试在<span style="font-size: 14px;">Safari</span>中会导致异步回调不触发,需要自己调试定制功能的同学注意下。

<span style="font-size: 14px;">// 获得拖拽文件的回调函数<br>function getDropFileCallBack (dropFiles) {<br>    console.log(dropFiles, dropFiles.length);<br>}<br><br>var dropZone = document.querySelector("#dropZone");<br>dropZone.addEventListener("dragenter", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragover", function (e) {<br>    e.dataTransfer.dropEffect = 'copy'; // 兼容某些三方应用,如圈点<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("dragleave", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br>}, false);<br><br>dropZone.addEventListener("drop", function (e) {<br>    e.preventDefault();<br>    e.stopPropagation();<br><br>    var df = e.dataTransfer;<br>    var dropFiles = []; // 拖拽的文件,会放到这里<br>    var dealFileCnt = 0; // 读取文件是个异步的过程,需要记录处理了多少个文件了<br>    var allFileLen = df.files.length; // 所有的文件的数量,给非Chrome浏览器使用的变量<br><br>    // 检测是否已经把所有的文件都遍历过了<br>    function checkDropFinish () {<br>        if ( dealFileCnt === allFileLen-1 ) {<br>            getDropFileCallBack(dropFiles);<br>        }<br>        dealFileCnt++;<br>    }<br><br>    if(df.items !== undefined){<br>        // Chrome拖拽文件逻辑<br>        for(var i = 0; i < df.items.length; i++) {<br>            var item = df.items[i];<br>            if(item.kind === "file" && item.webkitGetAsEntry().isFile) {<br>                var file = item.getAsFile();<br>                dropFiles.push(file);<br>                console.log(file);<br>            }<br>        }<br>    } else {<br>        // 非Chrome拖拽文件逻辑<br>        for(var i = 0; i < allFileLen; i++) {<br>            var dropFile = df.files[i];<br>            if ( dropFile.type ) {<br>                dropFiles.push(dropFile);<br>                checkDropFinish();<br>            } else {<br>                try {<br>                    var fileReader = new FileReader();<br>                    fileReader.readAsDataURL(dropFile.slice(0, 3));<br><br>                    fileReader.addEventListener('load', function (e) {<br>                        console.log(e, 'load');<br>                        dropFiles.push(dropFile);<br>                        checkDropFinish();<br>                    }, false);<br><br>                    fileReader.addEventListener('error', function (e) {<br>                        console.log(e, 'error,不可以上传文件夹');<br>                        checkDropFinish();<br>                    }, false);<br><br>                } catch (e) {<br>                    console.log(e, 'catch error,不可以上传文件夹');<br>                    checkDropFinish();<br>                }<br>            }<br>        }<br>    }<br>}, false);<br></span>
Nach dem Login kopieren

相关推荐:

如何实现文件拖拽上传

html5文件拖拽上传的示例代码分享

Dropzone.js实现文件拖拽上传功能

Das obige ist der detaillierte Inhalt vonjs steuert das Ziehen von Dateien und ruft den Drag-Inhalt ab. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Verwandte Etiketten:
Quelle:php.cn
Erklärung dieser Website
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn
Beliebte Tutorials
Mehr>
Neueste Downloads
Mehr>
Web-Effekte
Quellcode der Website
Website-Materialien
Frontend-Vorlage
Über uns Haftungsausschluss Sitemap
Chinesische PHP-Website:Online-PHP-Schulung für das Gemeinwohl,Helfen Sie PHP-Lernenden, sich schnell weiterzuentwickeln!