Skip to content

maxwelldu/HTML5Course20170717

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

84 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

HTML5Course20170717

##20170821

//获取元素
document.getElementById()  //一个DOM对象
DOM对象.getElementById()  
document.getElementsByTagName() //包含多个DOM对象的数组
DOM对象.getElementsByTagName()

//创建元素
document.createElement('') //可以创建p,div,span,link,script,img

//创建事件
document.createEvent('kaiyu');

//属性
innerText, innerHTML,checked(true|false ""|"checked"),title, value, src, href, contentEditable

//DOM元素API参考,包括属性和方法 https://developer.mozilla.org/zh-CN/docs/Web/API/Element

///修改皮肤就是切换样式的href属性值
通用的属性:id, class, name, title, style
document.title //获取文档的标题

//自定义属性
对原有标签的功能进行扩展,v-for, v-if, v-show;
用来在元素上面存储数据data-id="1" username="maxwell"

//属性操作
DOM对象.属性名  //获取属性
DOM对象.属性名 = 属性值 //设置属性

//非标准的属性需要使用以下方式去获取和设置,当然也对标准属性进行操作,是比较通用的
DOM对象.getAtrribute(属性名)  //获取属性
DOM对象.setAttribute(属性名, 属性值) //设置属性
DOM对象.hasAttribute(属性名) //判断是否有某个属性

//元素操作
DOM对象.appendChild(要添加的对象)
DOM对象.insertBefore(要添加的对象,要添加到哪个对象的前面)

//节点关系
DOM对象.childNodes  数组//获取所有的子节点,包括文本节点,元素节点,注释节点
节点.nodeType //值可以 1是元素节点
DOM对象.previousSibling //上一个兄弟节点,可能是文本节点或注释节点
DOM对象.previousElementSibling //上一个兄弟元素节点
DOM对象.parentNode //父节点

//样式
DOM对象.style.样式 //样式如果是中横线,需要改成驼峰命名;这里的样式只能够得到或者设置行内样式
getComputedStyle(DOM对象) //获取DOM对象的计算后属性的对象(CSSOM)
DOM对象.className 设置class的值,如果有多个,可以用字符串拼凑

//事件, 事件可以嵌套
//绑定事件
DOM对象.on事件名 = function() {
  //这里面的this指向当前对象
}

//取消绑定事件
DOM对象.on事件名 = null;

常用事件名:
鼠标:click, dblclick, mouseover, mouseout, mousedown, mouseup, mousemove,
contextmenu, mouseenter, mouseleave, mousewheel, DOMMouseScroll(Firefox),
mouseenter和mouseleave不会冒泡,mouseover, mouseout会冒泡
表单事件:submit, reset
键盘:keyup, keydown, keypress, input
窗口相关:scroll, resize
input框:invalid, focus(不冒泡), blur(不冒泡), change, input
资源加载:load, DOMContentLoaded
load事件是指当前页面结构加载完成,并且里面的所有资源都加载完成

//变量
全局变量其实就是把当前变量名放到window当中的一个属性

//函数
函数其实就是把函数名作为window当中的一个属性,他的值的是function

//调试能力:最重要,自学的时候有用,写代码的时候有用,调试的时候更有用
console.log()
console.dir()
断点调试,添加观察表达式,调用堆栈, 作用域(local, closure, global)
网络环境模拟
DOM断点
事件监听断点
Ajax断点

//概念的理解
user agent表示当前的浏览器,它代理你去上网
信号量 非常重要,一定要理解,就是页面元素的变化都根据这个信号量来决定,自己说的一个名词;实际上说白就是一个变量或者属性
业务逻辑方法  信号量和业务逻辑通常是对应的,业务逻辑会根据信号量的值作出不同的决定,到底是改变元素的颜色还是大小,还是位置等等
页面解析顺序是文本的从上到下;如果js代码写在需要获取的html元素之上的时候,会暴错,获取不到;如果需要写在上面,要添加window.onload事件
资源:只要是有链接地址的都是资源,不论里面的内容是什么;
html内容是资源, css文件,js文件,图片,音频,视频,网络字体文件,API
URL: 统一资源定位符
URL地址包括:http://www.baidu.com:80/news/index.php?username=a#fa
协议://域名或IP:端口号/路径/文件名?queryString#锚点(hash)
queryString和hash值都可以用来在页面之间传递

//页面传值:
本地存储,localStorage, sessionStorage, cookie

//技巧
state = !state //通常用来做 toggle 效果,或者开关
class设置样式,id属性用来给js使用
http://bbs.duchengjiu.top/read.php?tid=42
web6期时候的视频,包括git等:
链接: https://pan.baidu.com/s/1eS099sA 密码: du7w
命令行,工程化视频:链接: https://pan.baidu.com/s/1bpMuxXH 密码: ambq
//git是一个版本控制工具:针对修改(变化)的版本控制工具,历史管理,最主要的功能是备份和团队协作
下载git工具,到这个网址下载对应的版本 https://git-scm.com/downloads
//命令行操作(最主要的是心态,第一你能够意识当前学的这个东西非常有用,或者能提升效率;第二个你就会拼命的去把他学好;意味着你能够节省很多的时间,enjoy your life!) https://guoyongfeng.github.io/book/21/21/04-shell%20%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%9F%BA%E7%A1%80%E4%BD%BF%E7%94%A8.html
windows平台常用的命令行工具有git bash, putty, securecrt
, powershell
常用命令:
cd change directory改变目录
  cd /d/HTML5Course20170717/20170822
  cd ..
ls List 查看列表
  ls 查看当前文件夹中的文件
  ls -l 以长格式查看,包括权限,用户,大小,创建时间等
技巧:按tab键自动补全
输入任何命令都加一个 -v
输入过的命令通过上下箭可以选择
ctrl+a 直接跳到开头
ctrl+e 跳到当前行的末尾
ctrl+u 当前行内容全部删除|撤销

mkdir 文件夹名
rm -rv 文件夹名,只能删除空的目录,git bash可以删除非空的目录
rm -rfv 文件夹名 强制删除
touch a.js b.css index.html .gitignore
.开头的文件通常都是隐藏文件
.gitignore文件表示git仓库忽略提交的文件列表
. 表示当前目录
.. 表示上级目录
通常你输入的命令没有任何反应表示最好的响应
操作的时候一定要特别的小心谨慎,知道自己的命令会发生什么事;误操作有可能会把系统整崩,有可能删除数据库
通常编程中的目录和文件名最好全部是英文名,并且是小写
安装软件,有时候装到中文名的目录,也会发生问题
1.cd 目录切换

注意目录分隔符为“/”,与dos相反

# 格式:cd dirname,比如我们要进入到d盘的website目录
$ cd /d/website

# 到当前目录的上一级
$ cd ../

# 到当前目录的上上级
$ cd ../../

2.mkdir 新建文件夹

$ mkdir dirname
$ mkdir website

3.touch 创建文件

$ touch .gitignore
$ touch a.js b.html c.css

4.ls 显示文件

命令格式:ls [option] file

# 显示详细列表
$ ls -l

# ls -l的简写
$ ll

# 显示所有文件,包含隐藏文件(以. 起头的文件名)
$ ls -a

# 显示文件及所有子目录
$ ls -R
$ 显示文件(后跟*)和目录(后跟/)
$ ls -F

# 与l选项合用,显示目录名而非其内容
$ ls -d
5.pwd 显示当前路径

$ pwd
6.cat 显示文件内容

# 格式:cat filename
$ cat a.js

7.rm 删除文件或目录

命令格式: rm [-r] filename (filename 可为档名,或档名缩写符号.)

# 删除档名为 file1 之文档.
$ rm file1

# 删除档名中有五个字元,前四个字元为file 之所有文档.
$ rm file?

# 删除档名中,以 f 为字首之所有文档.
$ rm f*

# 删除目录 dir1,及其下所有文档及子目录.
$ rm -r dir1

8.cp 文档的复制

命令格式: cp [-r] source destination

# 将文档 file1 复制成 file2
$ cp file1 file2

# 将文档 file1 复制到目录 dir1 下,文件名仍为 file1.
$ cp file1 dir1

# 将目录 /tmp 下的文档 file1复制到现行目录下,文件名仍为 file1.
$ cp /tmp/file1 .

# 将目录 /tmp 下的文档 file1现行目录下,档名
为file2
$ cp /tmp/file1 file2

# (recursive copy) 复制整个目录.
$ cp -r dir1 dir2

# 复制dir1整个目录到dir2
$ cp -R dir1 dir2

9.mv 移动文件

命令格式: mv source destination

# 将文档 file1,更改档名为 file2.
$ mv file1 file2

# 将文档 file1,移到目录 dir1 下,档名仍为 file1.
$ mv file1 dir1

# 若目录 dir2 不存在,则将目录 dir1,及其所有档案和子目录,移到目录 dir2 下,新目录名称为 dir1.若目录dir2 不存在,则将dir1,及其所有文档和子目录,更改为目录 dir2.
$ mv dir1 dir2

10.grep 搜索

$ grep string filename
# 在a.js文件中查找===字符串,并且显示行号
$ grep -rn '====' a.js
vim: 链接: http://pan.baidu.com/s/1hr2W8RE 密码: qay8
vim 05-vim.html
ESC 在不同模式之间切换
进入插入模式之后不能输入各种命令
i 在当前位置前面插入
I 在当前行首插入内容
o 在当前行下面插入一行
O 在当前行上面插入一行
a 在当前位置后面插入字符
A 在当前行尾插入字符

移动:
hjkl : wasd类似
gg 文件的开头第一行
w e b 单词之间跳转
显示行号,进入末行模式 :set nu
在命令模式下输入:

:100 到100行
100G 到100行
:1,5 copy 7   拷贝1-5行,粘贴到第7行
字符选择,按v
复制 y 复制一行yy 复制10行 10yy  复制当前光标到末尾 y$ 复制当前光标到文件末尾yG
粘贴 p
命令状态:
j,k,h,l:上下左右
0: 行首
$: 行尾
i,I :插入命令,i 在当前光标处插入 I 行首插入
a,A:追加命令,a 在当前光标后追加,A 在行末追加
o,O:打开命令,o 在当前行下打开一行,O在当前行上插入一行
r,R :替换命令,r 替换当前光标处字符,R从光标处开始替换
数字s: 替换指定数量字符
x: 删除光标处字符
dd: 删除当前行
d0: 删除光标前半行
d$: 删除光标后半行
ctrl+f :后翻页
ctrl+b:前翻页
G : 文件尾
数字G: 数字所指定行
/string 查找字符串
n 继续查找
N 反向继续查找
% 查找对应括号
u 取消上次操作
ex命令状态
:0 文件首
:1,5 copy 7 块拷贝
:1,5 del 块删除
:1,5 move 7 块移动
:1,$s/string1/string2/g 全文件查找string1并替换为string2
:wq! 存盘退出
github
程序员的社交网站 没有妹子,只有代码  开源项目的集中地
注册一个github帐号,需要在邮箱中进行验证
下载git命令行工具
打开命令行工具:
git config --global user.name "你的github用户名"
git config --global user.emal "你的github邮箱"


git clone 仓库地址
git pull

git的更多学习:https://guoyongfeng.github.io/book/01/04-git%E5%91%BD%E4%BB%A4%E8%A1%8C%E5%9F%BA%E6%9C%AC%E4%BD%BF%E7%94%A8.html
在bbs.duchengjiu.top这个网站找一下git系列教程

将本地修改提交到远程仓库
git add .
git commit -m '描述'
git push origin master

正负性的值 http://www.cnblogs.com/snandy/p/3589517.html

IIFE

// 最常用的两种写法
(function(){ /* code */ }()); // 老道推荐写法
(function(){ /* code */ })(); // 当然这种也可以

// 括号和JS的一些操作符(如 = && || ,等)可以在函数表达式和函数声明上消除歧义
// 如下代码中,解析器已经知道一个是表达式了,于是也会把另一个默认为表达式
// 但是两者交换则会报错
var i = function(){ return 10; }();
true && function(){ /* code */ }();
0, function(){ /* code */ }();

// 如果你不怕代码晦涩难读,也可以选择一元运算符
!function(){ /* code */ }();
~function(){ /* code */ }();
-function(){ /* code */ }();
+function(){ /* code */ }();

// 你也可以这样
new function(){ /* code */ }
new function(){ /* code */ }() // 带参数

##20170822

onload事件在window对象,还有图片对象,音视频

vim 中写代码,按大小写的aio都可以进入插入模式 按ESC,然后输入 :wq! 保存并强制退出 ZZ 也保存退出 :w 保存 :q 退出

reset.css

/* http://meyerweb.com/eric/tools/css/reset/
   v2.0 | 20110126
   License: none (public domain)
*/

html, body, div, span, applet, object, iframe,
h1, h2, h3, h4, h5, h6, p, blockquote, pre,
a, abbr, acronym, address, big, cite, code,
del, dfn, em, img, ins, kbd, q, s, samp,
small, strike, strong, sub, sup, tt, var,
b, u, i, center,
dl, dt, dd, ol, ul, li,
fieldset, form, label, legend,
table, caption, tbody, tfoot, thead, tr, th, td,
article, aside, canvas, details, embed,
figure, figcaption, footer, header, hgroup,
menu, nav, output, ruby, section, summary,
time, mark, audio, video {
	margin: 0;
	padding: 0;
	border: 0;
	font-size: 100%;
	font: inherit;
	vertical-align: baseline;
}
/* HTML5 display-role reset for older browsers */
article, aside, details, figcaption, figure,
footer, header, hgroup, menu, nav, section {
	display: block;
}
body {
	line-height: 1;
}
ol, ul {
	list-style: none;
}
blockquote, q {
	quotes: none;
}
blockquote:before, blockquote:after,
q:before, q:after {
	content: '';
	content: none;
}
table {
	border-collapse: collapse;
	border-spacing: 0;
}

实体字符:

  空格
>   >
&lt;   <
&copy; 版权号
&reg;  
&quot; "
&amp;  &

##组件化思想

将一个小组件的css写好之后放到一个css文件
组件对应的js放到一个js文件中
在需要使用的页面将css和js引入;写上对应的html结构就搞定了

##伪代码|画图

假的代码,能够指导你的开发思想
可以用中文加上你会写的代码,描述性的
好处:让你从没思路到有思路
如果伪代码也写不出来,在图纸上多画一画, 光去想想不出来的时候写出来画出来,慢慢思路就有了

#20170823

html,css,js代码缩进使用2个空格,不要使用tab或四个空格
html元素中的id主要给js用,不要给css用
写方法的话,尽可能让一个方法只完成一件事情
后面写构造函数(类)的时候,一个类只描述一个对象

可以使用正则的常用方法有
字符串的 `replace`, search, match, split
正则对象的 exec `test`
所有语言都有正则,是通用的技能

正则表达式的创建
字面量的方式:/正则/修饰符
对象的方式:  new RegExp('正则字符串', '修饰符');

- 字符类型
  . 除了回车换行之外的任意字符
  \d [0-9]
  \D [^0-9]
  \s 空白字符
  \S 非空白字符
  \w [0-9a-zA-Z_]
  \W 非\w
  \t 制表符
  \n 换行符
- 字符集合
  [1234] 表示一个字符,匹配1,2,3,4中的任意一个
  [^1234] 表示一个字符,匹配不是1,2,3,4的任意一个

- 边界
  ^ 匹配开头
  $ 匹配结束
  \b 匹配单词边界
- 分组与反向引用
  ()
- 或者
  | 可以单独使用或者在分组内部使用;不能够在字符集中使用, 在字符集中就表示一个竖线
  a|b
  (sina|qq)  
  [sina|qq]  x错误的使用方式
- 数量词
  {2} 精确匹配前面的一个字符或一个分组2次
  {2,} 至少2次,最多不限
  {2,8} 匹配2次到8次之间
  ? 0或1次
  + 1或多次
  * 0或多次

html hack: 针对IE9做什么事情

 <!--[if lt IE 9]>
    <script src="https://cdn.bootcss.com/html5shiv/3.7.3/html5shiv.min.js"></script>
    <script src="https://cdn.bootcss.com/respond.js/1.4.2/respond.min.js"></script>
  <![endif]-->
  ```

CSS透明度:
css hack

.transparent_class { /* IE 8 */ -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)";

/* IE 5-7 */ filter: alpha(opacity=50);

/* Netscape */ -moz-opacity: 0.5;

/* Safari 1.x */ -khtml-opacity: 0.5;

/* Good browsers */ opacity: 0.5; }


#20170824
<<<<<<< HEAD

=======

78e9c24225fa2a100059945c07d9bb8783946153 表单验证的方式:

  • 在表单的submit事件中:验证失败返回false, 表单将不会提交;全部通过返回true, 正常提交表单
  • 在form的input元素blur事件,当验证失败给当前input元素的状态设置为false, 并将整个表单的一个状态进行重新计算,当表单的状态为可用,让提交按钮可用; 表单状态信号 = input1.状态信号 === true && input2.状态信号 === true ... 表单状态信号 = input1.状态信号 && input2.状态信号 ... 手动提交表单:oForm.submit();

造轮子:把基础的东西我们要自己写出来;以后需要开发类似的功能,可以直接使用 包括了 - js验证库(写一堆校验的方法) - css库(写一堆方便使用的class样式) - web组件库(写一堆有界面有交互的小挂件,小组件)组件就是我们网页中经常会出现的一些小模块(包括了html,css,js)

透明度: opacity: .2; filter: alpha(opacity=20);

js设置透明度: var oSpan = document.getElementsByTagName('span')[0]; var opacity = 0.1; oSpan.style.opacity = opacity; oSpan.style.filter = "alpha(opacity=" + opacity*100 + ")"


针对最新的浏览器:

offsetParent 找到离自己最近的已定位的元素为参考元素 offsetLeft 自身的border外侧到offsetParent元素的内边框 offsetTop offsetWidth width + padding + border offsetHeight height + padding + border clientWidth width + padding clientHeight height + padding


开启定时器

var timer = setInterval(函数, 间歇时间); //函数的地方不要去调用,直接给函数 //方式一 var timer = setInterval(function(){ }, 1000); //方式二 function fun() { } var timer = setInterval(fun, 1000); 停止定时器 clearInterval(timer);

定时器的注意事项:在你开启定时器之前最好先关闭定时器:设表先关


##标准的动画

//配置参数 var oDiv = document.getElementById('odiv'); var time = 1000; var interval = 20; var frames = time / interval; var distance = 400; var step = distance / frames;

//信号量 var startLeft = 100;//起始位置信号量 var frame = 0; //当前帧信号量

var timer = setInterval(function(){ frame++; oDiv.style.left = startLeft + step * frame + 'px'; if (frame >= frames) { clearInterval(timer); } }, interval);


图片的load事件,表示图片已经下载完成 offsetLeft, offsetWidth, clientWidth这些值都需要等图片下载完成之后才能获得

//当页面上所有的资源都加载完成之后再执行, 这个方法只能绑定一次,绑定多次会覆盖 window.onload = function(){

} //这个事件是当页面内容加载完成的时候会执行,可以绑定多次,会依次执行 document.addEventListener('DOMContentLoaded', function(){

}) //jquery的写法,当DOM内容加载完成的时候执行 $(function(){

});


如何判断页面上所有的图片都加载完成 通过一个加载完成的个数信号量,加载完一张就把信号量+1, 当信号量的值和图片标签的个数相等时,表示页面中的所有图片加载完成 在图片加载完成之后就可以让无缝滚动的功能开始工作


通用的技术点:

正则 JSON

JSON编码格式必须是UTF-8, 如果是GBK或其他则需要先转换后再生成JSON

前后端的区分: 前端是指工作在浏览器上面的所有事情都是前端负责(html, css, js[动态效果,和后端打交道,获取数据]) 后端是工作在服务器上的所有事情:动态编程语言(java,php,python,ruby)+数据库(mysql,mongodb,redis)


##20170825

系统的难看的各种组件,在以后的工作中基本上都需要去自己封装一个类似的,比如: alert 警告框 confirm 确认框 prompt 输入框,可以在里面输入内容 模态框 和html,css相关的有:特殊的是checkbox, radio, select, file文件上传 和js相关:html5的验证错误提示信息要能够接收并处理; 滚动条

onload事件只能绑定一个,重复绑定会使用最后一个 页面的DOM结构加载完成的事件是: document.addEventListener('DOMContentLoaded', function(){ console.log(2); }); 这个事件可以绑定多次,当HTML结构被解析完成之后就会调用当前事件


XML 凯玉同学 18


JSON 对象{} 数组[]

访问值 对象.属性名 对象[属性名变量或字符串]


二维数组:

var arr = []; // arr[0][0] = '凯玉'; //这个是会报错 //如果需要使用二维数组,需要先把数组中的项变成一个数组

for (var i = 0; i < 3; i++) { arr[i] = []; for (var j = 0; j < 3; j++) { arr[i][j] = j; } } console.log(arr);


删除属性: delete obj.property; delete后面跟变量,不会报错,但是无法删除变量(实际上就是无法删除window中的属性);只能够用来删除自定义对象中的属性

window对象是宿主对象 对象的遍历:(会遍历到原型上面的允许枚举的属性) for (var k in obj) { console.log(k, obj[k]); }


BOM对象中有定时器,navigator对象, location对象 navigator就是浏览器对象,里面最主要的一个属性是userAgent, 标识了浏览器;我们可以使用userAgent区分出IE,FF,Chrome, Safari, Opera或者手机上面的浏览器,像UC, 微信浏览器等等; 这个属性还可以被后端利用,可以让手机访问网站的时候直接跳转到手机站 alert(navigator.userAgent);

比如访问此地址: 03-navigator.html#username=kaiyu location.hash 的值就是我们之前所学的锚点的内容#username=kaiyu 比如访问此地址:03-navigator.html?age=10 location.search 的值是 ?age=10 后面学习表单和AJAX的时候就知道这个也叫queryString, 就是GET请求时候的参数 location.href属性可以让页面跳转 location.reload() 刷新当前页面 location.assign() 相当于修改 location.href属性, 是可以通过历史记录后退到之前的页面 location.replace() 把当前页面替换成目标页面,不能通过历史记录后退到之前的页面

//每3秒刷刷新当前页面 //3秒之后跳转到百度页面


回调函数:通常就是调用函数的时候传递函数作为参数;在调用的函数内部会自动调用我们传递进去的函数; 可以有效的通知我们事情完成的情况,是成功了,失败了,还是在什么状态 我们可以定制当程序在不同阶段的时候执行我们自定义的函数 function a(cb) { cb && cb(); } a(function(){ console.log('回调函数里面的内容'); });


异步:

就是程序不会立即执行:比如setTimeout, setInterval, 绑定事件,ajax

call和apply都可以执行函数,并且第一个参数是改变函数内部this的指向 call在执行函数的时候,如果函数有参数,传递参数是以逗号分隔的参数列表 apply在执行有参数的函数时,第二个参数传递一个数组,数组中的值依次传递到调用函数的中

函数的默认值写法 callback = callback || function(){};

和下面的语句一样 if (!callback) { callback = function(){} }

//相当于判断callback有值的时候执行 callback && callback(); 和下面的语句一样 if (callback) { callback(); }


##20170828

var timer = setTimeout(function(){ }, 3000); clearTimeout(timer);


逐帧动画:(原理是使用定时器周期性的更改雪碧图[精灵图]{sprit}的背景定位)

var x = 0; var y = 0; var n = 0; var timer = setInterval(function(){ n++; x -= 190; console.log(x, y); div.style.backgroundPosition = x + "px" + " " + y + "px"; if(x <= -760){ x = 0; y -= 190; } if(y <= -2000){ x = 0; y = 0; } if (n >= 9) { clearInterval(timer); } }, 1000)


函数截流一:

var lock = true; oDiv.onclick = function(){ if (!lock) return; lock = false; setTimeout(function(){ lock = true; }, 3000); //执行具体的业务逻辑,3秒钟之后能够再次点击 }

函数截流二:

function throttle(fn, delay, context) { context = context || null; clearTimeout(fn.timeoutId); fn.timeoutId = setTimeout(function(){ fn.call(context); }, delay); } function queryData() { console.log('搜索:' + this.value); } var oInput = document.querySelector('#search'); oInput.onkeyup = function(){ throttle(queryData, 500, this); }


轮播图核心

var oRightBtn = document.querySelector('#rightBtn'); var oCirclesLi = document.querySelector("#circles").querySelectorAll('li'); var oMUnit = document.querySelector("#m_unit"); var oUl = oMUnit.querySelector('ul'); var oLi = oUl.querySelectorAll('li');

var imgLength = oLi.length; var width = 780; var animatetime = 600; var tweenString = "BounceEaseOut"; var interval = 2000; var index = 0; //0 1 2 3 4

//把0号li克隆,然后添加到carouseUL的最后 oUl.appendChild(oLi[0].cloneNode(true));

oRightBtn.onclick = rightBtnHandler; function rightBtnHandler() { //如果本身在运动,则不做任何事 if (oMUnit.isAnimated) return;

index++; changeCircles(); animate(oMUnit, {"left":-width*index}, animatetime, tweenString, function(){ if (index > imgLength - 1) { index = 0; this.style.left = "0px"; } }); }

//更换小圆点 function changeCircles() { //n是信号量的副本 var n = index; if (n === imgLength) { n = 0; }

for (var i = 0; i < oCirclesLi.length; i++) { oCirclesLi[i].className = ""; } oCirclesLi[n].className = "current"; }


###间歇模型

var oUl = document.querySelector('ul'); var oLi = document.querySelectorAll('li'); var length = oLi.length;

oUl.appendChild(oLi[0].cloneNode(true)); var index = 0; function move() { index++; animate(oUl, {"top": -40*index}, 800, function(){ if (index > length -1) { index = 0; this.style.top = "0px"; } }); } //调用动画函数的间隔时间,要远大于动画运行时间 //这时就给人感觉是一个间歇的过程 setInterval(move, 1800);


##20170829

函数中的函数想要使用绑定事件的对象;需要先在外层声明一个变量保存this var self = this;


oLis[i].onmouseenter = function(){ var self = this; //得到当前的子元素dropbox var mydropbox = (function(){ for (var i = 0; i < self.childNodes.length; i++) { if (self.childNodes[i].className === 'dropbox') { return self.childNodes[i]; } } })(); }


变量作用域要么是全局的,要么是函数中局部的 ES6中有块级作用域: for (let i = 0; i < 10; i++) { console.log(i); } console.log(i);

ES6的模板字面量,支持换行,单引号,双引号,变量: ${变量的名称} ${对象.属性} <span>${i}</span> https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Global_Objects/String


特定的DOM元素移动(原因是一个页面上,特定的DOM对象只有一个,所以说你把他添加到其他位置,那之前的就会消失)


DOM0级事件只能够监听冒泡阶段 oSpan.onclick = function(){

} 事件移除 var oDiv = document.querySelector('div'); oDiv.onclick = function(){ console.log(1); this.onclick = null; }


###DOM2级事件(非IE低版本)

oSpan.addEventListener('click', function(){ }, false); //true表示捕获阶段,false表示冒泡阶段 如何移除事件 var oSpan = document.querySelector('span'); function cli() { console.log(2); this.removeEventListener('click', cli); } oSpan.addEventListener('click', cli);


###低版本IE的事件删除

var oDiv = document.querySelector('div'); function fn(){ alert(1); oDiv.detachEvent('onclick', fn); } oDiv.attachEvent('onclick', fn); 低版本IE中事件中的this是指window对象 oBox1.attachEvent('onclick', function(){ change.call(oBox1); });


DOM0级事件不能重复绑定,因为只是给一个属性赋值 DOM2级事件的addEventListener重复绑定事件会按照先后顺序执行 低版本IE事件能够重复绑定,执行顺序是倒序

对于点击目标对象来说,给他添加的事件监听,是否捕获对当前对象无效,都只是绑定事件而已,按照先后顺序执行

添加事件的轮子 function addEvent(obj, eventtype, fn) { if (obj.addEventListener) { obj.addEventListener(eventtype, fn, false); } else if(obj.attachEvent){ obj.attachEvent("on" + eventtype, function(){ fn.call(obj); }); } else { obj["on" + eventtype] = fn; } }


修改函数中this的指向可以使用call, apply, bind fun.call(this指向的对象, 参数1, 参数2...) fun.apply(this指向的对象,[参数1,参数2...]) fun.bind(this指向的对象) 返回的一个新的函数,新的函数内部的this值为当前指定的


##20170830

基础数据类型都是值传递(包括数字,字符串,布尔值,undefined) 对象都是引用传递, 传递的是对象的内存地址,这个地址能够访问到真实的对象(数组,对象,函数,日期对象,数学对象)


自定义事件一:

var elem = document.querySelector('div'); //创建一个基于Event类型的事件 var eve = document.createEvent('Event'); //给事件定义一个名字 // initEvent(自定义事件名称,是否冒泡,true能冒泡,是否能被取消,false不能取消) eve.initEvent('build', true, true); //添加build事件 //e.target 表示当前的元素 elem.addEventListener('build', function (e) { console.log(this); console.log(e.target); }, false);

var oSpan = document.querySelector('span'); oSpan.onclick = function() { elem.dispatchEvent(eve); }


自定义事件二:

//创建一个自定义事件,事件名称为kaiyu var eve = new Event('kaiyu'); var elem = document.querySelector('div'); var oSpan = document.querySelector('span'); elem.addEventListener('kaiyu', function () { console.log(this.innerText); }); oSpan.onclick = function(){ elem.dispatchEvent(eve); }

自定义事件的调用,我们又称为分发,dispatch

//浏览器会向所有的事件方法中传递一个实际的事件对象,在方法中写一个 event接收 oDom.onclick = function(event) { event = event || window.event; event.type //通用的事件类型 var target = event.target || event.srcElement; //事件目标,在冒泡中,依然是触发事件的那个元素

event.currentTarget //在冒泡中,当前的对象 }

阻止事件传播(包括捕获和冒泡阶段)及兼容处理: if (event.stopPropagation) { event.stopPropagation(); } else { event.cancelBubble = true; }

阻止默认行为: if (event.preventDefault) { event.preventDefault(); } else { event.returnValue = false; }


模拟元素点击:

oDom.click(); //点击oDom oDom.focus(); //获得焦点 oForm.submit(); //提交表单 oForm.reset(); //重置表单,让表单元素里面的值恢复默认值

验证错误会触发 invalid事件,这个时候可以自定义错误的显示方式, 比如放到一个span元素中,而不是系统默认的弹出样式

获取当前input框的验证信息(html5的input类型) oDom.validationMessage

设置自定义的错误信息: oDom.validationMessage = '自定义值';


###鼠标移动事件相关的:

event.clientX, event.clientY event.screenX, event.screenY event.offsetX, event.offsetY 之前不兼容,或者现在用的时候无法使用,比如两个元素的时候会冒泡

键盘事件,得到输入的键码: event.keyCode event.key


事件委托:

oUl.onclick = function(event) { event = event || window.event; var t = event.target || event.srcElement; // console.dir(t); if (t.nodeName === 'LI') { t.parentNode.removeChild(t); } }


contentEditable设置为 true,当前元素可以编辑

##20170831

keyCode对照表 http://www.cnblogs.com/shyy/archive/2012/04/09/2453029.html

HTML5表单里面的input可以支持正则验证 pattern属性里面写正则字符串,不带/ required表示当前值为必填


在一个普通的input元素,外面不包括form表单时,如何回车搜索或跳转:

document.addEventListener('DOMContentLoaded', function(){ var oInput = document.querySelector('#search'); oInput.addEventListener('keyup', function(event) { event = event || window.event; console.log(event.keyCode); if (event.keyCode === 13) { location.href = "https://www.baidu.com/s?wd="+this.value; //提交表单 //oForm.submit(); } }); });


在表单中,回车切换到下一项实现一:批量绑定事件:

document.addEventListener('DOMContentLoaded', function(){ var oInput = document.querySelectorAll('input');

for (var i = 0; i < oInput.length; i++) { (function(i){ oInput[i].addEventListener('keydown', function(event){ event = event || window.event; //当前元素不是提交按钮,并且按回车 if (this.type != "submit" && event.keyCode === 13) { event.preventDefault();//默认行为会提交表单 oInput[i+1].focus();//让下一个元素获得焦点 } }); })(i); } })



获取元素在页面中的净位置

function getAllTop(obj) { //累加器,累加器的初始为自己现在的offsetTop值 var allTop = obj.offsetTop; //当前正在计算高度的元素 var currentObj = obj; while (currentObj = currentObj.offsetParent) { allTop += currentObj.offsetTop; } return allTop; }


页面卷动值:

var scrollTop = document.body.scrollTop || document.documentElement.scrollTop; document.body.scrollTop = document.documentElement.scrollTop = 0;


得到窗口的宽度和高度

var windowwidth = document.body.clientWidth || document.documentElement.clientWidth; var windowHeight = document.body.clientHeight || document.documentElement.clientHeight;


js实现响应式

通过窗口的resize事件实时得到当前窗口的宽度值,根据不同宽度切换不同的css外链样式


显示鼠标当前位置在所在元素的坐标

默认的有offsetX, offsetY, 之前不兼容 有些时候当有子元素的时候还是不可用,比如在放大镜,需要我们自己周转 var offsetXValue = event.clientY - (getAllTop(obj) - scrollTop);


##20170901
吸顶效果:

var mainNav =document.querySelector('#main-nav'); var topDis = getAllTop(mainNav); window.onscroll = function(e) { var nowTop = document.documentElement.scrollTop || document.body.scrollTop; if(nowTop >= topDis) { mainNav.style.position = 'fixed'; mainNav.style.marginTop = 0; }else { mainNav.style.position = 'relative'; mainNav.style.marginTop = topDis + 'px'; } };

function getAllTop(obj) { var allTop = obj.offsetTop; while(obj = obj.offsetParent) { allTop += obj.offsetTop; } return allTop; }



###绑定滚轮事件,得到滚动的方向值:

oDiv.onmousewheel = mousewheelHandler; if (oDiv.addEventListener) { oDiv.addEventListener('DOMMouseScroll', mousewheelHandler, false); }

function mousewheelHandler(event) { event = event || window.event; if (event.wheelDelta) { var direction = event.wheelDelta > 0 ? 1 : -1; } else if (event.detail) { var direction = event.detail > 0 ? -1 : 1; } oH2.innerText = direction; }


###异常处理

try { 可能会出错的代码 } catch(error) { console.log(error); }


###JSON对象的序列化和反序列化

JSON.stringify(对象); 对象转换为字符串 JSON.parse(json格式的字符串); 字符串转为对象


##20170904

字面量方式创建对象(JSON),对象的属性访问可以是点或者中括号,中括号中可以有变量 对象的属性可以不加引号,可以有空格,有特殊字符,如果有空格或特殊字符, 访问的时候只能用中括号 对象的值可以是任何数据类型 this的六种情况: 直接调用,this是window 事件处理函数,this是触发当前事件的dom对象 定时器中的this是指window 对象.方法名(), this是指前面的这个对象; 原型上面的方法中的this,得看哪个对象调用这个方法,谁调用,this就是谁 函数.call(obj), 函数.apply(obj) 里面的this是指obj 构造函数中的this, 是指new新创建出来的空对象 总而言之:this的值是看如何调用的;闭包中的内容是看定义在哪儿 构造函数(类) 首字母大写,里面可以定义属性和调用方法 构造函数的原型上面定义方法 构造函数中有返回值: 1.返回的是基础数据类型会忽略,依然返回创建出的对象 2.返回的是引用类型,则会将这个引用类型对象返回

根据面向过程的代码改写成面向对象: 把变量变成属性,把函数变成方法 属性和方法前面通常都加上this, 如果方法里面有定时器,事件绑定, 我们一定要在这之前备份this;var self = this; 原型: 所有的函数都有原型 函数.prototype 所有的对象都有原型对象 [].proto 原型上有constructor指向到构造函数 原型链: 根据__proto__不断的往上找,直到到了Object就到终点了,不再继续找 Object是对象 函数也是对象 基础数据类型之所以能够调用方法,是因为在调用方法的时候会临时添加一个 包装对象上去,然后调用包装对象上的方法,当调用结束立即销毁包装对象

基础数据类型其实是对象.primitiveValue 原始值 http://www.w3school.com.cn/js/pro_js_value.asp

JavaScript秘密花园:http://bonsaiden.github.io/JavaScript-Garden/zh/#core.semicolon


##20170905
原型链:
	当访问对象的属性和方法时,先在当前对象身上查找,如果找到就返回
	如果当前对象找不到会找当前对象的原形对象(对象的构造函数的prototype),找到则返回
	如果原型对象上找不到会一直往上找到Object为止
	如果Object.prototype上找不到则会报错,提示 对象.属性 is not defined

##20170906
当你请求一个URL地址,如果返回的是html, 说明这是一个页面
当你请求一个URL地址,如果返回的是json字符串,我们这是一个API
在实际工作中拿到API文档之后,仔细阅读,不懂的问后端同事;调试API,配置好对应的参数,使用正确的请求方式,使用模拟API请求的工具(postman);请求方式,API地址,GET传参,POST传参

经典的AJAX请求代码,这个代码只在学习和面试的时候比较有用,对于你了解底层,实际工作中可能永远接触不到,原因是都被封装起来了

var xhr = new XMLHttpRequest(); //绑定准备状态改变事件 xhr.onreadystatechange = function() { //当内容加载完成 // if (xhr.readyState === 4) { if (xhr.readyState === xhr.DONE) { //把内容放到页面上 oH2.innerHTML = xhr.responseText; } } //请求资源 xhr.open('GET', 'http://h6.duchengjiu.top/shop/api_cat.php?a=1&b=2&c=3'); //发送请求 xhr.send();


Ajax请求实际就是在使用XMLHttpRequest这个对象
xhr.onreadystatechange 当xhr.readyState的值改变的时候会回调这个函数
xhr.responseText 请求后返回的文本内容
xhr.open(请求方式,URL); //如果是GET传参URL?a=1&b=2 如果是POST,这个地址可以只有URL,或者URL?a=1&b=2
xhr.send(POST请求的查询字符串a=1&b=2);
拿到xhr.responseText之后,由于它是JSON字符串,我们使用JSON.parse将其转为对象

ajax一定要把步骤分清了,第一步是能够顺利的把数据请求回来;
请求返回的HTTP状态码:
  200 - 300之间的是成功
  304 表示资源未改变,使用本地缓存
  404 表示资源未找到,是客户端请求了不存在的文件;有可能是后端之前给你的,但是最近删除了,这个时候你应该找后端商量
  500 表示服务器错误,这个你没有办法,直接让后端改;除非你也会写php,java,asp.net,nodejs
第二步是把拿到的数据充分的利用,根据返回内容在界面上更新DOM元素

异步请求
xhr.open(请求方式,API地址,是否为异步); true表示异步,false表示同步

商城API
获取商品分类完成
验证用户是否可用完成
显示热门商品

页面之间传值,可以通过get传参
在需要传递的页面的a链接中写上 目标页面的地址?id=1

web服务器nginx的安装,退出,使用
http://nginx.org/en/download.html 下载一个版本
下载完之后解压,解压好了就相当于安装
解压完了打开目录里面的nginx.exe启动,双击之后看不到任何效果,在浏览器里面输入localhost或者127.0.0.1 打开网站根目录下的index.html
退出方式1:把浏览器打开localhost的页面关闭;右击任务栏,启动任务管理器,进程,输入nginx进行搜索,右击nginx, 结束进程树,结束进程树  这个时候退出了,浏览器里面打开localhost提示无法网站网站,说明退出成功
退出方式2:打开nginx.exe所在目录,右击git bash here;
输入 ./nginx.exe -s quit

IIS是微软提供的一个Web服务器,可以打开控制面板,程序控制,打开和关闭windows功能,找到Internet信息服务,把复选框中的钩去掉,点击确定,这样就关闭了IIS服务器

如果你安装的wamp,能正常使用,把项目放到网站根目录,如果wamp装在C盘,地址是 C:\wamp\www
如果你安装的nginx能正常使用,把项目放到网站根目录,打开nginx所在目录下的html文件夹,这个文件夹就是网站的根目录

如果没有安装nodejs, 到nodejs官网下载windows版本进行安装,然后再继续下面的操作
使用nodejs的http server模块来启动一个web服务器
打开命令行窗口,输入下面这条命令
npm i -g http-server
打开你项目所在文件夹,右击git bash here, 输入下面这条命令
http-server
打开浏览器,在地址栏中输入 127.0.0.1:8080 敲回车访问即可

浏览器缓存资源的时候是根据一个完整的URL地址来缓存
调试ajax,可以直接看网络请求

localStorage.属性 = 值 //设置值
localStorage.属性 //设置值
<div data-id="">
obj.dataset.id //获得

function getQueryString(name) { var search = location.search.substr(1); var reg = new RegExp("(^|&)" + name + "=([^&]*)(&|$)"); var result = search.match(reg); return result === null ? null : decodeURIComponent(result[2]); }

nextElementSibling
ES6对象的简写:
{
  当属性和值一样的时候,只写一个
}

##20170908
Github上面的项目,在设置里面开启git pages,这样可以直接浏览静态网站,如果有ajax,需要请求的API也是https协议或者你自定义一个域名
自己可以购买域名
自己可以购买云主机(阿里云,腾讯云)

box-sizing属性
DOM对象.classList属性,有 add方法和remove方法

##动态商城网站项目
团队合作:
  git操作不熟练
  项目初期目录和文件的规划
  基础知识(DOM操作,兼容性)
  Ajax(GET/POST)

##20170918
jQuery
自制一个jQuery:
  可以批量选择元素,支持CSS选择器,返回一个类数组对象
  代码的书写,我们只使用一个变量叫$, 所有的方法都放到$.fn这个属性上
  让$()返回的对象($.fn.init构造出来的)能够调用$.fn上的方法;$.fn.init.prototype = $.fn
  实现链式调用,在方法(不能是init方法)里面最后返回this

jQuery版本:
1.x兼容IE6、7、8
2.X不兼容IE6、7、8

$(选择器) 可以选中元素,并返回jQuery($.fn.init的对象)
方法:
  html(html)/html() //设置或返回innerHTML内容
  css(属性,值); css({属性:值,属性:值});/css(属性); //设置或者返回css的计算后属性
  animate(目标状态的JSON,时长,回调函数);
  $().事件名(事件处理函数); //事件处理函数当中的 $(this) 表示当前操作的元素的jQuery对象
  stop(true, true); //清空当前动画队列,并将当前动画立即执行结束
  eq(index); 返回对应索引的jQuery对象
  addClass(类名); //添加类名 元素.classList.addClass(类名); 也可以使用className的字符串拼凑方法
  removeClass(类名); //移除类名
  siblings(); 返回所有的兄弟元素
  clone(); 克隆元素
  父元素.append(子元素);//追加到后面
  父元素.prepend(子元素);//在父元素的内部头部插入
  子元素.appendTo(父元素); //添加到父元素内部
  子元素.prependTo(父元素);
  新元素.insertBefore(旧元素);
  新元素.insertAfter(旧元素);
  旧元素.before(新元素);
  旧元素.after(新元素);
  旧元素.wrap(新元素);//用新元素包裹旧元素
  旧元素.wrapAll(新元素);//把所有的旧元素作为一组,在外面包裹新元素
  元素.empty(); //将元素内部的innerHTML清空
  元素.remove(); //移除元素
  元素.attr() ;//设置或获取自定义属性
  元素.prop(); //设置或获取元素固有的属性
  jquery对象转DOM对象;$('p')[1];
  DOM对象转jQuery对象:$(DOM对象或DOM字符串) $(window) $(document) $(this) $("<div></div>").appendTo()
  width()//width
  innerWidth()//width+padding
  outerWidth()//width+padding+border
  outerWidth(true)//width+padding+border+margin
  offset()//返回元素的净位置  offset().top 返回元素到顶部的净位置
  mousewheel();//滚轮事件,是一个官方的插件,默认的jquery里面不包含
  $(window).scrollTop(); /scrollTop(0); //获取scrollTop的值,设置scrollTop的值
  $('html,body').animate({"scrollTop": 0}, 1000); //滚动添加动画
  $(window).scroll();//滚动事件
  show();//显示
  hide();//隐藏
  toggle(); //显示/隐藏
  slideDown(); //下拉显示
  slideUp(); //上拉隐藏
  slideToggle(); //显示/隐藏
  fadeIn(); //淡入
  fadeOut(); //淡出
  fadeToggle();//淡入/淡出
  fadeTo(500, 0.3); //切换到对应的透明度; 如果说切换到对应的透明度之后再fadeIn的时候,就只能到达这种状态
  delay(600);//延迟
  stop(); stop(false,false);//停止并结下一个动画
  stop(true);//停止并清空队列
  stop(true, true);//瞬间完成当前的动画并清空队列
  stop(false, true); //瞬间完成当前的动画并继续下一个
  finish();//瞬间完成队列中所有的动画
  is(选择器);//判断jquery对象是否符合当前的选择器
  index(); //返回元素在真实的亲兄弟之间的序号
  children();//子元素,不包含孙子元素
  find();//找后代元素,包括儿子孙子等等
  parent();//父元素
  parents();//祖先元素
  each(function(index, item){
    console.log(index, item);
    });//遍历数组或类数组元素
  get(1); //相当于[1], 得到的是DOM元素
  $.get(url, {}, function(json){
    }); //返回的数据如果是json字符串, 自动帮我们转换成了对象,我们可以直接使用
  $.post(url, {}, function(json){
    });//返回的数据是json字符串会自动转换
  $.ajax({
    url: 地址,
    type: 请求方式get/post,
    dataType: 指定返回的数据类型,
    data: 请求时的数据对象,
    success: 成功时的回调
    })
  表单元素.serialize(); //获取表单当中的所有包含name属性的输入元素的查询字符串; k=v&k1=v1
  表单元素.serializeArray(); //获取表单当中所有包含name属性的输入元素的数组
  想要获取对应的对象:
  function formArrayToObject(arr) {
    var obj = {};
      for (var i = 0; i < arr.length; i++) {
        obj[arr[i].name] = arr[i].value;
      }
      return obj;
  }
  var formArray = $("form").serializeArray();
  var formObject = formArrayToObject(formArray);

筛选器:
  $(元素)
  $(元素:first)
  $(元素:last)
  $(元素:eq(3))
  $(元素:lt(3))
  $(元素:gt(3))
  $(元素:odd)
  $(元素:even)
  :animated
  :visible
  :checked


对同一个元素设置多个animate, 会把动画添加到动画队列当中
jQuery的插件无非就是丰富一下jQuery对象的方法(给jquery对象的原型上面加方法);$.fn.draggable = function(){}; 后面使用jquery选中的元素就可以此方法($('p').draggable());

##20170920
浏览器端跨域
同源策略(浏览器)
浏览器同一时间向同一个域名只能发送8个请求;所以使用多个域名的方式提升性能(为了服务器的安全,一次只能向同一个域名发送8个请求)
怎么区分数组和类数组(看原型)
URL:协议://IP地址或域名:端口/路径/文件?查询字符串#hash
http://www.163.com/a/b.html
http默认的是80端口
https://www.163.com/a/b.html
如果你网站的协议是使用的https, 那你请求的所有资源都需要是https

服务器端是可以跨域;可以用后端语言做爬虫(爬虫把一个页面就当成一个API)
jsonp:
jsonp('http://h6.duchengjiu.top/shop/api_cat.php?format=jsonp&callback=fun', 'fun', function(data){
  console.log(data);
});
//编写一个实用的轮子
function jsonp(URL, callbackname, callback) {
  //在window对象上强行增加一个属性,这个属性就是全局变量,是一个函数的名字
  window[callbackname] = callback;
  // 宿主对象 window
  //添加元素
  var script = document.createElement('script');
  document.body.appendChild(script);
  script.src = URL;
  document.body.removeChild(script);
}
jquery中的jsonp:
$.ajax({
  url: "http://h6.duchengjiu.top/shop/api_cat.php?format=jsonp&callback=fun",
  dataType: 'jsonp',
  jsonpCallback: "fun",
  success: function(data) {
    console.log(data);
  }
});

模板引擎:
  template标签用来存放模板的内容,不会显示在页面上

jquery插件开发:
  一种是往jquery的原型上面加方法: $.fn上面加方法, 比如 $.fn.draggable
  一种是往jquery构造函数本身加方法:$.加方法,比如ajax这种, $.ajax
  $.fn.draggable = function(){
    for (var i = 0; i < this.length; i++) {
      this[i].onmousedown = function(event){
        event = event || window.event;
        var deltaX = event.clientX - this.offsetLeft;
        var deltaY = event.clientY - this.offsetTop;
        this.style.position = 'absolute';
        document.onmousemove = event => {
          event = event || window.event;
          this.style.top = event.clientY - deltaY + 'px';
          this.style.left = event.clientX - deltaX + 'px';
        }
      }
      document.onmouseup = function(event) {
        document.onmousemove = null;
      }
    }
  }
htmlshiv.js兼容低版本浏览器

##20170926
H5C3
2D:
transition:
transform: rotate() scale() skew();
3D:
perspective: 500px;
transform: rotateX() rotateY() rotateZ() rotate3d() translateX() translateY() translateZ();
transform-origin: Y轴方向的轴 X轴方向的轴;
transform-style: preserve-3d; //保持3D
//定义关键帧动画
@-webkit-keyframes 动画名称{
  0% {
    transform: rotateX(300deg)
  }
  to {
    transform: translateX(300px)
  }
}
animation: 动画名称 持续时长 缓冲函数名 延迟时间 循环次数 是否折返 是否保持最终状态;
animation: move 1s ease 0s infinite alternate forwards;
animtion-play-state: paused;


prototype.js

箭头函数
明天说内网穿透,让你的网站能够被其他人看到

选择第三方库:
有能力的话自己摘取,不要全部引用;有些库可以允许你按模块下载
animate.css的动画分类:
引起注意的特效
弹跳入场
弹跳出场
淡入
淡出
翻转
光速入场出场
旋转入场
旋转出场
滑动入场
滑动出场
缩放入场
缩放出场
特殊特效


//让元素垂直居中的一种方式
top: 50%
transform: translateY(50%); //这个值相对于高

left: 50%;
transform: translateX(50%);//这个值相对于宽

图片的外层和a链接的外层,通常都会用div包裹,因为这个位置的元素内容可能会更新,一更新内容可能会导致页面布局就乱了,所以通常用div去布局,不要让具体的一个元素去布局
布局元素:header div nav ul li     
具体的元素:a img input

图片加超链接的情况,通常用一个a链接,然后用伪元素去定位图片,用line-height去定位文字
h1, h2, h3标签的用途:SEO优化的功能 SEO(搜索引擎优化,说白了就是你网站在百度上的排名) SEM 竞价排名(点击一次多少钱,便宜的几毛钱,稍微贵点几块钱)
h3重要的元素里面一定要设置文字,但是图片更好看,所以把文字text-indent: -9999em;
另外一个原因,为什么一定要加文字,我们说有视障者,他们看不到图片
background-size是真实雪碧图的大小/2
background-position: 真实雪碧图上小icon的位置/2
width,height都是雪碧图要显示的小icon的大小/2
如果background-size设置的是真实雪碧图的一半,那position和width,height都要再除以2

letter-spacing: 8px;
text-align: center;
/*往回拉8px*/
/*text-indent: 8px; */
/*或者padding*/
/*padding-left: 8px;*/

20171016
canvas用来制作图表,游戏,广告banner, 常用的会用的话5个属性,15个方法就行

<canvas width="500" height="500">不支持的浏览器会显示</canvas>
var canvas = document.querySelector('canvas');
var ctx = canvas.getContext('2d');
//绘制元素主要是有一堆的方法去设置笔的样式,以及一堆的方法去绘制具体的图形或文字或图片
ctx.strokeStyle = "red";//笔触的颜色
ctx.lineWidth = 4;//笔记的线宽
ctx.fillStyle = "blue";//设置填充色
ctx.font = "40px 微软雅黑";
ctx.globalAlpha = 0.5;//全局的透明度

ctx.strokeRect(x, y, width, height);//绘制的矩形框
ctx.fillRect(x, y, width, height);//绘制实心的矩形
ctx.clearRect(x, y, width, height);//把对应的矩形区域清空

//路径
ctx.beginPath();
ctx.moveTo(x, y);//移动笔触的起点
ctx.lineTo(x, y);//从起点画线一直画到当前的x,y
ctx.closePath();//闭合的时候会自动把当前的点和开始的点连接起来
ctx.stroke();//绘制框
ctx.fill();//填充
ctx.fillText("内容", x, y);
var img = new Image();
img.src = "./images/x.jpg";
img.onload = function(){
  ctx.drawImage(img, x, y);
  ctx.drawImage(img, sx, sy, swidth, sheight, dx, dy, dwidth, dheight);
}
//动画
var img = new Image();
img.src = "./images/1225.jpg";
img.onload = function(){
  var x = 100;
  var y = 100;
  setInterval(function(){
    ctx.clearRect(0, 0, 500, 500);
    x+=3;
    y+=4;
    ctx.drawImage(img, 235, 60, 90, 100, x, y, 90, 100);
  }, 30);
}
//事件
canvas不是DOM元素,不能够像给DOM元素添加事件一样方便,所以游戏引擎里面的显示对象,就是为了解决这些复杂的问题
js, jquery
canvas, phaser, jcanvas
canvas.addEventListener('click', function(event){
  event = event || window.event;
  //通过判断点击的位置在目标区域内,就当成是点击了这个显示对象
  if (event.offsetX > 100 && event.offsetX < 190 && event.offsetY > 100 && event.offsetY < 200) {
    console.log('clicked');
  }
});
//save(), restore();
save();保留当前的上下文,相当于是保留了ctx对象的所有的属性的值不变;
然后你就可以做一些独特的事情,不影响全局,当你完成之后可以调用restore()恢复之前的上下文
像旋转,缩放,位移,透明度等等,如果要针对某个显示对象则需要先调用save();完事之后调用restore();

//旋转

ctx.translate(x+self.width/2, y+self.height/2);//旋转的时候把参考点改变一下
ctx.rotate(20);//旋转的角度
ctx.drawImage(img, sx, sy, swidth, sheight, -dwidth/2, -dheight/2, dwidth, dheight);//对应的位置也要相应的发生变化,-宽度的一半

20171017
和canvas类似的可以绘图的是svg, 不过这个是描述性的, 不是通过js的api去绘制
遇到SVG图片,然后颜色还不一样,这个时候可以统一的上传到iconfont网站,然后把颜色去掉再下载

#20171017
Node的内容非常非常重要,因为现在前端开发都讲究工程化,gulp, webpack, express, vue-cli, vue
nodejs的三大特征:单线程,非阻塞I/O,事件机制
I/O 对于计算机来说可以在内存当中写数据或数据,可以在硬盘当中写数据读数据,也可以从网络当中去读数据或写数据
nodejs安装
到官网下载程序安装
会自动将程序的路径添加到环境变量的PATH里面,在执行程序的时候会把这个PATH变量里面所有的路径去找,找到了则执行,找不到则报错
验证安装
node -v
cmd和git bash的区别:
cmd: c: d:
git bash: cd /c     cd /d
//执行一个nodejs的文件
node 要执行的js文件.js
//如果运行的这个文件是启动一个web server, 需要手动的打开浏览器,输入地址去查看
协议://域名(IP):端口/路径/名件名?a=1&b=1#c=3&d=4
ftp:
http:
https:
ws:
//怕你等着急了,可以查看到正在访问的请求,而不至于等半天没反应
npm config set loglevel http
//解决速度慢的问题; 后面如果安装某些包比较费时,你可以使用已经安装好的同学的包
npm config set registry "https://registry.npm.taobao.org"
//安装一个第三方的模块, 第三方模块特别多,gulp,webpack, http-server, json-server, localtunnel
npm i underscore
//进程管理,nodejs程序炸了就挂了,所以需要一个能够自动重启的软件,类似的软件还有forever, supervisor
//i表示install -g表示--global
npm i -g pm2
//查看帮助
pm2 --help
//查看帮助,-h表示--help
pm2 -h
//启动05-http-server.js这个程序,通过pm2去启动; 如果开启之后不去停止会报端口号被占用
pm2 start 05-http-server.js
//关闭所有的pm2进程
pm2 kill
//nodejs中的模块导出
module.exports = {
  需要导出的内容
}
//nodejs中的模块导入
var m = require('./a1.js');
var m = require('./m1/');//相当于引入了m1目录下的index.js这个模块
var m = require('./m1');//会先在当前目录查找一下是否有m1.js这个文件,如果没有则看有没有m1这个目录,如果有这个目录去查看有没有index.js
var m = require('http');
var m = require('url');
var m = require('fs');
var m = require('underscore');//第三方模块
var m = require('gulp');//第三方模块
var m = require('webpack');//第三方模块
m.属性
m.方法()
//使用nodejs创建一下简单的webserver
let http = require('http');
http.createServer((req, res) => {
  req.url;//获取请求的地址
  //每次请求的时候都会执行的内容
  res.write('<h1>h1</h1>');
  res.writeHead(200, {"content-type":"text/html;charset=utf-8"});
  res.end("可以加返回的内容,相当于write并结束");//表示结束,如果没有这个则一直在请求
}).listen(3000, '127.0.0.1');
//fs模块,文件系统模块,目录的增删改查,文件的增删改查
//通用的规定,nodejs里面的回调函数中的第一个参数通常都是error对象,第二个才是数据
fs.mkdir();//创建目录
fs.stat('文件', (err, data) => {
    console.log(data.isDirectory());//检测是否是一个目录
});//检测状态
fs.readFile('文件', (error, data) => {
});
fs.readdir('目录', (error, files) => {
  //files就是指一个目录下面的所有的文件(包括目录)
})
fs.rename(oldpath, newpath, (err) => {

})

//路由做的事情就是根据不同的请求地址或者不同的请求方式,或者不同的请求参数去做不同的事情
if (req.url === 'a') {
  //做某件事
} else if (req.url === 'b') {
  //做某件事
}
//express
app.get('/', function(){
})
//url模块
var u = url.parse(req.url);//能够将地址转换成对象
var u = url.parse(req.url, true);//不仅能够将地址转换成对象,而且将查询字符串也能够转换成对象
//想要获得某个GET请求的参数为name的值
console.log(u.query.name);
//路由这一块可以是精确匹配;还有模糊匹配
//在学Vue的时候也会有路由配置,到时候就会有一级路由,二级路由,动态路由
//前端路由是指页面不跳转的情况下,所以通常是#/a/b/ 也可以变成/a 背后的原因是通过h5的history对象去管理
//后端路由通常是页面会发生跳转,所以是 /a /b  /a?id=1
let pathname = url.parse(req.url).pathname;

//path模块
let extname = path.extname(pathname);

//sd模块
npm i -S silly-datetime
let sd = require('silly-datetime');
sd.format(new Date(), 'YYYYMMDDHHmmss');

//路由的话可以单独写成一个文件,然后导出给主文件使用
在需要使用的地方导入
let router = require('./router.js');
router.showIndex(req, res);

//req
req.url 请求的地址
req.method 请求的方式

//querystring模块
npm i -S querystring
let querystring = require('querystring');
//分块post请求提交,每提交一部分数据
req.addListener('data', (chunk)=>{
});
//post提交完成
req.addListener('end', () => {
  let dataObj = querystring.parse(datastring);
});

//formidable 专门处理post请求的模块
npm i -S formidable;
let formidable = require('formidable');
//创建一个新的来源表单
let form = new formidable.IncomingForm();
form.uploadDir = './uploads';
form.keepExtensions = true;
form.parse(req, (err, fileds, files) => {
  if (err) {
    throw err;
  }
  console.log(fileds, files);
  console.log(util.inspect({fileds, files}));//ES6的简写相当于,{fileds: fileds, files: files}
  //时间,使用silly-datetime
  let time = sd.format(new Date(), 'YYYYMMDDHHmmss');
  let rand = Number.parseInt(Math.random() * 89999 + 10000);
  let extname = path.extname(files.pic.name);
  let oldpath = __dirname + '/' + files.pic.path;
  //新的路径
  var newpath = __dirname + '/uploads/' + time + rand + extname;
  //改名
  fs.rename(oldpath, newpath, (err) => {
    if (err) {
      throw err;
    }
    res.writeHead(200, {'content-type':'text/html;charset=utf-8'});
    res.end('成功');
  });
});
}

//util
util.inspect({});//可以把对象转换成字符串,方便调试

__dirname 表示当前文件所在的目录绝对地址

//ejs模块
npm i -S ejs
let ejs = require('ejs');
fs.readFile("./views/index.ejs",function(err,data){
    //绑定模板
    var template = data.toString();
    var dictionary = {
        a:6,
        news : [
            {"title":"陈伟我爱你","count":10},
            {"title":"哈哈哈哈","count":20},
            {"title":"逗你玩儿的","count":30}
        ]
    };
    var html = ejs.render(template,dictionary);

    //显示
    res.writeHead(200,{"Content-Type":"text/html;charset=UTF8"});
    res.end(html);
});

//生成package.json
npm init -y
//根据package.json下载对应的库通过
npm i
//安装的时候如果是线上需要用的模块
npm i -S underscore
//安装的时候如果是一些工具模块
npm i -D gulp

package.json说明:
main选项
scripts选项  npm run dev
dependencies
devDependencies

.gitignore通常需要忽略node_modules目录

Express中文官方网站上面的所有的资源都跑一遍,能够学到的知识挺多
express自定义端口号:
在 package.jsonr的scripts中修改:
"start": "set PORT=80 && node ./bin/www"

写API就是返回json数据而不是返回页面
res.json({'data':"a"})

路由: http://www.expressjs.com.cn/guide/routing.html

res.download()	提示下载文件。
res.end()	终结响应处理流程。
res.json()	发送一个 JSON 格式的响应。
res.jsonp()	发送一个支持 JSONP 的 JSON 格式的响应。
res.redirect()	重定向请求。
res.render()	渲染视图模板。
res.send()	发送各种类型的响应。
res.sendFile	以八位字节流的形式发送文件。
res.sendStatus()

nodejs进程管理:
pm2, supervisor, forever, strongloop
pm2 start ./bin/www

//ubuntu系统远程连接失败
在安全组配置一下,开启22 443 80端口,授权对象为 0.0.0.0/0
//ubuntu系统中安装nodejs和mongodb
//添加一个用户,输入两次密码,其他的回车即可
adduser maxwelldu
//把当前用户添加到sudo组
adduser maxwelldu sudo
//切换到这个用户
su - maxwelldu
//更新包
sudo apt-get update
//安装两个工具
sudo apt-get install build-essential libssl-dev
//安装nvm
wget -qO- https://raw.githubusercontent.com/creationix/nvm/v0.25.3/install.sh | bash
//使nvm生效
source ~/.profile
nvm
nvm ls-remote
nvm install 8.7.0
nvm list
nvm use 8.7.0
node -v

//编辑一下本地host,vim当中按i输入内容;保存退出按ESC键,然后按两个大Z或者按:wq回车
sudo vim /etc/hosts
//确保里面的内容只有一个127.0.0.1 后面的值为localhost dev
//下面的内容都注释起来
127.0.0.1       localhost dev

# The following lines are desirable for IPv6 capable hosts
#::1     localhost ip6-localhost ip6-loopback
#ff02::1 ip6-allnodes
#ff02::2 ip6-allrouters

//下面安装mongodb
//ubuntu上面安装mongodb的文档 http://docs.mongodb.org/manual/tutorial/install-mongodb-on-ubuntu

Ubuntu系统上面的MongoDB服务端和客户端的安装分为4步:
1.导入包管理系统需要用到的公钥:
sudo apt-key adv --keyserver hkp://keyserver.ubuntu.com:80 --recv 7F0CEB10
2.为MongoDB创建list文件:这个根据ubuntu系统的不同而不同,查看上面的文档
echo "deb http://repo.mongodb.org/apt/ubuntu "$(lsb_release -sc)"/mongodb-org/3.0 multiverse" | sudo tee /etc/apt/sources.list.d/mongodb-org-3.0.list
3.重载本地包数据库
sudo apt-get update
4.安装最新版的MongoDB
sudo apt-get install -y mongodb-org
5.启动
sudo service mongod start
6.测试
sudo mongo

ORM Object Relation Model 操作对象,让对象帮我们去操作数据库

//配置SSH免密钥登录
//git推送后自动更新网站

Express(RMVC框架)
M Model表示数据,就是负责数据的管理,对数据的CRUD(Create, Read, Update, Delete) 增删改查; 有可能是对数据库,也有可能对文件和目录
V view视图,通常是html模板
C Controller控制器,中间的协调者,把数据和模板都得到返回给用户;或者把数据得到返回json
实际网站请求就是RCMV, 返回的v是html
API请求就是RCM 返回的是json或者xml

Mongoose的使用
1.引入包
2.定义Schema,导出Model
3.对Model的操作,可以增删改查

function Person(name){
  this.name = name;
}
Person.prototype.sayHello = function(){
  console.log('hi');
}
var p = new Person('p1');
p.name;//实例属性
p.sayHello();//实例方法

静态属性,实例属性
静态方法,实例方法
Person.city = '北京';//这个属性在构造函数身上,使用的时候Person.city; 这个叫静态属性
Person.sayHi = function() {
  console.log('hi');
}//这个方法在构造函数身上,使用的时候使用Person.sayHi();这个叫静态方法

##20171024
基于Express+ejs+mongoose开发网站
mkdir node-ask
cd node-ask
npm i -g generator-express
express -e .
npm i
npm start
http://localhost:3000
写路由,写页面
开启mongo的服务器
引入mongoose模块
npm i -S mongoose
vim ./config/db.js
vim ./model/User.js
vim ./vendor/md5.js
注册功能:接收用户提交的用户名和密码,对密码加密,查询用户,渲染模板
vim ./views/user/register.ejs
需要开启调试工具(或者其他工具有对应的其他方法):
node-inspector &
node --debug ./bin/www
登录功能:安装express-session; 在app.js中配置

使用Teamview做团队任务管理
https://www.teambition.com/
石墨进行实时文档管理
https://shimo.im/
QQ其实就是Socket


#20171030
NodeJS复习
assert.equal();
console.log();
console.error();
crypto模块用来加密:md5, sha1
fs.readFile();
fs.readDir();
__dirname
__filename
exports
module
require()
http.createServer().listen();
path.dirname();
path.extname();
path.join();
path.normalize();
querystring.parse();
url.parse();
util.inspect();
模块:
  从 Y 路径的模块 require(X)
  1. 如果 X 是一个核心模块,
     a. 返回核心模块
     b. 结束
  2. 如果 X 是以 '/' 开头
     a. 设 Y 为文件系统根目录
  3. 如果 X 是以 './' 或 '/' 或 '../' 开头
     a. 加载文件(Y + X)
     b. 加载目录(Y + X)
  4. 加载Node模块(X, dirname(Y))
  5. 抛出 "未找到"

  加载文件(X)
  1. 如果 X 是一个文件,加载 X 作为 JavaScript 文本。结束
  2. 如果 X.js 是一个文件,加载 X.js 作为 JavaScript 文本。结束
  3. 如果 X.json 是一个文件,解析 X.json 成一个 JavaScript 对象。结束
  4. 如果 X.node 是一个文件,加载 X.node 作为二进制插件。结束

  加载索引(X)
  1. 如果 X/index.js 是一个文件,加载 X/index.js 作为 JavaScript 文本。结束
  3. 如果 X/index.json  是一个文件,解析 X/index.json 成一个 JavaScript 对象。结束
  4. 如果 X/index.node 是一个文件,加载 X/index.node 作为二进制插件。结束

  加载目录(X)
  1. 如果 X/package.json 是一个文件,
     a. 解析 X/package.json,查找 "main" 字段
     b. let M = X + (json main 字段)
     c. 加载文件(M)
     d. 加载索引(M)
  2. 加载索引(X)

#20171031
var Person = function() { }
简单工厂:用于创建单一对象的实例
function PersonFactory() {
  return new Person();
}
var p = PersonFactory();
批量生产:一个方法,能够实现批量创建
function PersonFactory(num) {
  if (num) {
    var result = [];
    for (var i = 0; i < num; i++) {
      result.push(arguments.callee());
    }
    return result;
  } else {
    return new Person();
  }
}
寄生增强:在简单工厂里面生产对象后,添加属性和方法
function PersonFactory() {
  //生产
  var p = new Person();
  //增强
  p.walk = function(){}
  //工厂
  return p;
}
安全工厂:防止有人使用new关键字去调用简单工厂方法
function PersonFactory() {
  if (this instanceof arguments.callee) {
    return arguments.callee();
  } else {
    return new Person();
  }
}
var p = new PersonFactory();
var p1 = PersonFactory();
工厂方法:创建多个不同类型的对象
function Cat() {
  this.name = 'hello kitty';
  this.type = 'cat';
}
Cat.prototype.init = function(){
  console.log(this);
}
function Dog() {
  this.name = 'wood';
  this.type = 'dog';
}
Dog.prototype.init = function(){
  console.log(this);
}
function AnimalFactory(type) {
  var animal;
  switch(type) {
    case 'Cat':
      animal = new Cat();
      break;
    case 'Dog':
      animal = new Dog();
      break;
  }
  if (animal) {
    animal.init && animal.init();
  }
}
原型模式:把类中公共的属性和方法提取
function Animal() {
  this.name = 'hello kitty';
}
Animal.prototype.init = function(){
  console.log(this);
}
function Cat(name) {
  Animal.call(this, name);
  this.type = 'cat';
}
Cat.prototype = new Animal();

function Dog(name) {
  Animal.call(this, name);
  this.type = 'dog';
}
Dog.prototype = new Animal();
function AnimalFactory(type) {
  var animal;
  switch(type) {
    case 'Cat':
      animal = new Cat('hello kitty');
      break;
    case 'Dog':
      animal = new Dog('wood');
      break;
  }
  if (animal) {
    animal.init && animal.init();
  }
}
惰性单例模式:希望创建出来的对象只有一个;并且希望在用到的时候才调用
function Animal() {
  this.name = 'animal';
}
var SingleAnimal = (function(){
  var _instance = null;
  return function () {
    if (!_instance) {
      _instance = new Animal();
    }
    return _instance;
  }
})();
var a1 = SingleAnimal();
var a2 = SingleAnimal();
console.log(a1 === a2);
闭包类:为了能够封装私有的属性和方法
var Animal = (function () {
        function Animal() {
            //公共属性
            this.name = 'animal';
            var sex = 0;//私有属性
            //私有属性希望对外可以暴露,但是可以限制
            this.getSex = function() { // getter
                return sex;
            }
            this.setSex = function(newsex) { // setter
                sex = newsex;
            }  
        }
        //公共方法
        Animal.prototype.say = function() {
            console.log('hi' + this.name);
        }
        return Animal;
    })();
    var a = new Animal();
    console.log(a.name);
    a.say();
    a.name = 'cat';
    console.log(a.name);
    a.say();
    console.log(a.sex);
    console.log(a.getSex());
    a.setSex(1);
    console.log(a.getSex());
适配器:
  数据适配
  参数适配

#20171103
必会的ES6知识点:
环境搭建:babel node npm webpack
let,const
rest: ...rest
解构赋值:[] {} [{[{}]}]
字符串:includes, startsWidth, endsWidth, trim, `${name}`
数字:Number.isNaN, Number.parseInt, Number.parseFloat
数组:Array.from(类数组) 数组.forEach
函数:参数默认值,箭头函数
对象:属性的缩写,方法简写
Symbol: 知道是一种类型, Symbol()能够产生一个独一无二的值,Symbol.iterator用来设置默认的迭代器
Set: 用来存放无重复的数据
类:class, extends, constructor, get, set, static, super
Promise: new Promise(function(resolve,reject){});   promise.then(function(){}).catch(function(){})
Promise.all, Promise.race
迭代器Iterator: next();   for(let k of arr) {}
生成器genertor: function * fn(){yield 'a'; yield 'b';yield 'c'}
ES2017: async await 实际上是generator和yield的语法糖
异步的解决方案:回调函数 --> promise --> generator --> async
模块化:export, export default, import './a'; import a from './a'; import * as a from './a'; import {hello, A} from './a';

#尝试学习Koa.js, Egg.js(选学), ThinkJS(选学), 小程序, WebPack, Git的分支等

#20171106
包管理:bower, npm, yarn
操作系统:chocolatey brew centos:yum ubuntu:apt-get
语言:php:pear,composer java:maven ruby:gem

yarn, Browserify, Grunt, eslint, lint, async, commonjs, amd, requirejs, haml, coffee script, typescript    

##5点后的练习计划
- 20170828 练习批量绑定事件和对应模型
- 20170829 练习函数截流滚动或者延迟搜索
- 20170830 添加事件的轮子
- 20170831 写事件委托删除ul中的li子元素
- 20170901 写拖拽模型
- 20170902 getAllTop方法

所有口头描述必须能够用一句话描述出来;要用类比的方式(生活中的比喻):
20170921 口头描述对同步异步的理解   https://www.zhihu.com/question/19732473
口头描述一下jquery的jsonp底层实现
口头描述一下对模板引擎的理解 一个静态的字符串,数据;把数据替换字符串中特定标记位置的内容;
20170925 对ajax的理解:至少体现三点:异步,HTTP请求(请求方式,响应状态码;可以继续挖很多),API
20170926 口头描述你对jquery的理解
20170927 口头描述你对underscore的理解
20170928 口头描述一下如何使用jsonp跨域 因为src属性可以跨域,所以利用这个特性;动态的创建script标签,并设置src属性,添加到页面上,这个script的内容就会立即执行,在当前页面上定义一个函数,这个外部的js文件调用这个函数,并传递json数据作为参数;jsonp
一句话:外部的js文件调用你定义的函数并传递json数据
20170929 优雅降级和渐进增强
20170930 事件代理、事件委托的优点
20171009 了解BFC吗?你会定制Bootstrap样式吗?
20171009 动态绑定事件的缺点
20171010 伪类和伪元素的区别
20171011 localStorage和sessionStorage的区别
20171012 描述GET和POST请求的区别
20171013 口头描述点语法和括号的区别
20171014 口头描述浅拷贝和深拷贝的区别

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •