发表于: 2017-07-03 23:30:18

2 996


今天做了的事:完成任务九 
明天要做的事:任务十 
今天遇到的问题:稍后写在下面 
感悟:为张睢阳齿,为颜常山舌。 
前言:任务总结至今日应该是到任务六,也就是进入到安哥拉的内容。但是今天做完任务九之后,觉得对于安哥拉略微清醒了一点,所以今日先讲一下任务九,然后接下来讲其他。

第五集 涧中石

任务九的过程大致为这样:通过file reader读取选到的文件,使用file reader自带的方法读到这个文件的信息(文件名,大小和路径),然后把他显示在dom中。接下来把文件信息添加到form data对象中,然后一起提交到服务器端口。(中间还有一个实现文件传输进度的小地方)。

上传图片

这是一个自带属性,input的type定义为file,那么就可以选择图片

file reader

h5自带的file reader可以读取一个文件的文件名,大小和路径,但是奇怪的是这个input的值(选中的图片)没法通过双向绑定获取到,所以百度一下是这样操作的。 
onchange=’angular.element(this).scope().fileChanged(this)’ 
在选择文件的input上添加这样一个事件,当input发生变化的时候,就把变化的这个元素(或字符串)包装成一个勾圈儿元素(这个主要是angular.element的作用)。 
但是光这样还是不够的,因为这样仍然无法正确读出这个文件的src,下面我就要先讲一下刚刚看了一些的涉及安哥拉原理的内容。

angular context

在我们对浏览器进行操作(触发事件)的时候,事件的回调函数就会在javascript解释器里执行,然后你就可以做任何DOM操作,等回调函数执行完毕时,浏览器就会相应地对DOM做出变化。 Angular拓展了这个事件循环,生成一个叫做angular context的执行环境,故事就发生在这个angular context里面。

$watch()

其作用为监听Model的变化。每次你绑定一些东西到Model上时就会往watch队列里插入一条watch。

$digest循环

当浏览器接收到可以被angular context处理的事件时,digest循环就会触发。这个循环是由两个更小的循环组合起来的。一个处理evalAsync队列,另一个处理watch队列。此时digest会遍历watch队列,如果当前watch没有变化,就往下检查,直到有watch变化,那么digest把这个变化记录下来,并继续往下检查,检查完一遍watch队列之后,若曾有某个watch出现变化,那么久从头将这个watch队列重新检查一遍,直到没有任何变化发生。这时把之前检查出现的变化一次性更新在DOM中。 
这个就被称为脏检查机制。 
回顾一下上上条,当我们在某个input里面输入一行字符串的时候(触发了事件),那么根据我前文所说,安哥拉会生成一个angular context,即每一个进入angular context的事件都会执行一次digest(例如我们输入‘wang’,那么没输入一个字母,都会执行一次digest循环)。

$apply()

读到这里我们可以得知,只有进入angular context,才会执行digest循环,进而捕获到watch得到的DOM变化,进而才能修改DOM。(若不进入digest,在有事件发生时watch仍可捕捉到,但由于未进angular context,未进行digest循环,即使捕捉到变化也无法体现在Model上)。 
那么谁来控制能不能进入angular context,来进行后面的步骤呢?apply。 
当事件触发时,你调用apply,它会进入angular context,如果没有调用就不会进入。 
但是我们平时(包括本人做以前任务时候),ng-model拿来就用,也没见调用过apply,那为什么会实现双向绑定呢? 
因为安哥拉默默帮你做了。实际上几乎我们所有的代码都包在scope.apply()里面,像ng−click,controller的初始化,http的回调函数等。在这些情况下,我们不需要自己调用,实际上我们也不能自己调用,否则在apply()方法里面再调用apply()方法会抛出错误。如果我们需要在一个新的执行序列中运行代码时才真正需要用到它,而且当且仅当这个新的执行序列不是被angular JS的库的方法创建的,这个时候我们需要将代码用scope.apply()包起来。 
例如使用勾圈插件,和使用自定义指令,两种情况,安哥拉不会默默帮你apply,必须手动apply。

file reader续

接上文没说完的话头,我们通过angular.element将增加的文件包装成一个勾圈儿元素,接上一个知识点,涉及到勾圈了,安哥拉很傲娇,不会帮你apply,那么只好由我们来手动apply,将这个变化文件体现在dom上,然后让file reader读到,进而进行后续操作。 
当 FileReader 读取文件的方式为 readAsArrayBuffer, readAsBinaryString, readAsDataURL 或者 readAsText 的时候,会触发一个 load 事件。从而可以使用 FileReader.onload 属性对该事件进行处理。 
需要在这个onload事件内部获取,才能获得我们需要的result。但在这之前,别忘了手动apply。

file reader又续

聪明的读者读到这一定会听出我话中的意思,这里我们用的是一种类似于勾圈的实现方式,那么安哥拉呢,正如我一遍遍说到的,安哥拉的做法就是使用自定义指令,这里我明天就开始学习,不久的后面我会给大家介绍。

form data

FormData 对象,可以把form中所有表单元素的name与value组成一个queryString,提交到后台。在使用Ajax提交时,使用FormData对象可以减少拼接queryString的工作量。 
根据上述定义,我们的做法就很清晰了。首先定义一个新的form data对象,然后我们通过自带的append方法吧键值对添加到这个form data里面,最后通过POST方法一起提交到接口。 
整个过程没有难度,唯一需要注意的是使用POST提交formdata,那么请求头的文件格式要设置为undefined,让浏览器自动帮你填充。

上传进度

有一个安哥拉自带的方法,叫做uploadEventHandler,是这样操作的 
uploadEventHandlers: { 
progress:function(file) { 
$scope.progress = Math.round(file.loaded * 100 / file.total); 
} 
} 
其中,.loaded表示已经进行的工作,.total 表示总共需要的工作量,通过这个百分率,来控制进度条的百分比。 
当然也有file-upload之类的好用的插件。

函数的形参

今天在学习的过程中,发现很多js的基础还不够,包括一个函数什么时候要传进去一个形参,以及这个形参是用来干嘛的,他和实际参数之间的数据怎么交流的,今天看了一下,还不是很懂,在此就不多饶舌了,先挖坑于此,来日再补。 
当然也欢迎金超师兄及各位看官讲解一二,不胜感激。



返回列表 返回列表
评论

    分享到