各类高度 | 包含选项 |
---|---|
height | content |
clientHeight | content+padding |
offsetHeight | content+padding+border+scroll |
scrollHeight | (子元素高度 <= content)? clientHeight:(子元素高度 + padding) |
注意:当我们按照如下设置:
此时height的计算结果为183px,因为横向滚动条的高度为17px,需要减去这17px才是元素的实际高度值。
各类高度 | 包含选项 |
---|---|
height | content |
clientHeight | content+padding |
offsetHeight | content+padding+border+scroll |
scrollHeight | (子元素高度 <= content)? clientHeight:(子元素高度 + padding) |
注意:当我们按照如下设置:
此时height的计算结果为183px,因为横向滚动条的高度为17px,需要减去这17px才是元素的实际高度值。
本系统所用技术包括:jade模板(加强的html),bootstrap(css样式集),express(Web应用框架),js,nodejs,mysql,token验证等。
GitHub地址:https://github.com/qingywen/DEMO/tree/master/Greeni
基本功能如下:
先写前端界面,包括index.html(公共页面),login.html(登录页面),signup.html(注册页面),my.html(个人中心),这里用到了bootstrap的示例页面signin,carousel和dashboard的页面结构和样式。
也许会有人跟我一样刚开始接触bootstrap并不知从何用起,以下做个简短说明:bootstrap是一个css样式集,用的好可以为你的项目锦上添花,用不好反倒累赘,因此还需好好琢磨。了解bootstrap的菜鸟教程可以浏览菜鸟教程。实际上,bootstrap3的中文官网已经讲解的非常详尽。不过仍建议先阅读菜鸟教程进行热身。
页面js主要功能为表单提交,提交前先进行简单的验证,再序列化表单,接着用ajax提交到服务器,最后关闭表单的默认提交功能。
前端界面搭建好后,我们来新建一个数据库,数据库表中只有一个users表,结构如下:
Field | Type | Null | Key | Default | Extra |
---|---|---|---|---|---|
P_Id | int(11) | No | PRI | NULL | auto_increment |
varchar(255) | NO | UNI | NULL | ||
password | varchar(255) | NO | NULL |
现在表数据如下:
P_Id | password | |
---|---|---|
1 | 1195259521@qq.com | 123 |
9 | qingywen@gmail.com | 123 |
12 | wenwu@gmai.com | 123 |
14 | 123@qq.com | 123 |
数据库导出文件为greeni.sql,在本地数据库中将sql文件导入新建数据库greeni即可。
前端、数据库搭建好后,我们即可开始整个应用的系统搭建,通过后台逻辑将前端和数据库连接起来。
这里在一个新文件夹中用express
进行项目初始化,当然前提是本地用npm安装了express。接着在package.json中加入db、ejs、jsonwebtoken三个模块,然后用cnpm install
进行安装。
这里我们需要将app.js文件中默认的渲染引擎从jade改为ejs。
修改routes文件夹下index.js、my.js的路由定向和事件句柄,此时要用到数据库,因此新建db文件夹,在db目录下新建DBConfig.js和SQL.js,分别用作数据库的连接配置文件和SQL语句模块。
在写登录验证的逻辑时,我们根据用户邮箱用jsonwebtoken随机生成一个令牌,并发送用户,用户在cookie中保存此令牌,在下次请求私有资源时则不必明文发送密码,而是在发送请求时随着cookie自动将令牌发送给服务器,服务器收到令牌验证成功后则返回用户所请求的资源,否则令牌有可能被恶意更改,则拒绝请求。
此时系统搭建完毕,我么可以用npm start
来启动项目,注意bin文件夹写的端口号为8000,因此访问地址为:127.0.0.1:8000。
最后我们想做一个小优化,如果每个用户登录到个人中心的页面都一样的话,这个个人中心恐怕是个假个人中心,因此我们需要对不同的用户请求返回一样的页面结构但是不同的用户信息。为求简易,这里我们只对每个用户返回各自的email,并添加到页面上。
因为页面首先需要在服务器上渲染才能返回给客户端,最经济的思路当然是在服务端渲染出不同的页面再返回给客户端。而html并没有变量的功能,因此我们使用jade模板(现更名为pug,但jade模块仍有效)来代替html。jade是一个非常高效的模板引擎,提供了变量、for循环等功能。有一个非常好的jade语法学习网站安利给大家。这里我们需要将之前的html转为jade,手动改编太麻烦,用这个html2jade的网站来转化吧。
得到jade格式的前端文件,我们修改app.js的模板引擎设置,将ejs引擎改回默认的jade引擎:
在routes下的my.js中,返回个人中心页面同时,返回用户的email:
修改views文件夹下my.jade文件中的标题,用来接收服务器传送来的email变量:
此后大功告成,每个用户登陆后访问个人中心的页面,其页面标题都是自己用来注册的email,因此此个人中心成立。
serialize()
,阻止表单默认提交方式preventDefault()
,以及设置cookie的CookieUtil.set()
均来自《JS高级程序设计》。jwt.sign() jwt.verify()
,建议细看jsonwebtoken包下的README.md,讲解很详细。中文译名为令牌,包含三个部分:header、payload、signature。
|
|
此为令牌的头部,可以在其中设置签名算法和token类型,如下所示:
该部分包含我们需要设置的信息:
signature则是将header和payload结合并用指定算法进行签名(加密)的结果。
|
|
验证令牌有效性是整个机制的关键:我们的方法是根据header里提供的信息,对payload再次进行签名,并将结果与signature进行比对,如果一致,则令牌有效;若不一致,则说明是经过恶意改动的无效令牌。
|
|
今天使用mysql -uroot -p
在终端连接数据库时,一直报错ERROR 1045 (28000): Access denied for user 'root'@'localhost' (using password: YES) The current server installed: "C:\Program Files\MySQL\MySQL Server 5.6\mysqld
,通过谷歌和百度搜寻了很多方法,大多都是关于如何重置root用户的密码,但由于版本不同,且答案冗杂,到最后也没能解决。因想起大一由于配置不好jdk的环境变量就放弃了Java,决定不能一头撞死,于是搜寻了下卸载MySQL的方法,准备重装。
第一步:在控制面板-程序和功能
中找到mysql进行卸载
第二步:找到安装目录,若仍有文件残余,则用360进行粉碎
第三步:清楚环境变量里mysql的配置
第四步:点击运行-regedit,打开注册编辑表,删除如下三个值:
HKEY_LOCAL_ACHINE\SYSTEM\ControlSet001\Services\Eventlog\Application\MySQL
HKEY_LOCAL_MACHINE\SYSTEM\ControlSet002\Services\Eventlog\Application\MySQL
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Eventlog\Application\MySQL
至此,清理完毕
MySQL5.7安装教程中写的非常完整,每一步都十分必要,因此不再赘述。
支持:IE,Opera,Chrome,Safari
返回:一个event对象,并被当前对象填充。
区别:IE中的window.event返回的event对象通常都含有固定的成员,其中只有一部分成员被当前对象填充;Opera,Chrome,Safari中,返回的event对象类型取决于当前事件。
支持:IE9及以上,Opera,Chrome,Safari
发生:当一个事件产生,一个event对象则会被初始化并作为第一个参数传递给事件处理程序,event对象的类型取决于当前对象。且与window.event引用自同一个对象。
区别:IE9之前event对象当且仅当用attachEvent方法注册事件时才存在,并且是window.event的复制,但并不是同一对象。
var cat; console.log(cat == null);
会返回true,是因为null == undefined。当浏览器遇到script的时候,有三种情况:
以上三个过程如下图。
元素消失,不占据页面空间。会导致页面的重排和重绘。无法获取鼠标事件。
元素消失,占据页面空间。导致页面的重绘。无法获取鼠标事件。
元素没有消失,只是看不见。导致页面的重绘。可获取鼠标事件。
元素定位在可视区域之外。导致该元素的重排和重绘。无法获取鼠标事件。
若设置overflow:hidden
,元素无法获取鼠标事件。若没有,元素宽高仍为0,但其子元素会撑破父元素,因此仍可以通过子元素获取到鼠标事件。
很少用到这个,不过有同学提到了,因此还是列出来。
此外,这元素都可以用选择器定位到,可见仍是可进行DOM操作的元素。因此虽然无法获取鼠标事件,但可以用js来触发事件响应。例如用$('.item').click()
即触发点击事件。
安装了VS2012并下载了opencv249后,按照Lennon的方法配置了系统环境变量、包含目录、库目录以及附加依赖,运行程序则开始出现各种错误,记录一下。
确定附加依赖项配置文件路径及版本号正确。文件名后面的数字及版本号。
缺乏动态文件库,可以手动下载并添加到C:\Windows\System32
目录(或报错目录)下,下载地址为Download missing dll
此图即可。
查看main函数有一个输入文件路径填写不正确,因此程序退出一闪而过。将文件路径填写正确后才开始正常运行。具体情况具体分析。
opencv中v10 代表适配 Visual Studio 2011
opencv中v11 代表适配 Visual Studio 2012
opencv中v14 代表适配 Visual Studio 2015
经验一:百度没有谷歌靠谱。
经验二:以后需要仔细查看报错信息而不是直接复制粘贴进行搜索。
看到《DOM编程艺术》第7章,有几点值得记一下。
document.write是一个古老的方法,它在W3C上定义了两种用途:一是在文档中输出HTML,另一种是在调用该方法的的窗口之外的窗口、框架中产生新文档(记得用close()关闭)。看似document.write对产生一个新的文档或窗口这样的用途很有意义,但书上说:
厮以为作者在这里讲的并不清楚,document.write违背了行为与表现分离的原则并不在于函数需要放在外部引用还是内部引用,而是因为当我们写了一段document.write来产生一个HTML文档时,这个新文档的结构hin可能是这个样子的:document.write的最大缺点是它违背了“行为与样式分离的原则”。即使把document.write语句挪到外部函数里,也还是需要在标记的
<body>
部分使用<script>
标签才能调用那个函数。
<script>
标签在<p>
标签前面,也就是说document.write只能在现有文档结构的最后添加元素,因此只要使用document.write,则必定有HTML标签在<script>
标签之后。这样的标记顺序十分的混乱,且里面的<script>
标签也不是我们想要的,这样让我对document.write的好感度一下降低零点。
反观用innerHTML来实现这个输出文档的功能,其输出文档结构如下:
Look!这才是我们想要的行为与表现分离的文档结构!虽然innerHTML并不是DOM标准的组部分,但是已经包含在HTML5的规范中。几乎所有的浏览器都支持该属性,绝大多数情况下可以完美取代document.write方法。书上有一个很恰当的比方,“innerHTML就像一把大锤,而DOM则是一把手术刀”,我们可以用innerHTML大刀阔斧的直接插入网页内容,但是若想获取或修改DOM节点的属性等,我们还得需要DOM里更精确的方法如createElement与createTextNode等。
总结一下document.write与innerHTML的区别:
<script>
元素后,破坏结构和行为分离的原则。行为与结构分离的三层逐级进化概念:当有一段标记仅是为脚本服务的,即为了让DOM脚本处理它们,那么用DOM方法来创建它们才是最合适的选择
onclick=“func()”
这样的属性。Ajax是一种用来与服务器异步交互的技术,其核心为XMLHttpRequest,很多书中都会大谈特谈Ajax的方便之处,但《DOM编程》显然为一股清澈之流,作者认为能通过Ajax实现的应用一定也可以通过非Ajax技术来实现,且构建Ajax网站最好的方法是先构建一个常规的网站,再去Hijax它。这个观点跟平稳退化有着相似之处。十分欣赏作者在网站构建方面的缜密思维,总会考虑到如果这个方法可用,则怎么去做,如果这个方法不可用,再怎么去做。从不假设用户的行为与环境,而是从最基本的条件出发,这样使得少量的特殊用户也能很好的浏览我们的站点。