javaScript
string
string换行
- string不能直接换行,换行需要搞事情:
- 加号拼接
- 每次换行行末加\
- ES6 模板字符串
正则表达式
实际就是词法分析器匹配字符。
常用匹配
/\d/ // 数字
/\w/ // 字母/数字/下划线
/\b/ // 单词边界
/\s/ // 空白
/a*/ // 闭包,0-n个a
/a+/ // 非零闭包,1-n个a
/a?/ // 0或1个a
/a{n}/ // n个a
/a{n,m}/ // n-m个a
/a{n,}/ // 最少n个
/a|b/ // a或b
/a[qwe]c/ // aqc/awc/aec
/[a-z]/ // a,b,c,...z
/[a-zA-Z]/ // a-z或A-Z
/[12-49]/ // 1或2-4或9 (1, 2, 3, 4, 9)
/a[^ab]c/ // a后字母非a或b,然后c
参数
// 这里面i和g就是参数,用来调整匹配选项
// 常用的: i(忽略大小写ignore) g(全局global) m(多行multi-line) u(unicode)
var exp = new RegExp('A', 'ig');
const exp1 = new RegExp(/\d/ig, 'i') // es5报错 es6中ig会被i覆盖
正则常用方法
str.search(expr|str); // 找到了返回位置,找不到返回-1,类似indexOf
str.match(expr|str); // 找到了返回结果数组,找不到返回null
str.split(expr|str); // 切数组
str.replace(expr|str, str|fn);
str.replace(expr|str, function(s) {
// s: 每次匹配到的东西
// return 要替换成xx
});
str.startsWith('abc'); // 用正则代替: /^abc/
str.endWith('abc'); // 用正则代替: /abc$/
reg.test(str) // 需要在reg前后加^和$才能用,测试能不能匹配到,返回Boolean
string操作
let str = 'abc';
/* 按字符串下标获取字符串 */
str[0]; // 'a', 不兼容ie6,7
str.charAt(1) // 'b'
let str='abcdefg';
let s=str.substring(0, 3); // 'abc', 从下标n开始,获取m个
/* 找到字符第一次在string中出现的下标 */
str.indexOf('c') // 2
str.indexOf('z') // -1
/* 从后往前找寻字符第一次在串中的下标 */
let str2 = 'aaa';
str2.lastIndexOf('a') // 2
/* 以某个符号拆分成数组 */
let str='1,2,3,4,5,6';
str.split(','); // [1,2,3,4,5,6], 可以用正则匹配
obj.toString(); // 强制转换为字符串
userAgent
获取浏览器UA会得到一大坨东西,用来识别浏览器不好使,这时候就要用到indexOf了
window.navigator.userAgent.indexOf('MSIE 7.0')
模板字符串
let a = `string1`; // 使用``代替''包裹字符串
let b = `string2`;
let c = `${a}and${b}`; // string1andstring2
基本数据类型
1. string
2. number // NaN属于number
3. boolean
4. undefined // undefined == null => true
5. function // 官方文档里没有定义function为数据类型,但typeof可以弹出
6. object // 可分为元素,array,null
7. global // es6顶层对象
数据真假(true/false)
false: false, 0, '', null, undefined, NaN;
true: true, 非空对象, 非0数字, 非空字符串;
检测数据类型
- isNaN() -> is Not a Number?true:false
- NaN == NaN -> false
- typeof sth -> type of sth
类型转换
显式转换
转换函数
转换函数是将字符串中第一个有效数字转换为数字
// string转换成整数,不一定是十进制,parseInt支持基方法,可指定基数来转换其他数字为十进制
parseInt('string')
parseInt('0xA') // result: 10
parseInt('0010') // result: 10
parseInt('FF', 16) // result: 255
// string转换成浮点数,不支持基方法
parseFloat('string')
parseFloat('2.2.5') // result: 2.2
parseFloat('0100') // result: 100
强制类型转换
Boolean(value) // '',0,null,undefined -> false
Number(value) // Number与转换函数不同在于,非数字将直接转换为NaN
String(value)
隐式转换
var x = '2'*2; // result: 4
var y = '2'+2; // result: '22' *加号就当连字符处理了*
/* 利用隐式转换可以便捷转换 */
var z = 2+''; // result: '2'
var n = '2'*1; // result: 2
var n = '2b'++; // result: NaN
流程控制语句
循环
遍历(Traversal)
有3种常用的遍历方法。
for (let i = 0; i < Things.length; i++) { // 这里i不能用const
// statement..
}
/* for in循环中,不管是遍历什么,prop类型都是string */
for (const prop in obj) { // 这里的变量prop可以用const
// statement..
}
while (condition) { // while是自定义循环条件,既是循环也是判断
// statement..
}
break
// 停止执行 result:0 1 2
for (let i = 0; i <= 5; i++) {
if (i==3) {
break;
}
alert(i);
}
continue
// 跳过本次执行 result:0 1 2 4 5
for (let i = 0; i <= 5; i++) {
if (i==3) {
continue;
}
alert(i);
}
9*9 乘法表
for (let i = 1; i <= 9; i++) { // 外层循环被乘数1-9
for (let j = 1; j <= i; j++) { // 内层循环乘数,不大于被乘数
document.write(i + '*' + j + '=' + i * j + ' ');
}
document.write('<br />'); // 每行末位换行
}
判断
三目运算符
三目运算符可用于缩写判断语句
if(condition){...} else {...} => condition ? statement1 : statement2;
if(true){...} => condition && statement1;
if(false){...} => condition || statement1;
// 用'||'的情况下,第一个条件true,不检测第二个直接返回true;
// 第一个条件false,会执行第二个条件检测。
作用域
在函数内部声明变量,则变量是该函数的局部变量
,在外部声明变量,则变量是全局变量
;
局部变量的作用域就是该函数内部
,全局变量的作用域就是全局;
!!若在函数内部不用指令声明变量,则实际声明了一个全局变量
;!!
function fn() {
i = 1; // globally scoped
}
window.onload = function () {
fn();
alert(i); // 1
};
日期对象Date()
- 当日期对象声明时,会获取到当前时间,并且不会自动改变,所以这里用
const
比较好; - 注意月份在计算机中存储是
0-11
,所以设置和获取的时候都要做处理; - 时间对象会自动进位,例如当月份为12时,年份+1;
const oDate = new Date();
oDate.setFullYear(2018, 1, 14); // 设置oDate为2018年2月14日
oDate.setHours(h, m, s, ms); // 设置oDate的时分秒和毫秒
const oHours = oDate.getHours(); // 获取oDate的小时数
const oMin = oDate.getMinutes(); // 获取oDate的分钟数
const oSeconds = oDate.getSeconds(); // 获取oDate的秒数
const oMonth = oDate.getMonth() + 1; // 获取月份为2月
const oMonth = oDate.getDay(); // 星期n, 0-6, 0是星期天
const oTime = oDate.getTime(); // 获取时间戳,1970.1.1 00:00至当前时间对象的毫秒数
数组(Array)
声明
let arr=[ 1, 2, 3 ];
let arr=new Array(1, 2, 3, 4);
arr = Array.of(3,2,1);
let arr=new Array(3); // 长度为3的空数组
数组操作
转换为字符串
let arr = [ 1, 'a', 2, 'b' ];
let arr2 = [ 1, 'a', 2, 'b' ];
arr.join(''); // arr: '1a2b'
arr2.join('&'); // arr: '1&a&2&b'
添加与删除
let arr = [ 1, 2, 3 ];
arr.push(5); // arr: [ 1, 2, 3, 5 ] 从后面插入
arr.unshift(0); // arr: [ 0, 1, 2, 3, 5 ] 从前面插入
arr.pop(); // arr: [ 0, 1, 2, 3 ] 从后面删除
arr.shift(); // arr: [ 1, 2, 3 ] 从前面删除
万能操作splice()
arr.splice(m, n, …)
- 从下标m开始,删除n个;
- 若n大于剩余长度,也可以执行;
- 若后面有元素则插入后面的元素;
let arr1 = [ 1, 2 ]
arr.splice(1, 2, 'a', 'b', 'c'); // arr: [1, a, b, c]
排序和连接
let arr = [ 1, 2, 3 ];
let arr1 = [ 4, 5, 6 ];
let arr2 = [ 7, 8, 9 ];
let arr3 = [ 31, 22, 15, 47, 'aa', 'bz', 'aa', 22 ];
alert(arr.concat(arr1,arr2)); // [1,2,3,4,5,6,7,8,9] 数组连接
alert(arr.reverse()); // [3,2,1] 数组倒序排列
alert(arr3.sort()); // [15,22,22,31,47,'aa','aa','bz'] 数组默认排序
alert(arr3.sort(function(a, b) { // 从小到大,return b-a是从大到小
return a - b;
}));
清空数组
let arr = [ 1, 2, 3, 4, 5 ];
arr.length = 0; // function 1
arr.splice(0, 5); // param1: index, param2: amount
while(arr.length > 0){
arr.pop();
}
json
json是一个对象,可以装任何东西,可以嵌套,json没有长度属性;
json由键值对组成,每个数据称为键(key),拥有一个相对应的键值(value);
键名类似于数组的下标,但数据类型是字符串,键值可以是任何形式;
es6中,最后一组键值对可以加,
;
取得json的键值有两种方式:
let json = { a:1, 'b':2, c:3 };
alert(json.a); // 1
alert(json.b); // 2
alert(json['a']); // 1
alert(json[a]); // error: not defined => 被当成数组了
json遍历
因为json没有长度属性,所以通常的for循环是不能遍历的,这里常用for in方法
const json = { a:1, 'b':2, c:3 };
for (const prop in json) { // for key in obj => key is string
console.log(prop + json[prop]);
alert(typeof prop); // string
}
// console: a1
// console: b2
// console: c3
json嵌套
const json = {
name: '小明',
job: '前端攻城狮',
addr: '杭州',
age: 20,
family: [
{ name: '小花', age: 25, job: 'java' },
{ name: '韩梅梅',
age: 28,
job: 'php',
family: [
{ name: '小花', age: 25, job: 'java' },
{ name: '韩梅梅', age: 28, job: 'php' }
]
}
]
};
eval解析json
const json='{ a:1, b:2 }';
const json1=eval('(' + json + ')');
/* eval解析字符串json时需要加括号,强制转换为对象 */
fn解析json
const json='{ a:1, b:2 }';
const fn=new Function('return' + json);
const json1 = fn(); // 解析的json
JSON转换
JSON.stringify('{"a":1,"b":2}'); // object to stirng
JSON.parse({"a":1,"b":2}); // string to object
/*
* JSON.parse() 解析的对象最后一个不能加逗号
*/
Math(本地对象)
Math.random(); // 获取0-1之间的随机小数不包括1
Math.ceil(); // 向上取整
Math.floor(); // 向下取整
Math.round(); // 四舍五入
Math.abs(); // 绝对值
Math.sqrt(); // 开方
Math.pow(); // n次方(幂)
Math.max(); // 求最大值
Math.min(); // 求最小值
严格模式
‘use strict’会产生一个script作用域,范围是当前js标签或文件内;
- 解决了局部函数中this是window的bug;
- 不用声明语句无法声明变量;
- 不允许在非函数的代码块内声明函数;
- 去除with;
ie9不兼容严格模式
javaScript的组成
- ECMAScript 核心解释器(ES5和ES6);
- DOM 文档对象模型(Document Object Model) <= document对象;
- BOM 浏览器对象模型(Browser Object Model) <= window对象;
DOM
DOM节点类型
- DOM中有两种节点类型,一种是元素节点ElementNode,即html标签;
- 还有一种TextNode,文本节点指文档中的文本,每个标签前后都有两个文本节点;
nodeType = 1
(element节点);nodeType = 3
(text节点);- 文本节点空着也是存在的;
DOM节点获取
子节点获取
在ie低版本中,obj.childNodes
可直接获取对象的子元素节点;
但在其他情况下,此操作会获取对象的全部子节点(文本节点和元素节点);
若要获取元素子节点,有3种常用方法:
- 用nodeType判断。nodeType = 1 (element节点);nodeType = 3 (text节点);
- 用
obj.children
,这种方法只会选择元素节点(只会选择子代不会选择子代的后代),obj.children
获取的节点是一个元素集合,obj.children[0]
<= 可以这样操作; - 用Element系列指令操作:
obj.firstElementChild
;obj.lastElementChild
;obj.nextElementChild
;obj.previousElementChild
;
兄弟节点获取
obj.firstElementSibling
;obj.lastElementSibling
;obj.nextElementSibling
;obj.previousElementSibling
;
兄弟节点和子节点Element语句有兼容性问题,以子节点为例,应该这样写:
obj.firstElementChild || obj.firstChild
父节点获取
obj.parentNode
元素节点tag名获取
获取node后可以用node获取tag名:
const obj = document.getElementById('id');
obj.tagName = 'LI'; // UpperCase
offset
obj.offsetParent
用来获取定位的参考父级元素;obj.offsetLeft
获取相对于定位父级的left;obj.offsetHeight
物体盒子模型高度;obj.scrollHeight
内容高度;- 当内容高度小于盒子,取盒子高度,否则取内容高度;
获取物体绝对位置
obj.getBoundingClientRect(); // 获取绝对位置;
// .left 左边距离页面左边的距离
// .top 上边距离页面上边的距离
// .right 右边距离页面左边的距离
// .bottom 下边距离页面上边的距离
DOM节点操作
插入新元素
首先,
var childNode = document.createElement(tagName)
此方法创建的元素会存储在内存中,并不显示在页面内。
若要使创建的节点置于html中,需要用到parentNode.appendChild(childNode)
将创建的节点置入指定父节点内。appendChild
方法会将结点插在父级末尾。
值得一提的是,append
方法会将childNode
剪切进新的节点尾部,而不是复制,利用这一点可以快速移动节点。
若要将节点插入父节点指定部位,需要用到insertBefore(childNode, existingNode)
,这个方法会将childNode
插入到existingNode之前。
删除元素
parentNode.removeChild(childNode)
复制元素
obj.cloneNode()
<= 返回复制的元素;obj.cloneNode(true)
<= 返回复制的元素包括该元素的子元素;
#####文档碎片 需要注意的是,在高版本的浏览器中,文档碎片是鸡肋
当遇到诸如,需要创建很多li时,若用循环一个个插入会造成性能低下,就像需要搬运很多小东西,却只一次搬运一件一样。
这时候,我们就可以用到文档碎片(DocumentFragment)了,它的作用相当于一个大的袋子,我们可以先把小东西都放进去,然后一次拎走,这样算法就优化很多了。
- 首先我们需要创建文档碎片
var oFrag = document.createDocumentFragment();
- 然后我们可以用循环将需要插入的元素放入碎片中,这里以正序插入为例:
oFrag.appendChild(ChildNode);
- 最后我们将碎片整体插入需要插入的节点内部
parentNode.appendChild(oFrag);
操作属性
- 获取:
obj.getAttribute('attrName')
; - 设置:
obj.setAttribute('attrName')
; - 删除:
obj.removeAttribute('attrName')
;
innerHTML bug
<body>
<div>
<h2>11111111</h2>
</div>
<input type="button" value="press" style="position: absolute; left: 50px; top: 50px;" />
</body>
<script type="text/javascript">
window.onload = function() {
const oDiv = document.querySelector('div');
document.querySelector('h2').onclick = function() {
alert('msg');
};
document.querySelector('input').onclick = function() {
oDiv.innerHTML += '<h3>222222</h3>';
// 对oDiv.innerHTML重新赋值会导致加在oDiv.innerHTML上的事件失效
};
};
</script>
批量修改css样式
在不封装任何方法的情况下,js本就是可以对css样式批量修改的,但都不好使,仅作了解。
with(obj.style){ // 性能低下
styleName = value;
styleName = value;
}
obj.style.cssText='width:200px;height:200px;'; // 会将当前行间样式清除后再添加
异常捕获
try{
// code try running
}catch(e){
// if error
// e: error msg
}
bom属性兼容
const scrollTop = document.documentElement.scrollTop || document.body.scrollTop;
const clientWidth = document.documentElement.clientWidth || document.body.clientWidth;
// etc..
Event
组合键
js中是不能用键码控制组合键的,这时候用到一些特别的键码,若按下返回true:
oEvent.ctrlKey
;oEvent.shiftKey
;oEvent.altKey
;
阻止默认事件
/* usually */
return false; // 同时会阻止冒泡
/* ie */
// 鼠标事件捕获
obj.setCapture && obj.setCapture(); // 捕获当前鼠标事件
// 释放捕获
obj.setCapture && obj.setCapture();
/* 兼容 */
function stopDef(e){
const oE = e || event;
oE.preventDefault ?
oE.preventDefault() :
window.event.returnValue = false;
}
事件冒泡
文档流中,触发子级事件会逐级依次触发父级事件,称为事件冒泡;
在某些情况下我们需要取消事件冒泡:
oEvent.cancelBubble = true; // ie, 但可兼容其他浏览器
oEvent.stopPropagation(); // chrome etc..
绑定与委托
事件绑定(监听)
我们有时会遇到这样的情况:同一个对象需要有多个事件,或多个文件中有多个事件需要文档加载完成后执行的代码,那么我们就不能再对对象加单个事件了,事件连等也不能完全解决我们的需要,这时候我们就需要事件绑定了。
- 非ie:
addEventListener
:
obj.addEventListener('event', function() {
// statement..
}, useCapture); // Boolean; true:使用事件捕获,反转事件流; false:冒泡;
// true的优先级大于false,同时出现true,父级优先;
- 兼容ie:
obj.attachEvent('on' + 'event');
- 兼容写法:
Object.prototype.adEv = function(ev, fn) { if (this.addEventListener) { this.addEventListener(ev, fn, false); } else { this.attachEvent('on' + ev, fn); } };
解除绑定
解除绑定(无法解除绑定的匿名函数), 因为匿名函数实际是每次都用constructor
生成了新函数;
Object.prototype.rmEv = function(ev, fn) { // 必须指定函数名
if (this.removeEventListener) {
this.removeEventListener(ev, fn, false);
} else {
this.detachEvent('on' + ev, fn);
}
};
事件源
事件源指第一个触发事件的对象,可以通过事件对象获取:
function a(e) {
const oE = e || event;
const target = oE.srcElement || oE.target;
alert(target.tagName); // 这里获取的标签名是大写,如果用标签名匹配记得大写
}
事件委托
事件冒泡会触发父级元素的事件,所以通过在父级绑定事件获取事件源,再对事件源进行操作,可以间接实现对子级的事件绑定,这叫做事件委托
子元素的事件可以委托给自身的父级元素,在点击子级时会触发绑定给父级的事件;
另外,无论子级层级高低都可以点透到子级;
- 提高性能(减少迭代);
- 可以给未来的元素加事件;
oUl.onclick = function(ev) { // 添加点击事件给父级
var oEvent = ev || event;
var oS = oEvent.srcElement || oEvent.target; // 获取点击的事件源(父级及所有子代)
if (oS.tagName == 'LI') { // 用某种方法匹配到需要元素
oS.style.background = 'red';
}
};
转码
/* 不含特殊字符 */
encodeURI(str);
decodeURI(str);
/* 含特殊字符 */
encodeURIComponent(str);
decodeURIComponent(str);
固定this指针
// 调用fn, 使this指向obj, 一般用作固定this到某个函数
fn.call(obj,arg1,arg2...);
fn.apply(obj,[arg1,arg2...]);
// 使用箭头函数,this指向父级
function aaa() {
() => {
console.log(this); // function aaa
}
}
多态
/*多态的基本概念:一个引用类型(变量)在不同情况下的多种状态。
js本身是无态的,天生就支持多态。*/
//Master类
function Master(name) {
this.name = name;
//方法[给动物喂食物]
}
//原型法添加成员函数
Master.prototype.feed = function(animal, food) {
window.alert('给' + animal.name + '喂' + food.name);
};
//动物类
function Animal(name) {
this.name = name;
}
//猫猫
function Cat(name) {
this.animal = Animal;
this.animal(name);
}
//狗狗
function Dog(name) {
this.animal = Animal;
this.animal(name);
}
//食物类
function Food(name) {
this.name = name;
}
//鱼
function Fish(name) {
this.food = Food;
this.food(name);
}
//骨头
function Bone(name) {
this.food = Food;
this.food(name);
}
var cat = new Cat('大花猫');
var fish = new Fish('黄花鱼');
var dog = new Dog('大花狗');
var bone = new Bone('猪骨头');
//创建一个主人
var master = new Master();
master.feed(cat, fish);
master.feed(dog, bone);
本地存储
cookie
- cookie一般存在网站根目录,因为父级目录无法读取子级目录的cookie;
- Expires/Max - Age: cookie有效期,默认值为session;
- cookie不能存中文,如果要存中文转成utf8;
- 数据类型均为string, 用JSON.parse()需要将JSON键加双引号;
- 删除cookie时,将有效期调成负值;
- cookie最大容量为4kb;
/**
* date: 2017-03-21 15:49:34
* author: AllocatorXy
* description: 原生cookie方法
*/
function setCookie(name, value, json) {
let str = name + '=' + value;
if (json) {
for (const k in json) {
switch (k) {
case 'expires': {
if (Number(json[k])) {
const oDate = new Date();
oDate.setDate(oDate.getUTCDate() + json[k]);
str += ';expires=' + oDate.toUTCString();
} else {
str += ';expires=' + json[k];
}
break;
}
default:
str += `;${k}=${json[k]}`;
break;
}
}
}
document.cookie = str;
}
function getCookie(name) {
const arr = document.cookie.split('; ');
for (let i = 0; i < arr.length; i++) {
const arr2 = arr[i].split('=');
if (name == arr2[0]) {
return arr2[1];
}
}
return ''; // 不存在的情况
}
function getCookieAll() {
const arr = document.cookie.split('; ');
const res = {};
for (let i = 0; i < arr.length; i++) {
const arr2 = arr[i].split('=');
res[`${arr2[0]}`] = arr2[1];
}
return res;
}
function removeCookie(name) {
setCookie(name, '', -2);
}
storage
h5提供了一个新的本地存储解决方案: localStorage和sessionStorage;
- 最大容量为5M;
- 数据类型依然是字符串;
- 不能被爬虫抓取;
- 存储东西太多会影响网页性能;
- 以key和value键值对组成;
/* localStorage和sessionStorage用法完全一样,只是有效期不一样 */
const ls = window.localStorage;
/* 设定一个值 */
ls.a = 'abc';
ls['b'] = '1234';
ls.setItem('c',89);
/* 获取一个值 */
alert(ls.a);
alert(ls['b']);
alert(ls.getItem('c'));
/* 删除 */
ls.removeItem('c'); // 删除一个
ls.clear(); // 清空
/* key */
ls.key(i); // 按索引取出某个键
ls.getItem(ls.key(i)); // 按索引取出某个键的值
onstorage
这个事件监控storage改变,当它改变时触发;
自定义属性
正常情况下除了低版本ie, 不能获取直接添加在标签中的自定义属性,有一些特殊方法;
get/setAttribute
obj.getAttribute('abc') // 获取obj的abc属性,返回的数据类型是string
obj.setAttribute('abc', 111) // 为obj设置abc属性
var a = obj.attributes; // 返回obj的属性集合NamedNodeMap
dataset
h5中新增了一种自定义属性对象,它在h5页面中这样呈现:
<div data-aaa="111"></div>
dataset
不是传统的js对象,而是DOMStringMap对象,在js中这样操作:
const a = obj.dataset; // 获取obj的所有以'data-'为前缀的属性
const b = obj.dataset.aaa; // 获取obj的'data-aaa'属性
const c = obj.dataset.aaBb // 获取obj的'data-aa-bb'属性,类似于angularJS
obj.dataset.aaBbCc = 1; // 设置obj的'aa-bb-cc'属性为1
需要注意的是,dataset的性能远低于attribute, 慎用!
遍历属性
元素的属性集合是可以被遍历的,但要尽量避免直接遍历:
for (let k in obj) {
console.log(k); // obj的所有属性全都被打印出来了,很恶心
}
这时候用dataset就很舒服:
for (let v in obj.dataset) {
console.log(v + '=' + obj.dataset[v]); // 这样只会打印'data-*'属性
}
classList
h5中提供了一种新的操作class的方法:
let c = obj.classList; // 返回DOMTokenList, 即obj的class集合
let d = obj.classList.value; // 标签的class值 形如:'class1 class2 class3'
另外针对classList还有几种新的方法:
obj.classList.add('active', 'a'); // 为obj添加类
obj.classList.remove('active'); // 为obj移除类
obj.classList.contains('active'); // 返回Boolean, 用于检测是否有某个类名
obj.classList.item(n); // 返回索引值为n的类名,若参数错误则返回第一个类名,但参数不能为空
/* 类似于jq的toggleClass, 若不存在类名返回true并为之添加类, 第二个参数可以不填 */
obj.classList.toggle('active', true|false);
文件操作
文件拖拽
oBox.ondragenter // 拖动文件进入oBox
oBox.ondragleave // 拖动文件离开oBox
oBox.ondragover // 拖动文件悬停在oBox
oBox.ondrop // 在oBox释放拖动的文件
////////////////////////////////////////////////
// oBox中drop事件触发必须阻止oBox中的dragover事件 //
////////////////////////////////////////////////
文件获取/读取
文件读取只能读取拖拽、文件上传input[type=file]获取到的文件;
<!-- 读取多个文件 -->
<input type="file" multiple>
oBox.ondrop = ev => {
// 拿到文件
const oFile = ev.dataTransfer.files[0];
// 读取文件基本信息
// alert(oFile.name);
// alert(oFile.size);
// alert(oFile.type);
// alert(oFile.lastModifiedDate);
const reader = new FileReader();
// reader.readAsText(oFile); // 以文本方式读取
reader.readAsDataURL(oFile); // 以base64方式读取
reader.onload = () => { //文件读取完毕后
alert(reader.result); //文件读取结果
};
return false; // 这里不组织默认事件会被浏览器打开文件
};