数字前端工作总结
Posted sasasatori
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了数字前端工作总结相关的知识,希望对你有一定的参考价值。
0. 前言
去年9月到现在总共做了两次ic的数字部分的开发,第一个设计是一个rfid的逻辑部分,第二个设计是一个多核处理器,我的工作主要是做架构设计以及主体代码的编写,模块代码一般分配给组里的其他研究生做。在做的过程中对一些问题有了反思,主要从工作流,设计约束和代码质量三个角度来做一下总结,希望反思能够带来更多的进步。
1. 工作流
我开发的基本flow是:粗设计规划(先明确此次设计的主要功能和大致结构,产生功能文档)-> 细设计规划(明确到有哪些模块与模块接口,细化功能文档,明确各个模块功能,编写模块端口表)-> 编写框架(将模块端口表转化成框架verilog代码,规定端口和关键信号)-> 分配模块(以文档和框架代码作为约束控制组员的代码实现)-> 模块汇总(整理完成的各个模块,仿真检验跨模块功能)-> 封顶测试(建立完整顶层,更新实现过程中文档里out of date的部分,整体转交验证)-> 代码综合(编写sdc,做综合,将rtl代码转为门级网表)-> 交付后端(提供文档,文档中说明物理尺寸约束和出线位置规划,以及网表和时序约束)-> 后仿验证(用后端做完的网表和sdf做后仿真对比前仿真的case,确定符合功能规划)
在具体工具上主要是VCS,Verdi,Design Compiler。验证时上fpga会用到Vivado。编写bench时会使用到Matlab,C,C++,Python这些高级语言。另外AI也是我新加入工作流的一个重要工具(我使用new bing,软件是一款跨平台桌面客户端的BingGPT),不管是作为编程助手,还是翻译软件,还是资讯检索,还是作为代码批处理工具都挺好用的,并且作为一款“自然语言编程工具”,AI具有极大的潜能,可以说其能发挥多大的作用是完全取决于使用者的,为此我专门去研究了一下prompt engineering。
我们的数字后端都是外包团队做的,所以只能够以我一般交付后端时的标准来谈。规范的产品开发流程肯定会比我这里复杂很多,毕竟高校研究所,就这么个把号研究生的草台班子。
2. 设计约束
首先明确一下目标,Design Compiler跑完综合后必须要看报告。即:
report_constraint -all_violators -verbose > $report_path/constraint.rpt
report_qor > $report_path/qor.rpt
report_power > $report_path/power.rpt
report_area > $report_path/area.rpt
report_cell > $report_path/cell.rpt
report_clock > $report_path/clk.rpt
report_hierarchy > $report_path/hierarchy.rpt
report_design > $report_path/design.rpt
report_reference > $report_path/reference.rpt
report_timing > $report_path/timing.rpt
check_design > $report_path/check_design_post_compile.rpt
check_timing > $report_path/check_timing_post_compile.rpt
这几个report里的内容,时序报告看constraint.rpt和timing.rpt,代码质量看check_design和check_timing,面积和功耗看power.rpt,area.rpt。constraint.rpt主要报一些违例,一般是约束写的问题,尽量在前端清理掉,setup的问题可以降低频率重新跑,hold的问题可以让后端插buffer来解,当然也可以梳理一下自己是否有逻辑块写的太大了导致的时序问题,如果是的话,可以在中间再插几级寄存器处理成多拍的。timing.rpt会报一个最大延时路径,与时钟周期比较,如果slack算出来是正的就ok,但是最好还是留一些余量,因为实际带上RC延时后,slack如果小了的话还是会超掉的。
check_design_post_compile.rpt尽量clean,真的有不可综合的语法的话应该design compiler都跑不完,所以check_design查出来的主要是一些信号的短路,冗余的线之类的问题,查一遍看看有没有不符合设计预期的,另外都清理掉会让后端做的时候更舒服一些。check_timing_post_compile.rpt必须确保clean。
设计约束这个事情一言以蔽之:写sdc。我写到现在还是不觉得自己能够把sdc写好了,只是大概知道要写什么内容,接下来说的一些点也只是我的个人经验,欢迎有经验的网友在评论区提供批评建议。
对于简单的单时钟的case,主要是确定几个重要参数,一般pnr工具的约束就看.lib里的和.sdc定义的,哪个更紧用哪个,所以写sdc的时候可以去参考.lib里面的一些参数,找一下要用到的cell的时序信息,看看自己要不要设置的更紧一点,因为如果设置的比.lib还松是没有意义的。input_delay,output_delay,这两个参数比较看经验,我还没有实测过流回来的芯片,师兄给的脚本设置的是时钟周期的20%,感觉有点过松,我看网上设置的情况有直接设置到70%的,不知道设置的这么松会不会在芯片实测时出现问题。
多时钟相对复杂一点,主要是需要配合设计一起看,create_generated_clock在使用时需要加上-add参数,以及处理好pin的问题(这个事情和下面check_timing联系在一起了)。
3. 代码质量
首先可综合的问题就不说了,这个太入门了,学过数集应该第一节课就说过这个问题。但是能混过仿真器和综合器的代码也不一定能用,在check_design和check_timing阶段就会把问题暴露出来,我谈一谈我遇到的几个case:
check_design:
- Warning: In design \'xxx\', port \'xxx\' is not connected to any nets. (LINT-28)
位宽问题,譬如一个模块拉了一个10b位宽的信号出去,但是在外面只连接了低8b的信号,那么高2b就会报这个问题,解决方法就是在引出时只拉需要用的线。
- Warning: In design \'xxx\', input port \'xxx\' is connected directly to output port \'xxx\'. (LINT-29)
输入到输出信号直接连接,如果非必要的话,那就直接让信号到外部连线,不要穿过这个模块。
- Warning: In design \'xxx\', the same net is connected to more than one pin on submodule \'xxx\'. (LINT-33)
Net \'xxx\' is connected to pins \'xxx\', \'xxx\'\', \'xxx\', \'xxx\'
一般普通的多驱动不会引发这个问题(clk和rst_n就是典型的多驱动),我这边出现这个情况还是信号位宽不匹配引发的,外部一个9b的信号连接到了一个16b模块的端口,所以用了符号位拓展的写法7signal[8],signal,但实际上最好还是直接让两边位宽匹配上。
- Warning: In design \'xxx\', output port \'xxx\' is connected directly to \'logic 1\'. (LINT-52)
Warning: In design \'xxx\', output port \'xxx\' is connected directly to \'logic 0\'. (LINT-52)
输出端口有直接的赋值就会引发这个warning,注意检查一下自己的赋值操作是否确实就是有意为之的。我这边的一个惨痛教训就是设计了几个可以写的reg,但是在代码里对写地址的处理出现了问题,写地址变量到不了写这几个reg的地址上去,综合器就直接把他们连成了reset时赋的初始值,但是当时没有注意查看check_design里面的内容,直接把这个设计交出去流片了。
check_timing:
- Checking generated_clocks
Warning: A non-unate path in clock network for clock \'clk_xxx\'
from pin \'u_xxx/xxx/xxx\' is detected. (TIM-052)
这个问题是在写分频设计时碰到的,我和这里是一样的情况(巧的要死,发这个帖子是微电子所的师兄,我接的就是他的代码),没有使用级联分频的写法,而使用了基于counter的分频电路。然后在最后加约束的时候没有把generated clock的位置加到分频时钟信号产生的位置上,导致了这个问题。这里的解决方案也分两种:1. 把分频时钟的reg用wire给引出来然后约束到wire上面(帖子里是这个方法)2.分频器的输出连接一个综合library中例化的dff,然后约束到这个dff的Q端,我采用了后面这种方案解决了这个问题。
另外对于跨时钟域设计注意一下时序上的处理,我在这里也吃过亏,快时钟到慢时钟时漏了打两拍处理,不知道回片以后这部分测试会不会出问题,明明fpga测试时是查出过这里的问题的,后来因为综合时在一个module下面调用了两个时钟导致出了一些问题又把这部分改掉了,改的时候漏掉了跨时钟域处理。如果是慢到快倒是直接采样就好,没有那么多问题。
- Checking loops
Warning: Disabling timing arc between pins \'A\' and \'Z\' on cell \'u_xxxx/xxx/xxx\'
to break a timing loop. (OPT-314)
这个的成因是写了逻辑环路,这个帖子 底下就有讨论。我碰到的case是在写处理器的regfile时,想要做一个如果在同一拍读写同一个寄存器地址,那么就直接让写端口赋值给读端口的逻辑,结果这个显而易见的引发了逻辑回环问题。解决过程是首先根据report里报告的产生回环的逻辑块,找到相应的逻辑,然后分析一下到底是怎么形成回环的,同时在写代码的时候就得谨慎的处理输入直接给输出或者通过组合逻辑给输出的情况,得要提前判断存不存在一条输出再到这个输入的反馈回路,打破loop的方法除了删除掉回环的部分,也可以在不影响时序的前提下在输入和输出之间插入一级寄存器。
- Checking unconstrained_endpoints
Warning: The following end-points are not constrained for maximum delay.
这个大部分情况下都是写了latch,在design compiler的运行log里面就可以看到打印的内容,如果是正常的寄存器:
Inferred memory devices in process
in routine xxx line xxx in file
\'xxx/xxx.v\'.
===============================================================================
| Register Name | Type | Width | Bus | MB | AR | AS | SR | SS | ST |
===============================================================================
| xxxx | Flip-flop | 8 | Y | N | N | N | N | N | N |
===============================================================================
而如果是latch:
Inferred memory devices in process
in routine xxx line xxx in file
\'xxx/xxx.v\'.
====================================================================================
| Register Name | Type | Width | Bus | MB | AR | AS | SR | SS | ST |
====================================================================================
| xxx | Latch | 8 | Y | N | N | N | - | - | - |
====================================================================================
如果是多时钟的情况也可能是generated clock处理的有问题。latch也是上课肯定会提到的事情,但是不去真的做数字前端就不会重视这方面的代码质量问题。我在两个地方都碰到过这个典型问题:
- case
- if...else...
这两个地方我一开始都采用alway@(*)的组合式写法,针对情况1,按照教科书的说法是case逻辑里面漏掉default或者if...else...里面漏掉else会引发latch,但是实际情况要复杂的多,去写一段很长的译码逻辑时必须要用到很长的case或者if...else...语句,而写得越长检查起来越麻烦,同时工具的表现也越不可控,我两次开发都在这个问题上栽了跟头,针对这种情况,方案1肯定是尽可能的检查latch的成因想办法消除掉,但还有一个简单粗暴的方案2:在不影响时序功能情况下直接改成时序驱动的always@(posedge clk),可以有效消除这一问题,比如在三段式FSM的输出逻辑部分,如果方案2不好使(改成时序驱动以后会引发时序问题)的话,那么还有方案3:所有组合的case/if...else...一定是可以用assign xx = xx ? xx : xx
三目运算符的嵌套来等效替换,换成这种写法之后latch肯定就无了。在e203的代码可以看到主要是方案3,这种写法确实电路上也是最可控的,只是会牺牲掉一些可读性。
从工作流的角度来说还有一些可以改进的地方:
- 子模块编写后就可以跑DC进行可综合性检查以及check_design,check_timing,不要一直拖到顶层完成才开始做。
- 应该引入spyglass来进行代码检查,相比check_design能查出更多的问题,尤其是一些跨时钟域的问题。
另外今天晚上复盘的过程中才意识到自己前面设计里面犯得一些严重问题(不看check_design,导致综合后的电路和设计预期的电路功能不符,跨时钟域处理失误等)。这些都是教训,估计很难预期回片后的测试能够成功了。但是做事就是这样,先有失败才有成功。
此外我计划在下次设计用systemverilog替换verilog,目前来看sv有很多特性非常吸引我,感觉是能够提高开发效率和开发质量的,当然具体如何要在试水之后才知道。
前端知识总结(HTML CSS Javascript)
HTML(超文本标记语言)
列表标签
无序列表ul:属性type:circle(空心圆) disc(默认,实心圆) square(黑色方块)
有序列表ol:属性type:1、A、a、I、i(数字、字母、罗马数字)
定义列表dl:
dt:定义标题
dd:定义描述
a标签的作用:
- 超级链接
- 锚链接(a href="#xxx",xxx代表的是锚点的位置,可以使用a标签声明,用name来坐定名称,或者使用其他的标签来定义,用id声明)
a链接中target属性的使用:
- _self 在自身页面打开
- _blank 在新窗口打开
- _parent 在父窗口打开
- _top 在顶部窗口打开
- _search相当于给窗口起一个名字,如果打开过不再打开新的页面(search可以换为任何自己起的名字)
target的属性值:top和parent
target=_parent,将链接的文件载入含有该链接框架的父框架集或父窗口中。如果含有该链接的框架不是嵌套的,则在浏览器全屏窗口中载入链接的文件,就象self参数一样。
target=_top,在当前的整个浏览器窗口中打开所链接的文档,因而会删除所有框架 不写的话就是表示默认值,默认值一般跟浏览器有关。
普通表格
<tr>表示为行
<td>表示为列(单元格)
<th>表示表头
表格的属性
border:边框像素为单位
width:宽度
height:高度
行的属性:
align:控制表格的对齐方式:center right left
valign:控制表格的垂直对齐(都是对表格的内容的控制)
跨列和跨行:
colspan=""占几列
rowspan=""占几行
<b> 定义粗体
<big>定义大号字体
<em>着重文字(斜体)
<i>斜体字
<sub>下标字,数学上的log下标
<sup>上标字,数学上的平方
<del>删除字,在文字上打上一条横线
表单标签
form标签
常用属性: action 表示动作,值为服务器端的地址,把表单的数据提交到该地址上进行处理
method:请求方式:get和post
enctype:表示表单提交的类型
默认值:application/x-www-form-urlencoded 普通表单
multipart/form-data 多部分表单(一般用于文件上传)
text/plain普通文本
get和set的区别:
get:数据储存在地址栏中,请求参数都在地址后拼接,不安全、效率高,大小有限制,一般用于查询数据
post:地址没有数据,请求参数单独处理,安全可靠、效率低,大小理论上没有限制,一般用于插入删除操作
input标签
type:可能要取得值:
text 文本框 输入内容
password 密码,密文或者掩码
radio 单选按钮,name必须要一致;value:提交给服务器的数据,表示同一组只能选中一个
checkbox 表示多选,name必须一致,返回值是数组,可以选多个
file 表示选择上传文件
以上具有输入性质的必须要有name属性,初始开始写value表示要有默认值(以后获取输入框的内容要根据name来获取)
一下按钮不具有输入性质,不需要name属性,但是按钮上的文字提示使用的是value属性
submit 提交
reset 重置
image 图片提交按钮
button 普通按钮
hidden 表示隐藏域,该框的内容服务器需要,但是不想让用户知道(不想清楚地显示在界面上)
email 表示邮箱格式的数据
name属性:表单元素的名字,只有name属性才能提交给服务器
value属性:提交给服务器的数据
placeholder:提示信息
高级属性:
disabled:禁用
readonly:只读
select元素(下拉列表)
<select name="">
<option value=""></option>
<option value=""></option>
</select>
selected表示选中该项,默认是选择第一项
textarea元素(文本区)
<textarea cols="100" rows="5">
框架标签
frameset框架结构标签,把body删除掉,使用frameset代替body
基本的注意事项
1.不能将<body></body>标签与<framesete></frameset>标签同时使用
2.假如一个框架有可见边框,用户可以拖动边框来改变他的大小。可以使用<frame>标签中加入:noresize="noresize"
3.freamset 的属性freamborder="1|0|yes|no"表示是否有边框,border="1"表示边框的粗细 bordercolor表示边框的颜色
其他标签
<!--该网页的关键字-->
<meta name="keywords" content="keyword1,keyword2,keyword3">
<!--该网页的描述-->
<meta name="description" content="this is my page">
<!--该网页的编码-->
<meta http-equiv="content-type" content="text/html; charset=UTF-8"> html4.01
<!--页面自动跳转,2秒后跳转到百度-->
<meta http-equiv="refresh" content="2;URL=https://www.baidu.com">
<!--该网页的编码-->
<meta charset="UTF-8"> html5
<!-- href:引入css文件的地址-->
<link rel="stylesheet" type="text/css" href="./styles.css">
<!--src:js的文件地址-->
<script type="text/javascript" src=""></script>
特殊符号
< 小于号
> 大于号
& 与字符
" 引号
® 己注册
© 版权
™ 商标
空格
CSS(层叠样式表)
语法规则:选择器属性:值;属性:值
使用方式:
-
内联方式
把css样式嵌入到HTML标签中 <div style="color:blue;font-size:50px">This is my HTML page. </div>
-
内部样式
使用style标签引用css <style type=“text/css”> //告诉浏览器使用css解析器去解析 div color:red; font-size:50px </style> 好处是:能够控制页面中的多个元素样式,缺点:只能一个页面使用
-
外部样式
将css样式抽成一个单独文件,谁用谁就引用,好处:多个页面可以同时使用 方式1:链接式: <link rel="stylesheet" type="text/css" href=“div.css"></link> rel:代表当前页面与href所指定文档的关系 type:文件类型,告诉浏览器使用css解析器去解析 href:css文件地址 方式2:导入式: <style type="text/css"> @import url("div.css") </style> 备注:link和@import区别: link所有浏览器都支持,@import某些版本低的IE不支持 @import是等待HTML加载完才加载,link解析到这个语句,就加载 @import不支持js动态修改
优先级:内联样式>内部样式>外部样式,就近原则
CSS选择器
基本选择器:
- 标签选择器 span
- id选择器 #xx
- class选择器 .xx
- 优先级从高到低:id>class>标签
属性选择器:
格式为:html标签[属性='属性值']css属性:css属性值;
或者html标签[属性]css属性:css属性值;具体示例:
input[type='text']
background-color: pink
font[size]
color: green
伪元素选择器:主要是针对a标签
a:link 静止状态
a:hover 悬浮状态
a:active 触发状态
a:visited 完成状态
层级选择器:
空格 表示后代选择器
大于号 子代选择器
加号 相邻的兄弟
~ 通用兄弟
其他选择器:
全局选择器 *
群组选择器 h1,h2
CSS属性
文本和文字属性
文字属性:font:italic bold 30px “幼圆”;/style weight size family swsf/
文本属性:text-indent:缩进,单位是em或者百分比
text-decoration:文字修饰
word-spacing:字符之间的间隔
letter-spacing:字母或单词之间的间隔
line-height:设置行高
背景属性:background-repeat: repeat-y:垂直方向平铺、repeat-x:水平方向平铺、repeat:水平垂直方向平铺、no-repeat:任何方向都不平铺
列表属性:
list-style-type:decimal;改变列表的标志类型
list-style-image: url(“images/dog.gif”);用图像表示标志
list-style-position: inside;确定标志出现在列表项内容之外还是内容内部
简写
list-style: decimal url(img/001.png) inside;
去掉样式:
list-style:none;
list-style-type:none;
尺寸显示轮廓属性:
display:none 不显示 block 块级显示 inline:行级显示 inline-block:行级块
block块元素 有宽度和高度
inline 是默认的行元素,没有高度和宽度
inline-block行块标签,既有行又有块
overflow:溢出,当内容超出了盒子的大小,如何处理
H5之后添加了弹性盒子,用于设置垂直对齐
display:flex
align-items:center;垂直居中
justify-content:center;水平居中
clear属性:规定元素的哪一侧不允许其他浮动元素
值 | 描述 |
---|---|
left | 在左侧不允许浮动元素。 |
right | 在右侧不允许浮动元素。 |
both | 在左右两侧均不允许浮动元素。 |
none | 默认值。允许浮动元素出现在两侧。 |
inherit | 规定应该从父元素继承 clear 属性的值。 |
定位属性
position:static|relative|absolute|fixed
静态定位(默认定位方式)static
相对定位(relative)相对于原来位置偏移某个距离。元素仍保持其未定位前的形状,他原本所占的空间仍保留
绝对定位(absolute):元素框从文档流完全删除,并相对于其包含块定位。包含块可能是文档中的另一个元素或者是视窗本身。元素原先在正常文档流中所占的空间会关闭,就好像原来不存在一样。元素定位后会生成一个块级框,而不论原来它在正常流中生成何种类型的框
固定定位(fixed)元素框的表现类似于将position设置为absolute,不过其位置相对于视窗本身。
盒子模型
border margin padding
CSS3扩展属性
border-radius 圆角属性 示例:border-radius:20px;
box-shadow 向方框添加阴影 示例:box-shadow:10px 10px 5px #333333;
background-size属性设置背景图片的大小
background-url(img/1.png);
background-size:200px 300px;
background-repeat:no-repeat;
background-image 为指定元素使用多个背景图像,多个URL用逗号隔开
text-shadow 文本阴影
javaScript
完整的javaScript实现包含了三个部分:ECMAScript,文档对象模型(DOM Document Object Model),浏览器对象模型(BOM Brower Object Model)
数据类型:
-
基本类型(原始类型)undefined null number string boolean
-
引用类型(对象类型)Object(Person) Array String Number Boolean RegExp
数组的声明:var a=[1,1,1,2];
三种使用方式:
- 在<script>标签中,可以放在网页中的任意位置
- 使用外部的js文件,把js代码单独放在文件中,通过引用来使用<script type="" src=""></script>>
- 放在标签中的事件中,常见事件onclick()
关系运算符:
==:比较的是两个值,会自动转换类型
===:比较的是引用,首先比较类型,如果类型不同,直接返回false
if语句:
if(变量):如果变量值是undefined,null表示false,其他是true,如果变量没有定义会出现异常。
zhangsan.name:是给zhangsan添加name的属性,没有赋值
增强for的写法:
for(var i in arr) i指的是下标
function中的参数不用写数据类型,返回值也不用写,如果有返回值就直接return
自行执行的匿名函数:
(function() document.write(""))();
闭包:
闭包就是能够读取其他函数内部局部变量的函数; 闭包可以理解成“定义在一个函数内部的函数“。
闭包三个条件:
1 闭包是一个内部函数
2 闭包能够读取其他(外部)函数的局部变量
3 闭包和局部变量在同一个作用域。
使用形式:1 闭包作为函数的返回值;2闭包作为函数的参数。
案例:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>闭包 closure</title>
<script type="text/javascript">
/*定义一个函数*/
function a()
var a=10;
document.write(a);
document.write("<br/>");
// a();
// a();
// a();
function b()
var num=10;//没有释放
/*函数包含函数*/
function c()
num++;
document.write(num);
document.write("<br />")
return c;
var f=b();//f是一个函数:闭包
f();
f();
f();
</script>
</head>
<body>
</body>
</body>
</html>
闭包的好处:
- 使局部变量常驻内存
- 避免污染全局变量
- 提高封装性保护局部变量
系统函数:
- 提示框alert(),,没有返回值,如果接受是undefined
- 确认框confirm(),返回值是boolean型,点击确定返回true,取消返回false
- 输入框prompt("","")第一个参数是提示信息,第二个参数是用户输入的默认值,点击确定返回用户的输入值,否则返回null.
其他系统函数:
- parseInt():将字符串转换为整形
- parseFloat():字符串转换为小数
- isNaN():判断数字是不是不是一个数字,不是一个数字返回true
事件:
事件 | 描述 |
---|---|
onchange | HTML 元素内容改变(离开光标触发) |
onclick | 用户点击 HTML 元素 |
onmouseover | 光标移动到HTML元素 |
onmouseout | 光标离开HTML元素 |
onkeydown | 用户按下键盘按键 |
onload | 浏览器已完成页面的加载 |
字符串、正则表达式:
var str="hello,我爱java";//原始类型
var str2=new String("hello");//引用类型对象类型
var str3=String("hello");//原始类型
RegExp对象方法:
exec:检索字符串中指定的值,返回找到的值,并确定其位置
test:检索字符串中的指定的值,返回true或者false
支持正则表达式的String对象的方法:
match:找到一个或者多个正则表达式的匹配
replace:替换与正则表达式匹配的子串
split:把字符串分割为字符串数组
正则表达式的示例:
var patt1=new RegExp("^1[3589]\\\\d9$");
document.write(patt1.test("13688889999"));//true
DOM
获取HTML元素:
- 通过id来获取 document.getElementById("");
- 通过标签名获取 document.getElementsByTagName("")
- 通过类名获取 document.getElementsByClassName("")
修改HTML元素:
- 修改内容:innerHTML=""(这个可以实现标签的效果显示) innerText(不能解析标签效果) 示例:document.getElementById(“p1”).innerHTML=“abcd”;
- 修改属性:attribute=新属性值 示例:document.getElementById(“image”).src=“2.jpg”;
- 修改css样式:style.property=新样式 示例:document.getElementById(“p2”).style.color=“blue”;
元素操作:
-
创建新元素 document.creatElement() 在已知的元素后面添加新的元素appendChild();
-
删除已有的元素 parent…removeChild(child)
如果能够在不引用父元素的情况下删除某个元素,就太好了。不过很遗憾。DOM 需要清楚您需要删除的元素,以及它的父元素。
这是常用的解决方案:找到您希望删除的子元素,然后使用其 parentNode 属性来找到父元素:
var child=document.getElementById(“p1”);
child.parentNode.removeChild(child);
DOM事件
DOM允许我们通过触发事件来执行代码,比如:元素被点击,页面加载完成,输入框被修改
示例:<h1 onclick="this.innerHTML='改变内容!'">点击文本!</h1>
onload 和 onunload 事件会在用户进入或离开页面时被触发。
onchange 事件常结合对输入字段的验证来使用。
onmouseover 和 onmouseout 事件可用于在用户的鼠标移至 HTML 元素上方或移出元素时触发函数
<div οnmοuseοver="mOver(this)" οnmοuseοut="mOut(this)" </div>
<script>
function mOver(obj)
obj.innerHTML="Thank You"
function mOut(obj)
obj.innerHTML="Mouse Over Me"
</script>
EventListener addEventListener()方法
document.getElementById("myBtn").addEventListener("click", displayDate);
addEventListener() 方法用于向指定元素添加事件句柄。
addEventListener() 方法添加的事件句柄不会覆盖已存在的事件句柄。
element.addEventListener(event, function, useCapture);
第一个参数是事件的类型 (如 “click” 或 “mousedown”). 把on去掉
第二个参数是事件触发后调用的函数。
第三个参数是个布尔值用于描述事件是冒泡还是捕获。该参数是可选的。
注意:不要使用 “on” 前缀。 例如,使用 “click” ,而不是使用 “onclick”。
事件传递有两种方式:冒泡与捕获。
事件传递定义了元素事件触发的顺序。 如果你将
元素插入到
元素中,用户点击元素, 哪个元素的 “click” 事件先被触发呢?
在 *冒泡 *中,内部元素的事件会先被触发,然后再触发外部元素,即:
元素的点击事件先触发,然后会触发
元素的点击事件。在 *捕获 *中,外部元素的事件会先被触发,然后才会触发内部元素的事件,即:
元素的点击事件先触发 ,然后再触发元素的点击事件。
addEventListener()的第三个参数默认值是false即冒泡传递,当值为true时,就是捕获传递
BOM
获取window尺寸(涵盖所有的浏览器)
var w=window.innerWidth||document.documentElement.clientWidth||document.body.clientWidth;
var h=window.innerHeight||document.documentElement.clientHeight||document.body.clientHeight;
window方法
- window.open()打开新的窗口
- window.close()关闭当前窗口
Screen
- 可用宽度:screen.availWidth 属性返回访问者屏幕的宽度,以像素计,减去界面特性,比如窗口任务栏
- 可用高度:screen.availHeight属性返回访问者的屏幕高度,以像素计,减去界面特性,比如窗口任务栏
Location
window.location对象用于获取当前页面的地址(URL),并把浏览器重新定向到新的页面
window.location对于在编写时可不使用window这个前缀。
- location.href 属性返回当前页面的URL
- location.hostname 返回web主机的域名
- location.pathname返回当前页面的路径和文件夹
- location.port返回web主机的端口
- location.protocal返回使用的web协议
history
window.history对象包含浏览器的历史
window.history对象在编写时可不使用window这个前缀
- history.back()–与在浏览器中点击后退按钮功能相同
- history.forward()–与在浏览器中点击前进按钮功能相同
- history.go(number|url)–加载历史列表中的某个具体页面。URL 参数使用的是要访问的 URL,或 URL 的子串。而 number 参数使用的是要访问的 URL 在 History 的 URL 列表中的相对位置。
JavaScript计时
Date对象(获取年 月 日 时 分 秒)
计时函数
setInterval()周期执行函数,间隔指定的毫秒数不停的执行指定的代码
cleanInterval()方法用于停止setInterval()方法执行的函数代码
setTimeout()延迟执行函数,只能执行一次
clearTimeout()方法用于停止执行setTimeout()方法的函数代码
动态显示时间:
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<input id="btn1" type="button" value="暂停" onclick="stoptime()" />
<input id="btn2" type="button" value="开始" onclick="starttime()" disabled="disabled" /><br />
<div id="clock">
<script type="text/javascript">
var clock = document.getElementById("clock");
var btn1 = document.getElementById("btn1");
var btn2 = document.getElementById("btn2");
function showtime()
var d = new Date();
var year = d.getFullYear();
var month = d.getMonth() + 1;
var day = d.getDate();
var h = d.getHours();
var m = d.getMinutes();
var s = d.getSeconds();
clock.innerHTML = t = year + "-" + month + "-" + day + " " + h + ":" + m + ":" + s;
var tid = setInterval("showtime()", 1000);
function stoptime()
clearInterval(tid);
btn2.disabled = false;
btn1.disabled = true;
function starttime()
tid = setInterval("showtime()", 1000);
btn1.disabled = false;
btn2.disabled = true;
</script>
</div>
</body>
</html>
以上是关于数字前端工作总结的主要内容,如果未能解决你的问题,请参考以下文章