赞
踩
目录
欢迎访问我的个人博客:https://www.gaoyuan.ink,一起共勉学习~
问题:你知道TCP协议、IP协议、HTTP协议分别在哪一层吗?
欢迎访问我的个人博客:https://www.gaoyuan.ink,一起共勉学习~
一、 项目的角色划分
如果不包括前、后期的市场推广和产品销售人员,开发团队一般可以划分为项目负责人、程序员、UI、业务(测试)这几个角色。
二、 开发工具的选取
三、 项目开发流程
只有每个开发人员都按照一个共同的规范去设计、沟通、开发、测试、部署,才能保证整个开发团队协调一致的工作,从而提高开发工作效率,提升工程项目质量。
DOCTYPE标签是一种标准通用标记语言的文档类型声明,它的目的是要告诉标准通用标记语言解析器,它应该使用什么样的文档类型定义(DTD)来解析文档。
现代浏览器的html布局引擎通过检查doctype决定使用兼容模式还是标准模式对文档进行渲染,一些浏览器有一个接近标准模型。
在HTML4.01中<!doctype>声明指向一个DTD,由于HTML4.01基于SGML,所以DTD指定了标记规则以保证浏览器正确渲染内容
HTML5不基于SGML,所以不用指定DTD
一、语义标签
标签 | 描述 |
---|---|
<header> | 定义了文档的头部区域 |
<footer> | 定义了文档的尾部区域 |
<nav> | 定义文档的导航 |
<section> | 定义文档中的节 |
二、增强型表单
输入类型 | 描述 |
---|---|
color | 主要用于选取颜色 |
date | 选取日期 |
datetime | 选取日期(UTC时间) |
datetime-local | 选取日期(无时区) |
month | 选择一个月份 |
week | 选择周和年 |
time | 选择一个时间 |
包含e-mail地址的输入域 | |
number | 数值的输入域 |
url | url地址的输入域 |
tel | 定义输入电话号码和字段 |
search | 用于搜索域 |
range | 一个范围内数字值的输入域 |
html5新增表单属性
属性 | 描述 |
---|---|
placehoder | 输入框默认提示文字 |
required | 要求输入的内容是否可为空 |
pattern | 描述一个正则表达式验证输入的值 |
min/max | 设置元素最小/最大值 |
step | 为输入域规定合法的数字间隔 |
height/wdith | 用于image类型<input>标签图像高度/宽度 |
autofocus | 规定在页面加载时,域自动获得焦点 |
multiple | 规定<input>元素中可选择多个值 |
三、音频和视频
音频:<audio src=" "></audio>
视频:<video src=" "></video>
四、Canvas绘图和SVG
五、WebSocket
WebSocket协议为web应用程序客户端和服务端之间提供了一种全双工通信机制。
特点:
(1)握手阶段采用HTTP协议,默认端口是80和443
(2)建立在TCP协议基础之上,和http协议同属于应用层
(3)可以发送文本,也可以发送二进制数据。
(4)没有同源限制,客户端可以与任意服务器通信。
(5)协议标识符是ws(如果加密,为wss),如ws://localhost:8023
Web Worker 的作用,就是为 JavaScript 创造多线程环境,允许主线程创建 Worker 线程,将一些任务分配给后者运行。在主线程运行的同时,Worker 线程在后台运行,两者互不干扰。等到 Worker 线程完成计算任务,再把结果返回给主线程。这样的好处是,一些计算密集型或高延迟的任务,被 Worker 线程负担了,主线程(通常负责 UI 交互)就会很流畅,不会被阻塞或拖慢。
Worker 线程一旦新建成功,就会始终运行,不会被主线程上的活动(比如用户点击按钮、提交表单)打断。这样有利于随时响应主线程的通信。但是,这也造成了 Worker 比较耗费资源,不应该过度使用,而且一旦使用完毕,就应该关闭。
Canvas 元素用于在网页上绘制图形,该元素标签强大之处在于可以直接在HTML上进行图形操作,
SVG先绘制后记忆,换句话说任何使用SVG绘制的形状都能被记忆和操作,浏览器可以再次显示
Canvas则是先绘制后忘记,一旦绘制完成你就不能访问像素和操作它
SVG对于创建图形例如CAD软件是良好的,一旦东西绘制,用户就很难操作它
Canvas则用于绘制和遗忘类似动漫和游戏的场画。为了之后的操作,
SVG需要记录坐标,所以比较缓慢。因为没有记住以后事情的任务,所以Canvas更快。
href 是指向网络资源所在位置,建立和当前元素(锚点)或当前文档(链接)之间的链接,用于超链接。
src是指向外部资源的位置,指向的内容将会嵌入到文档中当前标签所在位置;在请求src资源时会将其指向的资源下载并应用到文档内,例如js脚本,img图片和frame等元素。
1.id选择器( # myid)
2.类选择器(.myclassname)
3.标签选择器(div, h1, p)
4.相邻选择器(h1 + p)
5.子选择器(ul > li)
6.后代选择器(li a)
7.通配符选择器( * )
8.属性选择器(a[rel = “external”])
9.伪类选择器(a:hover, li:nth-child)
不可继承的:baidisplay、dumargin、border、padding、background、height、min-height、max- height、width、min-width、max-width、overflow、position、left、right、top、 bottom、float、clear、table-layout、vertical-align、page-break-after、 page-bread-before和unicode-bidi。
可继承的:
所有子元素可继承:visibility和cursor、z-index。
内联元素可继承:letter-spacing、word-spacing、white-space、line-height、color、font、 font-family、font-size、font-style、font-variant、font-weight、text- decoration、text-transform、direction。
块状元素可继承:text-indent和text-align。
列表元素可继承:list-style、list-style-type、list-style-position、list-style-image。
表格元素可继承:border-collapse。
1)有两种,IE 盒子模型、标准 W3C 盒子模型;
IE 的 content 部分包含了 border 和 padding;
2)盒模型:内容(content)、填充(padding)、边界(margin)、边框(border)
CSS盒模型和IE盒模型的区别:
在 标准盒子模型中,width 和 height 指的是内容区域的宽度和高度。增加内边距、边框和外边距不会影响内容区域的尺寸,但是会增加元素框的总尺寸。
IE盒子模型中,width 和 height 指的是内容区域+border+padding的宽度和高度。
box-sizing是CSS3新增属性,可调整盒子模型的样式。
box-sizing:border-box表示盒模型基于IE的盒模型,width和height决定盒模型的content区、padding区和border区。
box-sizing:content-box表示盒模型基于标准盒模型,width和height只决定盒模型的content区
box-sizing:inherit表示继承自父元素。
- /*已知容器的宽高 设置层的外边距*/
- div {
- position: relative; /* 相对定位或绝对定位均可 */
- width:500px;
- height:300px;
- top: 50%;
- left: 50%;
- margin: -150px 0 0 -250px; /* 外边距为自身宽高的一半 */
- }
-
- /*不知宽高-水平垂直居中 利用 `transform` 属性*/
- div {
- position: absolute; /* 相对定位或绝对定位均可 */
- width:500px;
- height:300px;
- top: 50%;
- left: 50%;
- transform: translate(-50%, -50%);
- }
-
- /*利用flex布局*/
- .container {
- display: flex;
- align-items: center; /* 垂直居中 */
- justify-content: center; /* 水平居中 */
- }
-
- /*让绝对定位的div居中*/
- div {
- position: absolute;
- width: 300px;
- height: 300px;
- margin: auto;
- top: 0;
- left: 0;
- bottom: 0;
- right: 0;
- }
清除浮动是为了清除使用浮动元素产生的影响。浮动的元素,高度会塌陷,而高度的塌陷使我们页面后面的布局不能正常显示。
1、父级div定义height;
2、父级div 也一起浮动;
3、浮动元素的父级div定义伪类:after , clear:both用来闭合浮动的
- &::after,&::before{
- content: " ";
- visibility: hidden;
- display: block;
- height: 0;
- clear: both;
- }
beforeCreate( 创建前 )
created(创建后)
beforeMount(挂在前)
mounted(挂载后)
beforeUpdate(数据更新前调用)
updated(更新后)
beforeDestroy(实例销毁前)beforeUnmount
destroyed(实例销毁后) unmounted
activated(被 keep-alive 缓存的组件激活时调用)
decactived(被 keep-alive 缓存的组件停用时调用)
实现mvvm的双向绑定,是采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调
一、加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount->子mounted->父mounted
二、子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated
三、父组件更新过程
父beforeUpdate->父updated
四、销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed
1.方法一:props和$emit
父组件通过props向下传递数据给子组件,子组件通过event给父组件发送消息,实际上就是子组件把自己的数据发送给父组件。
2.方法二:$attrs和$listeners
第一种方式处理父子组件之间的数据传输有一个问题:如果父组件A下面有子组件B,组件B下面有组件C,这时如果组件A想传递数据给组件C怎么办呢? 如果采用第一种方法,我们必须让组件A通过prop传递消息给组件B,组件B在通过prop传递消息给组件C;要是组件A和组件C之间有更多的组件,那采用这种方式就很复杂了。Vue 2.4开始提供了$attrs和$listeners来解决这个问题,能够让组件A之间传递消息给组件C。
- <!--组件C-->
- <template>
- <div>
- <input type="text" v-model="$attrs.messagec" @input="passCData($attrs.messagec)">
- </div>
- </template>
-
- <script>
- export default {
- name: 'C',
- data () {
- return {}
- },
- methods:{
- passCData(val){
- //触发父组件A中的事件,把从A得到的数据hello C还给A组件
- this.$emit('getCData',val)
- }
- }
- }
- </script>
- <!--组件B-->
- <template>
- <div>
- <input type="text" v-model="mymessage" @input="passData(mymessage)">
- <!-- C组件中能直接触发getCData的原因在于 B组件调用C组件时 使用 v-on 绑定了$listeners 属性 -->
- <!-- 通过v-bind 绑定$attrs属性,C组件可以直接获取到A组件中传递下来的props(除了B组件中props声明的) -->
- <C v-bind="$attrs" v-on="$listeners"></C>
- </div>
- </template>
-
- <script>
- export default {
- name: 'B',
- props:[
- message:{
- type: String,
- default: null
- }
- ],//得到父组件A传递过来的数据,hello B
- methods:{
- passData(val){
- //触发父组件中的事件,把message给组件A
- this.$emit('getChildData',val)
- }
- }
- }
- </script>
- <!--组件A-->
- <template>
- <div>
- <p>this is parent compoent!</p>
- <B
- :messagec="messagec"
- :message="message"
- :getCData="getCData"
- :getChildData="getChildData"></B>
- </div>
- </template>
-
- <script>
- export default {
- name: 'A',
- data(){
- return {
- message:'hello B',
- messagec:'hello C' //传递给c组件的数据
- }
- },
- methods:{
- getChildData(val){
- console.log('这是来自B组件的数据',val) //打印hello B
- },
- //执行C子组件触发的事件
- getCData(val){
- console.log("这是来自C组件的数据:", val) //打印hello C
- }
- }
- }
- </script>
3.方法三:provide和 inject
在 Vue.js 的 2.2.0+
版本中添加加了 provide 和 inject 选项。他们成对出现,用于父级组件向下传递数据。
父组件中通过provide来提供变量,然后在子组件中通过inject来注入变量。不论子组件有多深,只要调用了inject那么就可以注入provide中的数据。而不是局限于只能从当前父组件的prop属性来获取数据,只要在父组件的生命周期内,子组件都可以调用。
- <!--父组件-->
- <template>
- <div>
- <p>this is parent compoent!</p>
- <child></child>
- </div>
- </template>
-
- <script>
- export default {
- name: 'parent',
- provide: {
- forChidrenData:'这是要个子组件的数据'
- },
- data(){
- return {
- message:'hello'
- }
- }
- }
- </script>
-
-
-
- <!--子组件-->
- <template>
- <div>
- <input type="text" v-model="mymessage">
- </div>
- </template>
-
- <script>
- export default {
- name: 'child',
- inject:['forChidrenData'], //得到父组件传递过来的数据
- data(){
- return {
- mymessage:this.forChidrenData
- }
- }
- }
- </script>
4.方法四:vuex处理组件之间的数据交互
如果业务逻辑复杂,很多组件之间需要同时处理一些公共的数据,这个时候才有上面这一些方法可能不利于项目的维护,vuex的做法就是将这一些公共的数据抽离出来,然后其他组件就可以对这个公共数据进行读写操作,这样达到了解耦的目的。
5.方法五:中央事件总线
如果两个组件不是父子关系呢?这种情况下可以使用中央事件总线的方式。新建一个Vue事件bus对象,然后通过bus.$emit触发事件,bus.$on监听触发的事件。
公共事件总线eventBus的实质就是创建一个vue实例,通过一个空的vue实例作为桥梁实现vue组件间的通信。它是实现非父子组件通信的一种解决方案。
- <!--兄弟组件A-->
- <template>
- <div>
- <p>this is brother1 compoent!</p>
- <input type="text" v-model="mymessage" @input="passData(mymessage)">
- </div>
- </template>
-
- <script>
- export default {
- name: 'brother1',
- data(){
- return {
- mymessage:'hello brother1'
- }
- },
- methods:{
- passData(val){
- //触发全局事件globalEvent
- bus.$emit('globalEvent', val)
- }
- }
- }
- </script>
-
-
- <!--兄弟组件B-->
- <template>
- <div>
- <p>this is brother2 compoent!</p>
- <p>brother1传递过来的数据:{{brothermessage}}</p>
- </div>
- </template>
-
- <script>
- export default {
- name: 'brother2',
- data(){
- return {
- brothermessage:''
- }
- },
- mounted(){
- //绑定全局事件globalEvent
- bus.$on('globalEvent',(val)=>{
- this.brothermessage = val;
- })
- }
- }
- </script>
-
-
-
- //中央事件总线
- var bus=new Vue();
- var app=new Vue({
- el:'#app',
- template:`
- <div>
- <brother1></brother1>
- <brother2></brother2>
- </div>
- `,
- beforeDestroy(){
- sd bus.$off('globalEvent')
- }
- })
6.方法六:$parent和$children
- Vue.component('child',{
- props:{
- value:String, //v-model会自动传递一个字段为value的prop属性
- },
- data(){
- return {
- mymessage:this.value
- }
- },
- methods:{
- changeValue(){
- this.$parent.message = this.mymessage;//通过如此调用可以改变父组件的值
- }
- },
- template:`
- <div>
- <input type="text" v-model="mymessage" @change="changeValue">
- </div>`
- })
-
- Vue.component('parent',{
- template:`
- <div>
- <p>this is parent compoent!</p>
- <button @click="changeChildValue">test</button >
- <child></child>
- </div>
- `,
- methods:{
- changeChildValue(){
- this.$children[0].mymessage = 'hello';
- }
- },
- data(){
- return {
- message:'hello'
- }
- }
- })
-
- var app=new Vue({
- el:'#app',
- template:`
- <div>
- <parent></parent>
- </div>
- `
- })
- 每个对象都会在其内部初始化一个属性,就是prototype(原型),当我们访问一个对象的属性时,
- 如果这个对象内部不存在这个属性,那么他就会去prototype里找这个属性,这个prototype又会有自己的prototype,
- 于是就这样一直找下去,也就是我们平时所说的原型链的概念。
- 关系:instance.constructor.prototype = instance.__proto__
-
- 特点:
- JavaScript对象是通过引用来传递的,我们创建的每个新对象实体中并没有一份属于自己的原型副本。当我们修改原型时,与之相关的对象也会继承这一改变。
-
-
- 当我们需要一个属性的时,Javascript引擎会先看当前对象中是否有这个属性, 如果没有的话,
- 就会查找他的Prototype对象是否有这个属性,如此递推下去,一直检索到 Object 内建对象。
- function Func(){}
- Func.prototype.name = "Sean";
- Func.prototype.getInfo = function() {
- return this.name;
- }
- var person = new Func();//现在可以参考var person = Object.create(oldObject);
- console.log(person.getInfo());//它拥有了Func的属性和方法
- //"Sean"
- console.log(Func.prototype);
- // Func { name="Sean", getInfo=function()}
this总是指向函数的直接调用者(而非间接调用者);
如果有new关键字,this指向new出来的那个对象;
在事件中,this指向触发这个事件的对象,特殊的是,IE中的attachEvent中的this总是指向全局对象Window;
null 表示一个对象是“没有值”的值,也就是值为“空”;
undefined 表示一个变量声明了没有初始化(赋值);undefined不是一个有效的JSON,而null是;
undefined的类型(typeof)是undefined;
null的类型(typeof)是object;
Javascript将未赋值的变量默认值设为undefined;
Javascript从来不会将变量设为null。它是用来让程序员表明某个用var声明的变量时没有值的。
深拷贝和浅拷贝是只针对Object和Array这样的引用数据类型的
浅拷贝只复制指向某个对象的指针而不复制对象本身,新旧对象还是共享同一块内存。
但深拷贝会另外创造一个一模一样的对象,新对象跟原对象不共享内存,修改新对象不会改到原对象
深拷贝方法:
JSON.parse(JSON.stringify(obj))//深拷贝对象
原理: 用JSON.stringify将对象转成JSON字符串,再用JSON.parse()把字符串解析成对象,一去一来,新的对象产生了,而且对象会开辟新的栈,实现深拷贝。
递归方法实现深度克隆原理:遍历对象、数组直到里边都是基本数据类型,然后再去复制,就是深度拷贝
1、使用Object.keys(),Object.values()遍历 (返回一个数组,包括对象自身的(不含继承的)所有可枚举属性(不含Symbol属性)).
- Object.keys(obj).forEach(key=>{
- console.log(key, obj[key])
- })
2、for … in 、for-of循环遍历对象自身的和继承的可枚举属性(含继承)(不含Symbol属性)
- for(var i in obj){
- console.log(i,obj[i])
- }
3、Object.getOwnPropertyNames() (比上面多了不可枚举)
4、Reflect.ownKeys 包含所有的(自身+继承的)(含Symbol属性)
(1)为什么要防抖?
高频的函数操作可能产生不好的影响
如:resize、scroll、mousedown、mousemove、keyup、keydown……
这种在一瞬间(短时间内)对浏览器或服务器造成了过多压力的交互就需要进行优化了,为了解决这个问题,一般有两种解决方案:
debounce 防抖
throttle 节流
(2)目的:降低一个函数的触发频率,以提高性能或避免资源浪费
(3)防抖的原理就是:你尽管触发事件,但是我一定在事件触发n秒无操作后
才执行。
- function debounce(func, wait) {
- var timer;
- return function () {
- clearTimeout(timer)
- timer = setTimeout(func, wait);
- }
- }
(4)节流的原理很简单:如果你持续触发某个事件,特定的时间间隔内,只执行一次。
闭包就是能够读取其他函数内部变量的函数,在本质上是函数内部和函数外部链接的桥梁
- function foo(params) {
- var a = 'gaoyuan';
-
- function bar() {
- console.log(a);
- }
- return bar;
- }
-
- var res = foo();
- res(); // 高原
闭包轻松解决的经典问题:
- var arr = []
- for(var i = 0; i < 10; i++){
- arr[i] = function () {
- console.log(i)
- }
- }
- arr[0](); // 10
- arr[1](); // 10
- arr[2](); // 10
- arr[3](); // 10
-
- // 同一个上下文中创建的闭包是共用一个[[Scope]]属性的。
- // 因此上层上下文中的变量`i`是可以很容易就被改变的
-
- // 利用闭包来解决
- var arr = []
- for(var i = 0; i < 10; i++){
- arr[i] = (function (i) {
- return function () {
- console.log(i);
- }
- })(i)
- }
- arr[0](); // 0
- arr[1](); // 1
- arr[2](); // 2
- arr[3](); // 3
-
- //通过立即执行匿名函数的方式隔离了作用域,当执行 arr[0] 函数的时候,arr[0] 函数的作用域链发生了改变
-
分成:结构层、表示层、行为层。
结构层(structural layer)
由 HTML 或 XHTML之类的标记语言负责创建。标签,也就是那些出现在尖括号里的单词,对网页内容的语义含义做出了描述,但这些标签不包含任何关于如何显示有关内容的信息。例如,P标签表达了这样一种语义:“这是一个文本段。”
表示层(presentation layer)
由 CSS 负责创建。 CSS对“如何显示有关内容”的问题做出了回答。
行为层(behaviorlayer)
负责回答“内容应该如何对事件做出反应”这一问题。这是 Javascript 语言和 DOM主宰的领域。
TCP协议在传输层,IP协议在网络层,HTTP协议在应用层。
1.服务器角度
采取CDN加速 开启gzip压缩 允许使用强缓存或协商缓存 增加服务器带宽
2.客户端角度
合理组织CSS、JavaScript代码位置 减少DOM操作、添加事件委托 部分操作可设置防抖和节流 对于可预见的操作采取preload或prerender的预加载 对于图片可以懒加载 合并CSS图片(精灵图/雪碧图) 减少使用iframe 资源优化打包角度
3.资源优化打包角度
使用打包工具将Js文件、CSS文件和静态文件进行恰当打包处理。
跨域问题来自于浏览器的同源策略,即当协议、域名、端口号任意一个不同时,都会引发跨域问题。
jsonp、CORS可以用来解决跨域问题
宏任务是由宿主发起的,而微任务由JavaScript自身发起。
在ES3以及以前的版本中,JavaScript本身没有发起异步请求的能力,也就没有微任务的存在。在ES5之后,JavaScript引入了Promise
,这样,不需要浏览器,JavaScript引擎自身也能够发起异步任务了。
所以,总结一下,两者区别为:
宏任务(macrotask) | 微任务(microtask) | |
---|---|---|
谁发 起的 | 宿主(Node、浏览器) | JS引擎 |
具体事件 | 1. script (可以理解为外层同步代码) 2. setTimeout/setInterval 3. UI rendering/UI事件 4. postMessage,MessageChannel 5. setImmediate,I/O(Node.js) | 1. Promise 2. MutaionObserver 3. Object.observe(已废弃;Proxy 对象替代) 4. process.nextTick(Node.js) |
谁先运行 | 后运行 | 先运行 |
会触发新一轮Tick吗 | 会 | 不会 |
其中比较注意的是promise的内部既包含宏任务也包含微任务,promise内部执行为宏任务,then执行为微任务
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。