Vue
目录
vue-router 是什么?它有哪些组件vue用来写路由一个插件。router-link、router-view
Proxy 与 Object.defineProperty 优劣对比(vue3.0使用的就是porxy)
Set、map数组去重,new Set的数组去重和自己实现的哪个性能会更好
splice和slice、map和forEach、 filter()、reduce()的区别
setTimeout、Promise、Async/Await 的区别
Cookie,sessionstorage,localstorage区别
------怎么判断用户访问网页过程中是否还处于登录阶段:(后台————》因为都是表单提交)
----难点3---前端处理高并发数据 ,12306 这种,项目中没有设计过多,但是有去看过相关资料站
vue初始化页面闪动问题
在css里加上以下代码
[v-cloak] { display: none;}
router-link上事件无效解决方法
原因:router-link会阻止click事件,.native指直接监听一个原生事件
!!!vue项目中的性能优化
一、代码层优化
1,v-if 与v-show
2,computed 与watch
Computed是计算属性,依赖其他属性值,具有缓存。只有依赖属性发生改变,才会重新计算。
Watch为监听,每当数据变化都会执行回调
3, v-for循环加上key,方便内部机制精准找到该条数据。
4,长列表优化
使用object.freeze来冻结一个对象,一旦被冻结就不能再被修改
5,事件销毁
Vue组件销毁时,会自动清理它与其他实例的连接。如果js内使用addeventListener等方式是不会自动销毁的,需要在组件中手动销毁,避免内存泄漏
6,图片懒加载
可以使用插件 vue-lazyload插件,在main中全局引入,并注册,添加自定义选项,在组件中使用v-lazy属性标签
7,路由懒加载
Vue是单页应用,会引入很多路由,使用懒加载方式
8,第三方插件按需引入
借助babel-plugin-component,减少项目体积
二、webpack层面优化
1,图片进行压缩
在webpack.base.conf.js中url-loader中设置limit大小来对图片处理,小于limit图片转化为base64格式
2,减少es6转为es5
3,提取公共代码
三、基础web技术优化
1,开启gzip压缩
2,浏览器缓存
3,CDN使用
!!!前端如何优化网站性能
1,减少HTTP请求数据
2,控制资源文件加载优先级
3,利用浏览器缓存
4,减少重排
5,减少DOM操作
!!!vue与react区别
1,react整体是函数式的思想,把组件设计成纯组件,状态和逻辑通过参数传入,所以在react中,是单向数据流;
2,vue的思想是响应式的,也就是基于是数据可变的,通过对每一个属性建立Watcher来监听,当属性变化的时候,响应式的更新对应的虚拟dom。
3,vue表单可以使用v-model支持双向绑定,相比于react来说开发更简单。
4,改变数据的方式不同。react需要通过setState
5,react使用jsx,有一定的上手成本,并且需要一整套工具链支持。vue使用模版语法,完全脱离工具链。
vue常见兼容问题
babel-polyfill插件
浏览器默认的margin和padding不同。 解决方案是加一个全局的*{margin:0;padding:0;}来统一。
IE6双边距bug:块属性标签float后,又有横行的margin情况下,在ie6显示margin比设置的大。
浮动ie产生的双倍距离(IE6双边距问题:在IE6下,如果对元素设置了浮动,同时又设置了margin-left或margin-right,margin值会加倍。) #box{ float:left; width:10px; margin:0 0 0 100px;}
组件传值
父传子
通过props传递
子传父
在父组件中给子组件绑定一个自定义的事件,子组件通过$emit()触发该事件并传值
父组件通过$on接收
兄弟组件传值
通过vuex
Bus
vue如何获取dom
先给标签设置一个ref值,再通过this.$refs.你设置的名字
1,标签上之间写ref数据,设置默认字符串 通过 this.$refs.xxx
2.还有就是回调 ref = {(ref)=>this.xxx= ref} 通过this.xxx
v-on可以监听多个方法
assets和static的区别
这两个都是用来存放项目中所使用的静态资源文件。
两者的区别:
assets中的文件在运行npm run build的时候会打包,简单来说就是会被压缩体积,代码格式化之类的。打包之后也会放到static中。
static中的文件则不会被打包。
封装 vue 组件的过程
首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决:效率低、难维护、复用性等问题。
然后,使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。
vue.js的templete模版
先转化成AST树,再得到的render函数返回(Vue的虚拟DOM节点)
步骤:
首先,通过compile编译器把template编译成AST语法树(abstract syntax tree 即 源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创建编译器的。另外compile还负责合并option。
然后,AST会经过generate(将AST语法树转化成render funtion字符串的过程)得到render函数,render的返回值是ue的虚拟DOM节点,
问题-----数据不响应(对象)(数组)
原因:vue内部数据响应是通过object.definePrototype监听对象的每一个键的getter,setter方法来实现的,但这种方法只能监听到已有的属性,新增的数据是无法监听到的
解决:
1,可以将新增的属性提前在data中定义好,比如(message里面定义好属性)
2,直接替换到message,因为无法在message里面添加新的属性,因为message已经定义好了,那么可以之间修改message的值就可以了。 写法的话是通过扩展运算符复制到新的对象里面,将新增的属性也加上即可。
3,使用vue.set 他是vue官方提供的解决新增属性无法触发数据响应,视图更新的一种解决方法。
可以直接在方法中写入 vue.set(this.message,'属性名','属性值')。
为了简化写法,官方又将set方法挂载到原型上 Vue.prototype.$set = Vue.set,所以就直接使用 this.$set 来替换vue.set
应用场景的话,其实只有当你要赋值的属性还没有定义的时候需要使用vue.set,其他的时候一般不需要
原因:
vue不能检测到以下数组的变动
1,利用索引去直接修改 --> this.list[index] = newValue
2,修改数组的length长度属性 -》this.list.length = 0
解决:
1,可以通过vue.$set(this.list,0,'王武')
2,vue针对数组提供了数组变异方法,比如 push、pop、splice等一些操作数组的方法
在vue中可以直接使用这些方法,可以修改数组的值来触发数据响应。
如 --》 this.list.splice(0,1,'王武')
实际上,vue仅仅依赖getter、setter是无法做到数组调用push、pop这些放的,因为vue也是通过劫持这些方法,对这些方法进行包装变异来实现的。
过滤器filter,
比如需要将时间戳修改显示为 ‘yyyy-MM-DD HH:mm:ss’
一般的话需要使用插件moment去格式化这个时间戳来实现这样的效果。
vue自带了一个过滤器来简化操作。
(在export default 里面之间写 )
filters:{ formatDate(value){ return format(value,'yyy-MM-DD HH:mm:ss') } }
注册全局过滤器
在项目目录下新建filters
// filters\index.js
import Vue from 'vue'
import { format } from '@/utils/date'
Vue.filter('formatDate', value => {
return format(value, 'yyyy-MM-DD HH:mm:ss')
})
将这个文件引入main。js即可,在其他组件里直接使用
nexttick
Vue在更新DOM的时候是异步的,只要侦听到数据的变化,并缓存在同一事件循环中,等待事件循环中的所有的数据变化完成后,统一更新视图,未来得到最新的DOM所以设置 nextTick()
nextTick 是将这个回调函数延迟在下一次DOM更新数据后调用,DOM重新渲染后自动执行该函数
MVVM
MVVM全称是Model-View-ViewModel
Vue是以数据为驱动的,Vue自身将DOM和数据进行绑定,一旦创建绑定,DOM和数据将保持同步,每当数据发生变化,DOM会跟着变化。 ViewModel是Vue的核心,它是Vue的一个实例。
DOMListeners和DataBindings是实现双向绑定的关键。DOMListeners监听页面所有View层DOM元素的变化,当发生变化,Model层的数据随之变化;DataBindings监听Model层的数据,当数据发生变化,View层的DOM元素随之变化。
生命周期钩子函数?
created: 实例已经创建完成之后调用,在这一步,实例已经完成数据观测, 属性和方法的运算, watch/event事件回调. 然而, 挂载阶段还没有开始, $el属性目前还不可见
mounted: el被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
activated::keep-alive组件激活时调用
vue的生命周期主要分为几个简单,数据初始化,dom挂载,数据更新,组件卸载,在一个就是开启了组件缓存的时候,会有组件启用和组件停用阶段,每个阶段都有前后两个钩子除了缓存的那俩
--------------------
数据初始化阶段
beforeCreate:在实例初始化之后,数据观测 (data observer) 和 event/watcher 事件配置之前被调用。
created:实例已经创建完成之后被调用。在这一步,实例已完成以下的配置:数据观测 (data observer),属性和方法的运算,watch/event 事件回调。然而,挂载阶段还没开始,$el 属性目前不可见。
dom挂载阶段
beforeMount:在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted:el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用该钩子。如果 root 实例挂载了一个文档内元素,当 mounted 被调用时 vm.$el 也在文档内。
mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
数据跟新阶段
beforeUpdate:数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁之前。
updated:由于数据更改导致的虚拟 DOM 重新渲染和打补丁,在这之后会调用该钩子。
当这个钩子被调用时,组件 DOM 已经更新,所以你现在可以执行依赖于 DOM 的操作。然而在大多数情况下,你应该避免在此期间更改状态。如果要相应状态改变,通常最好使用计算属性或 watcher 取而代之。
updated 不会承诺所有的子组件也都一起被重绘。如果你希望等到整个视图都重绘完毕,可以用 vm.$nextTick 替换掉 updated:
缓存启用的时候会有下面两个钩子
activated:keep-alive 组件激活时调用。
deactivated:keep-alive 组件停用时调用。
组件卸载的时候:
beforeDestroy:实例销毁之前调用。在这一步,实例仍然完全可用。
destroyed:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
第一次页面加载会触发哪几个钩子
beforeCreate, created, beforeMount, mounted
vue-loader是什么?
vue文件的一个加载器,跟template/js/style转换成js模块。
vue-router 是什么?它有哪些组件
vue用来写路由一个插件。router-link、router-view
vue-router的两种模式
hash模式: 即地址栏 URL 中的 # 符号;hash虽然出现在url中,但是不会被包括在http请求中。
history模式:利用了 HTML5 History Interface 中新增的 pushState() 和 replaceState() 方法。
问题:404 的情况下,需要重新向后端发送请求,如果后端没有配置的对应路由处理,就会返回404.一般情况下都是在后端进行配置,将所有路由请求执行index。Html
双向绑定的原理
采用数据劫持结合发布者-订阅者模式的方式,通过Object.defineProperty()来劫持各个属性的setter,getter,在数据变动时发布消息给订阅者,触发相应的监听回调。
具体话其实就是通过Obeject.defineProperty() 中的setter和getter来监听属性变动实现Observer进行数据的监听然后就是通知订阅者,那么订阅者其实就是简单的一个数组,这个数组中的内容就是我门使用了的一个数据的集合,使用了的数据可以通过getter得到,其实就是在调用的时候给数组里面添加一个订阅者这样就是实现了一个Watcher(需要监听的数据的集合),然后在实现一个Compile其作用就是解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图,
其实vue的数据双向绑定就是MVVM作为数据绑定的入口,整合Observer、Compile和Watcher三者,通过Observer来监听自己的model数据变化,通过Compile来解析编译模板指令,最终利用Watcher搭起Observer和Compile之间的通信桥梁,达到数据变化 -> 视图更新;视图交互变化(input) -> 数据model变更的双向绑定效果。
data必须是一个函数
对象为引用类型,当复用组件时,由于数据对象都是指向同一个data对象,当在一个组件中修改data时,其他重用的组件中的data会同时被修改,而使用返回对象的函数,由于每一返回的都是一个新对象,引用地址不同,则不会出现这个问题。
Watch、computed、methods区别
Watch是做单一的数据监听,computed是计算属性,将计算的值进行缓存、methods是操作方法
comuted,支持缓存,只有依赖发生改变,才会重新计算,不支持异步
watch,不支持缓存,数据发生改变,会直接触发响应的操作,支持异步
接受两个参数,第一个是最新的值,第二个是输入之前的值
vue.extend和vue.component
- extend 是构造一个组件的语法器。 然后这个组件你可以作用到Vue.component这个全局注册方法里 还可以在任意vue模板里使用组件。 也可以作用到vue实例或者某个组件中的components属性中并在内部使用apple组件。
- Vue.component 你可以创建 ,也可以取组件。
v-show和v-if
v-show指令是通过修改元素的displayCSS属性让其显示或者隐藏
v-if指令是直接销毁和重建DOM达到让元素显示和隐藏的效果
keep-alive
<keep-alive></keep-alive> 包裹动态组件时,会缓存不活动的组件实例,主要用于保留组件状态或避免重新渲染。
比如有一个列表和一个详情,那么用户就会经常执行打开详情=>返回列表=>打开详情…这样的话列表和详情都是一个频率很高的页面,那么就可以对列表组件使用<keep-alive></keep-alive>进行缓存,这样用户每次返回列表的时候,都能从缓存中快速渲染,而不是重新渲染
Vuex
Vuex可以被看作项目中所有组件的数据中心,我们将所有组件中共享的State抽离出来,任何组件都可以访问和操作我们的数据中心.
· state中保存着共有数据
· 改变state中的数据有且只有通过mutations中的方法,且mutations中的方法必须是同步的
· 如果要写异步的方法,需要些在actions中, 并通过commit到mutations中进行state中数据的更改.
vuex有哪几种属性?
有五种,分别是 State、 Getter、Mutation 、Action、 Module
state => 基本数据(数据源存放地)
getters => 从基本数据派生出来的数据
mutations => 提交更改数据的方法,同步!
actions => 像一个装饰器,包裹mutations,使之可以异步。
modules => 模块化Vuex
通过mapAction异步提交事件到action。action通过commit提交到mutation。mutation会修改state中的值。 最后通过getter把对应值抛出去,在页面的计算属性中通过mapGetter来动态获取state中的值
为什么要在action提交异步
同步的意义在于这样每一个 mutation 执行完成后都可以对应到一个新的状态
vue-router 有哪几种导航钩子
- 全局导航钩子:作用:跳转前进行判断拦截。
2.组件内的钩子;
3.单独路由独享组件
*全局导航钩子
router.beforeEach(to,from,next);
router.beforeResolve(to,from,next);
router.afterEach(to,from,next);
*组件内钩子
beforeRouteEnter
beforeRouteUpdate
beforeRouteLeave
*单独路由独享组件
beforeEnter
{ to(去的那个路由)、from(离开的路由)、next(一定要用这个函数才能去到下一个路由,如果不用就拦截 }
vue中key的作用
为了保证遍历同级元素的唯一性,用来提高更新dom的性能,从原来上来说就是通过key来判断元素是否需要重新渲染,key的唯一性保证了元素的唯一性,key的作用就是更新组件的时候判断两个阶段是否相同,相同就复用,不相同就删除旧的创建新的。
SPA应用
单页面应用,仅在该Web页面初始化时加载相应的HTML、JavaScript、CSS。一旦页面加载完成,SPA不会因为用户的操作而进行页面的重新加载或跳转。
SSR
SSR也就是服务端渲染,也就是将Vue在客户端把标签渲染成HTML的工作放在服务端完成,然后再把html直接返回给客户端。
SSR有着更好的SEO、并且首屏加载速度更快等优点。不过它也有一些缺点,比如我们的开发条件会受到限制,服务器端渲染只支持beforeCreate和created两个钩子,当我们需要一些外部扩展库时需要特殊处理,服务端渲染应用程序也需要处于Node.js的运行环境。还有就是服务器会有更大的负载需求。
Vue2.x响应式数据原理
Vue在初始化数据时,会使用Object.defineProperty重新定义data中的所有属性,当页面使用对应属性时,首先会进行依赖收集(收集当前组件的watcher)如果属性发生变化会通知相关依赖进行更新操作(发布订阅)。
Vue3.x响应式数据原理
Vue3.x改用Proxy替代Object.defineProperty。因为Proxy可以直接监听对象和数组的变化,并且有多达13种拦截方法。并且作为新标准将受到浏览器厂商重点持续的性能优化。
vue 2.0 与3.0 区别
2.0使用Object.defineProperty重新定义data中的所有属性,当页面中使用对应属性时,会进行依赖手机,如果发生变化,对依赖进行更新
3.0使用proxy替换,可以直接监听对象数组的变化。
Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改
Proxy 与 Object.defineProperty 优劣对比(vue3.0使用的就是porxy)
Proxy 的优势如下:
Proxy 可以直接监听对象而非属性;
Proxy 可以直接监听数组的变化;
Proxy 有多达 13 种拦截方法,不限于 apply、ownKeys、deleteProperty、has 等等是 Object.defineProperty 不具备的;
Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;
Object.defineProperty 的优势如下:
兼容性好,支持 IE9,
而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平
,因此 Vue 的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。
JS
Object.assign(),一般用与浅拷贝。
Object.create() ,方法创建一个新对象,使用现有的对象来提供新创建的对象的proto。
Axios和ajax区别
区别:axios是通过Promise实现对ajax技术的一种封装,就像jquery对ajax的封装一样,
简单来说就是ajax技术实现了局部数据的刷新,axios实现了对ajax的封装,axios有的ajax都有,ajax有的axios不一定有,总结一句话就是axios是ajax,ajax不止axios
优缺点:
ajax:
1、本身是针对MVC编程,不符合前端MVVM的浪潮
2、基于原生XHR开发,XHR本身的架构不清晰,已经有了fetch的替代方案,jquery整个项目太大,单纯使用ajax却要引入整个jquery非常不合理(采取个性化打包方案又不能享受cdn服务)
3、ajax不支持浏览器的back按钮
4、安全问题ajax暴露了与服务器交互的细节
5、对搜索引擎的支持比较弱
6、破坏程序的异常机制
7、不容易调试
axios:
1、从node.js创建http请求
2、支持Promise API
3、客户端防止CSRF(网站恶意利用)
4、提供了一些并发请求的接口
什么是重绘?回流(重排)
重绘:当渲染树中的元素外观(比如颜色 )发生改变,不影响布局,产生重绘
回流:当渲染树元素的布局(尺寸,位置)发送改变,产生重绘回流。
因为浏览器需要通过回流计算最新值回流必将引起重绘,但重绘不一定引起回流。
最小化重绘和回流?
需要对元素进行复杂的操作时候,可以先隐藏(display:none),操作完后再显示需要创建多个dom节点。
for in 、for of、for each
for in 一般常用来遍历对象或json
for of数组对象都可以遍历,遍历对象需要通过和Object.keys()
for in循环出的是key,for of循环出的是value
Amd/cmd规范区别
Amd提前执行依赖,尽早执行,cmd按需执行依赖,懒执行。
http与https的区别
http是超文本传输协议,信息是明文传输,https则是具有安全性的ssl/tls加密传输协议。
http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443
http协议
- 超文本的传输协议,
- 基于TCP/IP通信协议来传递数据(HTML,图片资源)
- 基于运用层的面向对象的协议,由于其简洁、快速的方法、适用于分布式超媒体信息系统
- 4.http请求信息request: 请求行(request line)、请求头部(header),空行和请求数据四部分构成 请求行,用来说明请求类型,要访问的资源以及所使用的HTTP版本. 请求头部,用来说明服务器要使用的附加信息 空行,请求头部后面的空行是必须的 请求数据也叫主体,可以添加任意的其他数据。
- 5.http相应信息Response 状态行、消息报头、空行和响应正文 状态行,由HTTP协议版本号, 状态码, 状态消息 三部分组成 消息报头,用来说明客户端要使用的一些附加信息 空行,消息报头后面的空行是必须的 响应正文,服务器返回给客户端的文本信息。
对prototype和proto的理解
对象、函数都会有_proto_这个属性,对象并不具有prototype属性,只有函数才有prototype属性
import和require的区别
require 是赋值过程并且是运行时才执行,
import 是解构过程并且是编译时执行。
import必须写在文件的顶部引入。require的性能相对于import稍低,因为require是在运行时才引入模块,而import只需要依据import中的接口在编译时引入指定模块
Set、map数组去重,new Set的数组去重和自己实现的哪个性能会更好
Set是一种新的数据结构。它类似于数组,但是成员的值都是唯一的,没有重复的值。
Set本身是一个构造函数,用来生成Set数据结构。
查找元素、删除元素、插入元素速度更快js中的数据类型
2. 利用for循环嵌套for循环,然后splice去重
3. 利用indexof去重
4. 利用includes去重
5. 利用reduce+includes arr.reduce((prev,cur) => prev.includes(cur) ? prev : [...prev, cur], [])
应用场景Set用于数据重组,Map用于数据储存Set:
(1)成员不能重复
(2)只有键值没有键名,类似数组
(3)可以遍历,方法有add, dee,has
Map:
(1)本质上是健值对的集合,类似集合
(2)可以遍历,可以跟各种数据格式转换
例子
let s = newSet();s.add([1]);s.add([1]);console.log(s.size);
答案:2
两个数组[1]并不是同一个值,它们分别定义的数组,在内存中分别对应着不同的存储地址,因此并不是相同的值都能存储到Set结构中,所以size为2
数组统计次数
- 最简单的就是for循环
- Reduce函数接受四个参数
初始值(或者上一次回调函数的返回值),当前元素值,当前索引,调用 reduce 的数组。
对上一次的数值进行累计,当然最简单的就是我们常用的数组求和,求乘积了。
reduce的高级用法
1,计算数组中每个元素出现的次数
- 数组去重
- 将二维数组转化为一维
- 将多维数组转化为一维
- 对象里的属性求和
map和forEach有何区别
foreEach()方法:
针对每一个元素执行提供的函数。
map()方法:
创建一个新的数组,其中每一个元素由调用数组中的每一个元素执行提供的函数得来。
区别
forEach()方法不会返回执行结果,而是undefined。也就是说,forEach()会修改原来的数组。而map()方法会得到一个新的数组并返回。
ES6之rest参数和拓展运算符
用于获取函数的多余参数,这样就不需要使用arguments对象了。rest参数搭配的变量是一个数组,该变量将多余的参数放入其中。
比如一个函数实参传【1,2,3,4,5】 ,那么形参可以使用a,...rest这样的接受,那么a就为1,rest就是剩下的2,3,45
基本类型:
number string boolean null undefined symbol bigint
引用数据类型:object (包含,Date,RegExp,Function,Array,Math..)
symbol
symbol是基本类型之一,symbols 是一种无法被重建的基本类型。
类型判断
Array.isArray()
JavaScript数据类型检测的四种方式
1. typeof
返回值是字符串,
有”number”,”boolean”,”string”,”undefined”,”function”,”object
局限性: 不能区分数组,对象,正则,因为返回的都是”object”
2. instanceof 检测一个实例是否属于某个类
Object.prototype.toString.call() 最全面的方式
首先获取Object原型上的toString方法,让方法执行,并且改变方法中的this指向
Object.prototype.toString 返回当前方法的执行主体(this)所属类
toString
toString方法不仅仅是转换为字符串
Object.prototype.toString 不是用来转换为字符串的
typeof对于基本类型(除了Null)是可以检测到的,但是引用类型就统一返回object
instance of 用于检测构造函数的原型是否出现在某个实例函数的原型链上
Typeof
Indexof
instanceof
prototype.toString.call() 最准确最常用
**函数类型**Function fn(){
console.log(“test”);
}
Object.prototype.toString.call(fn); // "[object Function]"
**数组类型**
var arr = [1,2,3];
Object.prototype.toString.call(arr); // "[object Array]"
会返回一个形如 "[object XXX]" 的字符串。
splice和slice、map和forEach、 filter()、reduce()的区别
- slice(start,end):方法可以从已有数组中返回选定的元素,返回一个新数组, 包含从start到end(不包含该元素)的数组方法 注意:该方法不会更新原数组,而是返回一个子数组
- splice():该方法从数组中添加或删除项目,返回被删除的项目。(该方法会改变原数组)
splice(index, howmany,item1,...itemx) ·index参数:必须,整数规定添加或删除的位置,使用负数,从数组尾部规定位置 ·howmany参数:必须,要删除的数量, ·item1..itemx:可选,向数组添加新项目
3.map():会返回一个全新的数组。使用于改变数据值的时候。会分配内存存储空间数组并返回,forEach()不会返回数据
4.forEach(): 不会返回任何有价值的东西,并且不打算改变数据,单纯的只是想用数据做一些事情,他允许callback更改原始数组的元素 5.reduce(): 方法接收一个函数作为累加器,数组中的每一个值(从左到右)开始缩减,最终计算一个值,不会改变原数组的值 6.filter(): 方法创建一个新数组,新数组中的元素是通过检查指定数组中符合条件的所有元素。它里面通过function去做处理
浅拷贝和深拷贝
数据类型分为基本数据类型和引用数据类型,
基本数据类型存储在栈中,引用数据类型存储在堆中,引用数据类型在栈中存储了指针,指向堆中地址。
浅拷贝只是赋值了内存地址,如果地址改变,会跟着改变。 object.assign()
深拷贝开辟一块新的内存地址。,深拷贝,是拷贝对象各个层级的属性
复杂深拷贝(对象或者数组)
1.使用JSON对象的stringify和parse方法
2.使用递归
function deep(obj) {
//判断拷贝的要进行深拷贝的是数组还是对象,是数组的话进行数组拷贝,对象的话进行对象拷贝
var objClone = Array.isArray(obj) ? [] : {};
//进行深拷贝的不能为空,并且是对象或者是
if (obj && typeof obj === "object") {
for (key in obj) {
if (obj.hasOwnProperty(key)) {
if (obj[key] && typeof obj[key] === "object") {
objClone[key] = deep(obj[key]);
} else {
objClone[key] = obj[key];
}
}
}
}
return objClone;}
DOM事件流和事件委托
DOM事件流分为三个阶段:
- 捕获阶段
- 目标阶段
- 冒泡阶段
事件流描述的是从页面中接受事件的顺序,IE和网景推出了两个正好相反的概念,IE推出的是冒泡流,从下到上,网景则是事件捕获流,从上到下。
可以通过addEventListener方法给元素添加点击事件,前两个参数分别是点击事件的名称和执行的回调,第三个参数就是是否开启捕获,确定事件发生的阶段,默认是false,也就是冒泡流。
事件代理
利用事件的冒泡原理来实现,通过给祖先元素添加事件,通过事件目标对象开始向上查找,找到匹配的子节点为止,找不到则绑定事件到祖先元素,找到就触发事件
原型链
每一个函数都有一个prototype的属性,当他作为构造函数的时候,它实例化出来的函数会有一个_proto_的属性,它执行构造函数的prototype。
函数通过prototype来访问其父元素的属性和方法,找不到一次往下找,构成原型链,直到Object的原型为止。
访问某个属性或方法的时候,会先从当前对象中查找,没有的话就顺着原型链开始寻找,直到找到最顶端,也就是Object的原型(null)为止。
另外每一个原型上都有一个constructor属性,指向相关联的构造函数
面向对象
三大特性:继承,多态,封装
封装
把客观的失误封装成抽象的类,可以把自己的数据和方法只让可信的类或对象去操作。不可信的隐藏
继承
简历一个新的派生,
多态
同一操作作用与不同类的实例,将产生不同的执行结果。收到同样的信息,回馈不同的结果。
js继承
通过构造函数继承 ,使用call apply这个两个方法可以改变this指向
通过原型链继承 prototype
组合继承
将原型链和构造函数组合一起。 思路是使用原型链实现对原型方法的继承,通过借用构造函数来实现对实例属性的继承。既可以在原型上定义方法实现函数复用,又能保证每个实例都有他自己的属性
使用组合继承避免了原型链和借用构造函数的缺点,融合优点,是最常用的继承模式
比如:
Function admin( name ) {
This.name =name
This,colors = [‘red’,’blue’,’green’]
}
Admin.prototype.sayname = ()=>{
Alert(this.name)
}
Function myfn( name,age ){
//继承 借用构造函数继承实例的属性
Admin.call (this,name)
This.age= age
}
//原型链继承
Admin.prototype = new admin()
Admin.prototype.constructor=admin
Admin.prototype.sayage=()=>{ alert(this.age)}
class里面super是干嘛的
super()执行父类的构造函数
super() 返回的是子类的实例
new操作符都做了些什么
- 创建一个空对象
- 将空对象的proto属性指向构造函数的原型
- 将this指向这个对象
- 返回这个对象
闭包
闭包是指有权访问另一个函数作用域中变量的函数,主要是以函数套函数的形式,
内部函数可以引用外层的参数和变量,参数不会被垃圾回收机制回收
为什么要使用闭包 在全局定义变量和局部定义变量
全局变量:可以重用、但是会造成全局污染而且容易被篡改。
局部变量:仅函数内使用不会造成全局污染也不会被篡改、不可以重用。如果不使用的话,将值设为null即可
所以,全局变量和局部变量的优缺点刚好相对。闭包的出现正好结合了全局变量和局部变量的优点。
问题---什么是垃圾
没有被引用的对象就是垃圾,就是要被清除的,(有个例外---》如果几个对象引用形成一个环,互相引用,但根访问不到他们,这几个对象也是垃圾)
闭包的危害:
因为闭包会将内部变量储存在内存中,如果长时间不清除的话会造成内存泄漏,影响程序的性能
解决方法: 对于不使用的变量及时清除
垃圾回收机制
标记清除法
当变量进入执行环境的时候,垃圾回收器将其标记为“进入环境”,当变量离开环境的时候,标记为“离开环境”
引用计数法
是跟踪记录每个值被使用的次数,当这个值引用次数为0时候,说明没有变量在使用,这个值就没法被访问,因此可以回收
ES6
1)let声明变量和const声明常量
2)箭头函数ES6中的函数定义不再使用关键字function(),而是利用了()=>来进行定义
3)模板字符串模板字符串是增强版的字符串,用反引号(`)标识,可以当作普通字符串使用,也可以用来定义多行字符串
4)解构赋值ES6 允许按照一定模式,从数组和对象中提取值,对变量进行赋值
5)for of循环for...of循环可以遍历数组、Set和Map结构、某些类似数组的对象、对象,以及字符串
6)import、export导入导出ES6标准中,Js原生支持模块(module)。将JS代码分割成不同功能的小块进行模块化,将不同功能的代码分别写在不同文件中,各模块只需导出公共接口部分,然后通过模块的导入的方式可以在其他地方使用
7)set数据结构Set数据结构,类似数组。所有的数据都是唯一的,没有重复的值。它本身是一个构造函数
8)... 展开运算符可以将数组或对象里面的值展开;还可以将多个值收集为一个变量
9)修饰器 @decorator是一个函数,用来修改类甚至于是方法的行为。修饰器本质就是编译时执行的函数
10)class 类的继承ES6中不再像ES5一样使用原型链实现继承,而是引入Class这个概念11)async、await使用 async/await, 搭配promise,可以通过编写形似同步的代码来处理异步流程, 提高代码的简洁性和可读性async 用于申明一个 function 是异步的,而 await 用于等待一个异步方法执行完成
12)Promise是异步编程的一种解决方案
13)SymbolSymbol是一种基本类型。Symbol 通过调用symbol函数产生,它接收一个可选的名字参数,该函数返回的symbol是唯一的
14)Proxy代理使用代理(Proxy)监听对象的操作,然后可以做一些相应事情
Class
定义“类”的方法的时候,不需要加上function这个关键字,直接把函数定义放进去了就可以了。另外,方法之间不需要逗号分隔,加了会报错。
1,类的数据类型就是函数,类本身就指向构造函数
2,类的所有方法都定义在类的prototype属性上面
3, Object.assign方法可以很方便地一次向类添加多个方法。
4,类的内部所有定义的方法,都是不可枚举的
constructor方法
(1)constructor方法是类的默认方法,通过new命令生成对象实例时,自动调用该方法。一个类必须有constructor方法,如果没有显式定义,一个空的constructor方法会被默认添加。
(2) constructor方法默认返回实例对象(即this),完全可以指定返回另外一个对象
(3) 类必须使用new调用,否则会报错。这是它跟普通构造函数的一个主要区别,后者不用new也可以执行。
不存在变量提升:(class定义变量时)
箭头函数
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this,另外箭头函数里也不能使用call\apply\bind修改this的指向
箭头函数相当于匿名函数,是不能作为构造函数的,不能被new 。没有arguments实参集合,取而代之用...剩余运算符解决 。没有自己的this。他的this是继承当前上下文中的this 。没有函数原型 。不能当做Generator函数,不能使用yield关键字 不能使用call、apply、bind改变箭头函数中this指向 Set数据结构,数组去重
this的指向
- 在对象的方法中使用,this指向当前的对象
- 在独立的函数中使用
在严格模式下,this指向undefined
非严格模式下,this指向全局对象,比如window
通过call\apply\bind来指定
都可以改变this指向,区别就是call\apply 改变的同时执行函数,bind不执行,而是返回这个函数
call\apply 第一个参数就是要改变的this的值,区别就是call传入的是参数列表,apply传入的是参数数组
- 构造函数
如果一个函数是构造函数,那么this就指向它实例化出来的对象
- 箭头函数
箭头函数不会创建自己的this,它只会从自己的作用域链的上一层继承this,另外箭头函数里也不能使用call\apply\bind修改this的指向线程接着执行之后的代码,等到I/O结束后,event loop线程再把运行结果交给主线程,然后主线程再执行相应的回调,整个任务结束。
Js底层原理
js是单线程语言,意思就是JS引擎一次只能处理一件事情,如果有多件事情需要处理,那么JS引擎会一件一件的来
同步异步事件
同步就是马上就能完成的事情,异步就是一时半会不能完成的事情,就像打开课本,这就是一个同步事件,马上就能做到,再看水壶烧水,这就是一个异步事件,因为你不能控制水烧开,只能等待水被烧开,对比一下,异步事件比同步事件多了不确定性.
为了解决异步事件的执行顺序问题,JS引擎产生了一个机制,那就是Event Loop(事件循环)。通过这个机制,JS引擎对异步事件进行处理,一次处理一件。
每次主线程执行栈为空的时候,引擎会优先处理微任务队列,处理完微任务队列里的所有任务,再去处理宏任务。
常见的微任务有 promise.then catch finally、process.nextTick
常见的宏任务有 setTimeout、setInterval
Event Loop
js是一个单线程语言,所有的任务只能排队一个一个去做,这样效率明显很低。 所以event loop就是为解决这个问题而提出的。
在主程序中,分为两个线程,一个运行程序本身,称作主线程,另一个负责主线程和其它线程进行通信(主要是I/O操作),被称作event loop线程
在运行程序的时候,当遇到I/O操作的时候,主线程就让Event loop 线程通知相应的I/O模块去执行,然后主
Promise
Promise是异步编程的一种方案,可以将异步操作以同步方式输出,每个操作返回的都是Promise对象,可支持链式调用。通过 then 方法执行回调函数,Promise的回调函数是放在事件循环中的微队列。
它有三种状态 pending、fulfilled/resolved、rejected,,这个状态一旦改变完就不会再改变了,可以用then方法指定resolve和reject状态的回调函数,可以catch捕捉错误信息
promise构造函数接收一个函数,作为参数,分别为resolve和reject,实例生成后,可以用then方法指定resolve和reject状态的回调函数,可以catch捕捉错误信息
catch是then的语法糖
Promise.all()方法用于将多个 Promise 实例,包装成一个新的 Promise 实例。
比如 Promise.all([promise1, promise2]).then(success1, fail1) ,比如一次性调用多个ajax请求
promise1和promise2都成功才会调用success1
promise.all方法是通过判断所有都成功则返回成功.
Promise.race同样是将多个 Promise 实例,包装成一个新的 Promise 实例。
比如promise里面有3个任务,哪个结果获得的快,就返回那个结果,不管结果本身是成功还是失败
promise值穿透
.then 或者 .catch 的参数期望是函数,传入非函数则会发生值穿透。
Promise方法链通过return传值,没有return就只是相互独立的任务而已
setTimeout、Promise、Async/Await 的区别
宏任务 微任务JS中同步和异步
事件循环中分为宏任务队列和微任务队列
其中setTimeout的回调函数放到宏任务队列里,等到执行栈清空以后执行
promise.then里的回调函数会放到相应宏任务的微任务队列里,等宏任务里面的同步代码执行完再执行
async/await
async/await是ES7语法,是用来实现异步编程的,语法是在function关键字前加上async,代表是异步函数,await只能在async函数里使用。
async将任何函数转换为promise,这是异步函数的特征之一。 await 可以使用在任何返回Promise函数的函数之前,并且会暂停在这里,直到promise返回结果才往下进行。
async/awaite基本做到了用同步代码的风格实现异步逻辑,让代码更简洁。
async函数表示函数里面可能会有异步方法,await后面跟一个表达式
async方法执行时,遇到await会立即执行表达式,然后把表达式后面的代码放到微任务队列里,让出执行栈让同步代码先执行
防抖和节流
防抖:事件被调用后,在执行之前无论被调用多少次都会从头开始计时
节流:不管事件被调用多少次,总是按规定时间间隔执行
防抖和节流的作用都是减少http请求,优化性能
可以用闭包进行封装 传入两个参数 一个是要执行的函数 一个间隔时间
定义一个标记符 作用是 判断 清除定时器 然后返回一个函数 这个函数进行判断标记符 如果为true 就返回 否则 就把标记符赋值一个setTimeout 然后执行传入的函数,
TCP的三次握手和四次挥手---网络通信
1,客户端向服务端发送请求,要求建立连接。
2,服务器向客户端发送,可以建立连接。
3,客户端向服务端发送请求,服务器验证,建立连接。
1,客户端发送报文给服务端数据。
2,服务器收到消息,数据还没有完毕
3. 服务器已经完成,发消息给客户端
4,客户端发送消息,关闭连接
为什么连接的时候是三次握手,关闭的时候却是四次握手?
TCP是全双工的,每个方向都要进行单独关闭。当一方完成数据发送任务后,发送一个FIN报文来终止这一方向的连接,这意味着不再发送数据,但是还可以接收数据,除非对方也发送了FIN报文。假设client端是主动发起方,当server端收到Client端的FIN报文后,知道它不再发送数据过来了。但server端自己还有数据没发完,不想立即关闭连接,所以只能先回复一个ACK报文,告诉client端,"你发的FIN报文我收到了"。server端等所有的数据都发送完了,然后发一个FIN+ACK报文给client端,client端收到后发送一个ACK报文给server端,server端收到了,然后才真正关闭了连接,故需要四步握手。
TCP如何保证数据可靠性
• 数据包校验
• 超时重传机制
• 应答机制
• 对失序数据包重排序
• TCP还能提供流量控制
优雅降级,渐进增强
针对低版本浏览器进行构建页面,保证最基本的功能实现,然后在针对高级浏览器进行效果,交互等方面的改进,达到更好的用户体验
降级,一开始就构建完整的功能,然后在针对低版本浏览器进行兼容。
Udp、tcp
基于连接和无连接
Tcp是一个传输控制协议,是面向连接的协议,在收发数据前必须和对方建立可靠的连接。这就设计了三次挥手四次握手。
Udp是一个非连接协议。传输数据之前源端与终端不建立连接。当他想传送时,抓取来自应用程序的数据,然后扔到网上
Tcp更可靠。
Eslint规则
使用单引号,双引号报错
禁止重复函数声明
禁止使用alert
Css
圣杯布局/双飞翼布局
两者都属于三列布局,是一种很常见的布局方式
分为子列,主列,附加列。子列一般是居左的导航,宽度固定,主列是居中的主要内容
,宽度自适应。附加列一般为广告系你想,居右宽度固定
px,rem。Em
px像素,相对长度单位。相对于显示器屏幕分辨率而言的。
EM是相对长度单位。相对于当前对象内文本的字体尺寸。
一般浏览器的默认字体高都是16px。所有未经调整的浏览器都符合: 1em=16px。
为了简化font-size的换算,需要在css中的body选择器中声明Font-size=62.5%
em是相对于父级元素的单位,会随父级元素的属性变化而变化
rem是CSS3新增的一个相对单位,是为了解决em的缺点
em可以说是相对于父级元素的字体大小,当父级元素字体大小改变时,又得重新计算。
rem只相对于根目录,即HTML元素。所以只要在html标签上设置字体大小,文档中的字体
大小都会以此为参照标准,一般用于自适应布局。
Cookie,sessionstorage,localstorage区别
Cookie是为了标识用户身份而存储在用户本地终端上的数据(一般经过加密),还可以设置有效时间。一般在同源的http的请求中,会在浏览器和服务器之间传递。每次ajax请求都会将他传送到后台去,一半用用户登录,cookie信息判断用户是否登录。大小不超过4k
localstorage存储持久数据,浏览器关闭数据也不会丢失,除非主动删除。
Sessionstorage当浏览器关闭就自动删除。
Cookie设置的过期时间之前就一直有效,不管浏览器关闭与否。
三角形
Width 0 height 0 border-width 10px border-style solid实线 border-color transparent 2 red 4
flex属性-flex:1到底是什么
flex属性 是 flex-grow、flex-shrink、flex-basis三个属性的缩写。
flex-grow:定义项目的的放大比例;
默认为0,即使存在剩余空间,也不会放大;
所有项目的flex-grow为1:等分剩余空间(自动放大占位);
flex-grow为n的项目,占据的空间(放大的比例)是flex-grow为1的n倍。
flex-shrink:定义项目的缩小比例;
默认为1,即 如果空间不足,该项目将缩小;
所有项目的flex-shrink为1:当空间不足时,缩小的比例相同;
flex-shrink为0:空间不足时,该项目不会缩小;
flex-shrink为n的项目,空间不足时缩小的比例是flex-shrink为1的n倍。
flex-basis: 定义在分配多余空间之前,项目占据的主轴空间(main size),浏览器根据此属性计算主轴是否有多余空间,
默认值为auto,即 项目原本大小;
设置后项目将占据固定空间。
所以flex属性的默认值为:0 1 auto (不放大会缩小)
bfc 块级格式化上下文
BFC是一个独立的布局环境,其中的元素布局是不受外界的影响
块级格式上下文
用于对块级元素排版,默认情况下只有根元素(body)一个块级上下文,但是如果一个块级元素设置了float:left,overflow:hidden或position:absolute样式,就会为这个块级元素生产一个独立的块级上下文,使这个块级元素内部的排版完全独立。
overflow:hidden清除浮动
overflow:hidden"可以溢出隐藏,还有另外一个特殊的用途,那就是清除包含块内子元素的浮动,这个就设计到bfc
visibility:hidden与display:node区别
都能让元素不可见
区别
- display:none 会让元素完全从渲染树中消失,不占据任何空间,
- Visibility:hidden不会让元素从渲染树小时,占据空间,内容不可见
Display会造成重排,visibile 重绘,读屏器不会读取display的内容,会读取visil的内容
CSS选择器
- id选择器( #myid)
- 类选择器(.myclassname)
- 标签选择器(div, h1, p)
- 紧邻同胞选择器 h1 + p(选的是h1后紧跟的那个p)
- 一般同胞选择器 h1 ~ p(选择所有跟在h1后的p)[css3]
- 子选择器(ul > li)
- 后代选择器(li a)
- 通配符选择器( * )
- 属性选择器(a[rel = "external"])
- 伪类选择器(a:hover, li:nth-child)
水平垂直居中
- position: relative / fixed; /* 相对定位或绝对定位均可 */
margin: -150px 0 0 -250px; /* 外边距为自身宽高的一半 */
- position: absolute/fixed;
top: 50%; left: 50%; transform: translate(-50%, -50%);
- display: flex;
align-items: center; /* 垂直居中 */
justify-content: center; /* 水平居中 */
- line-height: 200px; /* 垂直居中 */ text-align: center; /* 水平居中 */
哪些属性可以继承
所有元素可继承: visibility cursor
内联元素可继承: 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
CSS3有哪些新特性
圆角 (border-radius:8px)
新增各种CSS选择器、伪类 (经常用到 :nth-child)
文字渲染 (Text-decoration)
转化为简写属性,可设置text-decoration-color, text-decoration-style, text-decoration-line三个属性,默认值为currentcolor solid none。
透明色 & 透明度(opacity)
旋转 (transform)
旋转 rotate,缩放 scale,倾斜 skew,平移 translate
动画(animation) & 过渡效果(transition)
阴影(box-shadow, text-shadow)
box-shadow: x-offset y-offset blur-radius spread-radius color;
text-shadow: x-offset y-offset blur-radius color;复制代码
新的布局方式,如 多列布局 multi-columns 、 弹性布局 flexible box 与 网格布局 grid layouts
线性渐变(gradient)
多背景(background-image可以设置多个url或linear-gradient)
边框可以设置图片(border-image)
H5新特性
语义化标签:header、footer、section、nav、aside、article
增强型表单:input 的多个 type
新增表单元素:datalist、keygen、output
新增表单属性:placehoder、required、min 和 max
音频视频:audio、video
canvas
地理定位
拖拽
本地存储:localStorage - 没有时间限制的数据存储;sessionStorage - 针对一个 session 的数据存储,当用户关闭浏览器窗口后,数据会被删除
新事件:onresize、ondrag、onscroll、onmousewheel、onerror、onplay、onpause
WebSocket:单个 TCP 连接上进行全双工通讯的协议
h5性能优化
1,减少http请求
2,使用缓存减少向服务器请求数量
3,压缩HTML/CSS/JS,启用Gzip
4,按需加载
5,减少cookie
6,异步加载第三方资源
position(定位)样式
static:默认值,表示无定位
absolute:表示采用绝对定位地方时,相对于position值不是static的父容器进行定位,该值会使元素脱离文档流,使用该值后可以用left,right,top,bottom对元素进行移动定位
relative:表示采用相对定位的方式,相对于元素原来的位置进行定位,该值不会使元素脱离文档流,使用该值后可以用left,right,top,bottom对元素进行移动定位
fixed:表示采用固定定位的方式,相对于浏览器窗口进行定位,并且无论滚动条怎么滚动,使用了该值的元素都始终处于固定值,该值会使元素脱离文档流,使用该值后可以用left,right,top,bottom对元素进行移动定位
sticky(粘性定位):sticky是css定位新增属性;可以说是static(没有定位) 和 固定定位fixed 的结合;它主要用在对 scroll 事件的监听上;简单来说,在滑动过程中,某个元素距离其父元素的距离达到 sticky粘性定位的要求时(比如top:100px);position:sticky这时的效果相当于fixed定位,固定到适当位置
使用条件:父元素不能overflow:hidden或者overflow:auto属性。 必须指定top、bottom、left、right4个值之一,否则只会处于相对定位 父元素的高度不能低于sticky元素的高度 sticky元素仅在其父元素内生效
Grid 布局简介
将容器划分成一个个网格, 并指定网格的大小、布局、位置、层级实现基本布局,
是一种二维布局、更适用于多行和多列布局,多用于可视化大屏
浮动
浮动元素脱离文档流,不占据空间。
- 使用空标签清除浮动---》在所有浮动标签后面添加一个空标签 css clear:both 缺点就是增加了无意义的标签
- 使用overflow --》 给他的父标签添加 css overflow:auto (zoom:1 用与兼容ie6)
- 使用after伪对象清除浮动 ---》 只能适用于 非 ie浏览器。 需要为清除浮动元素的伪对象中设置height:0 ,否则该元素会比实际高出若干像素
浮动引起的问题
- 父元素高度无法被撑开,影响与父元素同级的元素
- 与浮动元素同级的非浮动元素会跟随其后
盒模型:
盒模型组成:content(内容区)、padding(填充区)、border(边框区)、margin(外边距区)
怪异盒模型:width/height+margin
标准盒模型和怪异盒模型的区别是整个盒子的宽高决定方式的不同,可通过设置css属性box-sizing为content-box和border-box分别将盒子设置为标准盒模型和怪异盒模型。
了解postcss吗
postcss 一种对css编译的工具,类似babel对js的处理
postcss 只是一个工具,它通过插件实现功能
安装postcss-loader ,在webpack中配置
Sass less
他们是动态的样式语言,是css的预处理器,是css上的一种抽象层。
区别
变量符不同,less用@ scss用$
Sass支持条件语句,可以使用if else ,less不可以
物理1像素
使用transform 缩放0.5倍
为什么设置物理1像素
UI设计师要求的1px是指设备的物理像素1px,而CSS里记录的像素是逻辑像素
dpr----设备像素比
要想达到1px效果,只需要查询当前设备的dpr,再根据dpr进行缩放即可
CSS预处理、后台处理器
预处理器例如,less、sas、stylus,用来预编译sass或less,增强css代码的复用性。
后处理器例如,postcss,通常被视为在完成的样式表中根据css规范处理css
Sprite
是一种网页图片应用处理方式,把网页中一些背景图片整合到一张图片文件中,再利用css'的background-image / background-repeat / background -positon 的组合进行背景定位
优点:
减少页面的http请求,提高性能,是被广泛传播和应用的主要原因
减少图片字节
减少命名困扰
跟换风格方便
Hack
针对不同浏览器,不同版本写特定的css样式
webpack
webpack是一个预编译模块方案,它会分析你的项目结构将其打包成适合浏览器加载的模块。
它的打包原理就是:把所有依赖打包成一个bundle.js文件,通过代码分割成单元片段并按需加载。
核心思想:
1.一切皆模块,一个js,或者一个css文件也都看成一个模块,
2.按需加载,传统的模块打包工具(module bundlers)最终将所有的模块编译生成一个庞大的bundle.js文件。
但是在真实的app里边,“bundle.js”文件可能有10M到15M之大可能会导致应用一直处于加载中状态。
因此Webpack使用许多特性来分割代码然后生成多个“bundle”文件,而且异步加载部分代码以实现按需加载。
打包配置
webpack打包优化 ----》优化前端性能
指优化webpack的输出结果,在浏览器上快速运行
1,压缩代码。删除多余的代码、注释、简化代码的写法等等方式
2,利用CDN加速。将引用的静态资源路径修改为CDN上对应的路径。
3,删除死代码。将代码中永远不会走到的片段删除掉
4,提取公共代码
具体----
配置 entry入口 output 出口
还有一些插件 比如: html-webpack-plugin
还有一些打包的loder 比如: css-loader style-loader babel-loader
各种Loader配置:module参数
通过Loader,对每一种特定的资源做出相应的处理。Loader的种类相当多,有些比较基础的是官方自己开发
plugins参数是个数组,按照某些要求,初始化。
plugin和loader的区别
【Loader】:用于对模块源码的转换,loader描述了webpack如何处理非javascript模块,并且在buld中引入这些依赖。可以将不同的语言转换为JavaScript,或者将内。比如说:CSS-Loader,Style-Loader等。
在webpack.config.js中指定loader。module.rules可以指定多个loader,对项目中的各个loader有个全局概览。
用options对象进行配置。plugin可以为loader带来更多特性。loader可以进行压缩,打包,语言翻译等等。
loader从模板路径解析,npm install node_modules。也可以自定义loader,命名XXX-loader。
语言类的处理器loader:CoffeeScript,TypeScript,ESNext(Bable),Sass,Less,Stylus。任何开发技术栈都可以使用webpack。
plugin是一个扩展器,解决loader无法实现的其他事,从打包优化和压缩,到重新定义环境变量
打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包
过程中的某些节点,执行广泛的任务
用过哪些loader、plugin
css-loader:
css-loader 主要用于处理图片路径(包括导入 css 文件的路径),并且会将 css 样式打包进 js 文件中(以模块的形式打包导入)。
style-loader:
style-loader 通过 <style> 标签将 css 插入到 DOM 中。建议 style-loader 与 css-loader 结合使用。
sass-loader:
加载 sass/scss 文件并且变异成 css。
uglify-webpack-plugin:
压缩 javascript
提高webpack的构建速度
1:优化图片
使用 url-loader 优化, 将小图片转化成base64压缩,防止小图片太多请求次数太多。
2:分离第三方包
打包后的bundle.js文件夹较大,所以每次加载的时候,请求比较慢,所以有必要在打包时将第三方包分离出来。使用CommonsChunkPlugin 插件进行配置。
3:分离 css 文件并压缩 css 文件
使用 extract-text-webpack-plugin 插件将css文件分离出来。为了使项目加载时候尽早优先加载css样式,也为了解决js文件体积过大的问题
4: 压缩 js 文件
使用 uglifyjs-webpack-plugin 将js压缩,减少打包后的 vendor.js , bundle.js 等js的文件大小
5:压缩Html
为了减少打包后的文件体积,使性能更好,效率更高,提高加载速度,打包时有必要进行压缩。
使用html-webpack-plugin 进行压缩
5,使用webpack-uglify-parallel来提升uglifyPlugin的压缩速度。
6,使用Tree-shaking和Scope Hoisting来剔除多余代码
减少检索路经:resolve.alias可以配置webpack模块解析的别名
webpack打包文件体积过大?(最终打包为一个js文件)
1.异步加载模块
2.提取第三库
3.代码压缩
4.去除不必要的插件
移动端
移动端的兼容问题
- 给移动端添加点击事件会有300S的延迟 如果用点击事件,需要引一个fastclick.js文件,解决300s的延迟
- 一般在移动端用ontouchstart、ontouchmove、ontouchend
- 移动端点透问题,touchstart 早于 touchend 早于click,click的触发是有延迟的,这个时间大概在300ms左右,也就是说我们tap触发之后蒙层隐藏, 此时 click还没有触发,300ms之后由于蒙层隐藏,我们的click触发到了下面的a链接上 尽量都使用touch事件来替换click事件。
- 例如用touchend事件(推荐)。 用fastclick,github.com/ftlabs/fast… 用preventDefault阻止a标签的click 消除 IE10 里面的那个叉号 input:-ms-clear{display:none;}
- 设置缓存 手机页面通常在第一次加载后会进行缓存,然后每次刷新会使用缓存而不是去重新向服务器发送请求。如果不希望使用缓存可以设置no-cache。
- 圆角BUG 某些Android手机圆角失效 background-clip: padding-box; 防止手机中网页放大和缩小 这点是最基本的,做为手机网站开发者来说应该都知道的,就是设置meta中的viewport
- 设置用户截止缩放,一般写视口的时候就已经写好了
移动端的适配
通过使用rem单元配合媒体查询完成屏幕适配,
比方以苹果6为例子,向上匹配plus,向下匹配5,不做过多适配,rem是相对单位,相对html元素的font-size值的属性,比如font-size:100px,1rem就是100px,这样就可以通过html的font-size可以适配
- 自适应方式
- Viewport
- Scale缩放
移动端300ms延迟怎么解决?
1. faskclick
原理: 在检测到touchend事件的时候,会通过DOM自定义事件立即出发模拟一个click事件,并把浏览器在300ms之后真正的click事件阻止掉
缺点: 脚本相对较大, 不建议使用
2、禁用游览器缩放
缺点,就是必须通过完全禁用缩放来达到去掉点击延迟的目的
在html文档头部添加meta标签。
3、更改默认的视口宽度
只是禁用了浏览器默认的双击缩放行为
4、通过 touchstart 和 touchend模拟实现
什么是点击穿透?
假如页面上有两个元素A和B。B元素在A元素之上。我们在B元素的touchstart事件上注册了一个回调函数,该回调函数的作用是隐藏B元素。我们发现,当我们点击B元素,B元素被隐藏了,随后,A元素触发了click事件。
这是因为在移动端浏览器,事件执行的顺序是touchstart > touchend > click。而click事件有300ms的延迟,当touchstart事件把B元素隐藏之后,隔了300ms,浏览器触发了click事件,但是此时B元素不见了,所以该事件被派发到了A元素身上。如果A元素是一个链接,那此时页面就会意外地跳转。
移动端的性能优化
1、首屏加载和按需加载,懒加载
2、资源预加载
3、图片压缩处理,使用base64内嵌图片
4、合理缓存dom对象
5、使用touchstart代替click(click 300毫秒的延迟)
6、利用transform:translateZ(0),开启硬件GUP加速
7、使用viewport固定屏幕渲染,加速页面渲染内容
8、尽量使用事件代理,避免直接事件绑定
我的项目
接口和参与预留给后端
第一家公司叫 赢信慧通, 青岛赢信慧通教育科技有限公司
地址在 海淀区 上地街 金隅大厦b座908室
第二家公司叫 对啊网,北京对啊网教育科技有限公司,
地址 北京 经济技术开发区 科创十三街18号院15号楼1层
住在 敬园小区,做56路公交车。
自我介绍
(你好),我是刘雪,来自山西临汾。本科学历,目前应聘的岗位是咱们公司的web前端开发,我有三年从事web前端开发工作的经验。比较擅长的技术栈主要有vue react,其实像前端这些主流技术个人都有涉及到,目前经历主要有两家,主要后一家呆的时间比较就一些,在这家公司主要负责的项目,最近的公司采用的react比较多一些,小程序开发,我也有参与过,开发技术呢主要uni-app,taro,其实对于小程序我个人觉得核心还是基于文档的开发能力,对于文档的阅读去开发这是我自己也是看中的一方面。
我的上一家公司是一个美容行业。涉及仪器美容、微整、大健康等,为了给客户提供提供更便捷的服务 。
我参与了(pc端 官网项目)、(移动端 -- 针对客户需求)(后台管理系统,管理员和用户权限,给用户增加产品项目)
------下面是具体项目介绍
因为做这几个项目中时间跨度有点久,用了不同的技术,其实我们公司主要核心技术还是react,react用的比较多,但是不同的产品线里也会用到vue,所以我也参与了vue项目开发。
--------有代表性的就是后台管理系统,
他是以react+ts开发。ts是js的超集。ts是为了增强react开发,是一个类型注解,对接参入参的一个注解,类型限定,达到静态编译。优点是在项目开发的时候就会出现错误提示,节省了后期找bug和维护问题。
就我个人而言刚开始使用的时候比较头疼这个开发模式,因为接触了新东西难免会生疏麻烦,刚开始会比较困难,因为赶工期这个情况,所有什么类型都是any,后来随着不断开发以及项目迭代更新,重新修改了。 发现这个开发模式特别的好,在编译的时候就报出了哪里错误,省去了大量时间,提高后期来发。
用了一段时间后发觉这种模式也没什么,我觉得ts只是一个辅助型的注解东西,有没有都能写代码,有了确实提高了后期维护成本与时间。
具体功能的话也就是管理员给这一天使用过的仪器进行增删改查。以及权限判断,当前跳转到具体页面后,因为需要判断token值,在这里 我封装了一个如果vue路由守卫相似功能的高阶组件。axios二次封装,在请求头中加入token字段,如果没有token就重点向到登录页面。有的话就根据token值来展示用户页面还是管理员。
-------在pc端中技术选型是react + antd 。
我在项目中负责主页、题库模块。
主页中使用了flex布局以及成熟的ui框架 antd。主页中分为标题和内容展示。
标题使用了粘性定位sticky,我使用了antd的下拉菜单效果是鼠标划过显示具体课程。,对数据一级二级渲染跳转进入详情页面
内容部分为展示图标,(效果和标题相同)
底部是采用了h5新增的媒体标签video,并且使用了节流函数,在1秒内只执行一次。
在题库组件中,也是对课程的进一步展示,使用了瀑布流效果,点击跳转到详情页,(这里需要判断用户是否登录,封装了高阶组件来进行路由拦截),重定向到登录页面,有免费资料和付费区域。
--------移动端项目中vue +vant
选用vue框架 + vant,我负责主页布局渲染,这里采用左右布局方式。分别渲染一级二级数据。,使用了ui组件的导航菜单navmenu。进入页面后这里使用三段式布局。标题内容,底部导航路由跳转(有首页,班级,购物车,我的)。首页展示了公开课、题库、视频库、系统班,当点击班级的时候,这里使用了路由守卫,进入课程页面时候。判断是否登录。使用vant Popup 弹出层,表单验证。
如何管理项目
- 开发前小组团队先要确定好全局样式,编码规范。global.css eslint
- 每个模块的负责人是谁,及功能实现
- 命名规范文件
你封装过什么组件
react项目中使用二次封装button 按钮
React 路由懒加载 ,loading效果 在表格等容器中加载数据时显示
项目中难点??
问题----前端支付功能怎么实现
官网 微信支付api 支付宝api
微信的话 (JSAPI支付) 进行开发步骤, h5支付
业务逻辑 (电商平台为例子)
就一定会有订单逻辑:
1.用户选择课程产品后进入提交订单流程 ----> 生成订单 (待付款)
2.生成订单后进入支付流程 --->选择支付方式(支付或者微信)
3.唤起对应的支付应用程序,用户确认金额并支付,支付成功后 ----->完成订单 (已付款);
在这个过程中,前端工程师能干什么????
注意,因为安全性的原因,前端算出来的总支付金额,只是给用户确认的,最后支付金
额肯定是由后端算出来的,然后前后两端金额对比无误后,进入支付阶段。
需要前端去选择并唤起支付程序(微信或支付宝),然后通过微信或者支付的提供的对
应API,唤起支付
---session,cookie,登录超时原理浅析
1.cookie保存在客户端,session保存在服务器端,通过这两个提供的信息,服务器端进行相关操作来判断登录是否超时
2.cookie(目的可以跟踪会话),也可以保存一些用户想要保存的东西(登录时,是否勾选保存账号密码)。session用来跟踪会话
打开浏览器第一次请求的时候,服务器会自动为其创建一个session,并赋予其一个sessionID,发送给客户端的浏览器。之后客户端接着请求应用中其他资源的时候,会自动在请求头上添加:Cookie:JSESSIONID
Session超时:超时指的是连续一定时间服务器没有收到该Session所对应客户端的请求,并且这个时间超过了服务器设置的Session超时的最大时间,再次登录会重新在cookies里新增一个JSESSIONID。
------怎么判断用户访问网页过程中是否还处于登录阶段:(后台————》因为都是表单提交)
客户端在进行调用接口的操作的时候,就会把cookie一起通过 ,请求头发送给服务端,
服务端除了接收到接口传递的正常参数外,还要接受cookie中的内容,然后去拿cookie中的用户标示然后去 服务端缓存redis 中的用户信息进行查找,如果redis中没有该用户的相关信息就表示登录超时,这个接口就会返回给客户端一个标示(这个表示是我和后端同事自己定义的)
例如:status = 1002
客户端拿到status = 1002这个标示后,知道该用户已经超时,直接把页面跳转到登录页面,不允许用户再访问。
---订单待支付倒计时
web前端处理订单待支付倒计时计算显示问题
处理方法:
1.调用后端接口拿到所有的订单,获取所有的倒计时订单,获取到期时间(尽量时间戳,不行就自己转换)。
2.渲染列表的时候把未支付的订单加上计数器dom,然后把到期时间戳写在dom属性里面
((4.如果到期了就改变订单状态,如果这个时候dom过多处理起来或许会有延迟,但是也就差一丢丢,后端也会做超时取消的,前后端都做。
5.如果后端不做的话,就是前端拿到超时订单,先修改dom,然后在用这个订单号调接口让后端修改这个订单状态。
(后端有时候不会这样给,有时候是给你下单时间,然后自定义个倒计时15分钟,或者半小时,到期调接口改状态,这个时候就得自己计算出来到期时间戳了)
----不算难点---在请求ajax有遇到乱码问题
这个问题一般是没有统一页面和服务器的编码,对请求和响应的content-type设置正确编码。对请求参数进行编码处理。
----难点3---前端处理高并发数据 ,12306 这种,项目中没有设计过多,但是有去看过相关资料站
1.应用和静态资源分离。
将静态资源(js,css,图片等)放到专门的服务器中。
2.页面缓存
将应用生成的页面缓存起来可以节省大量cpu资源。
对于部分页面经常变换数据的,可以使用ajax来处理。
3,CDN
CDN是一种特殊的集群页面缓冲服务器,和普通的集群的多台页面缓冲服务器相比主要区别是:其存放位置和分配请求方式不同。
CDN的服务器分布在全国各地,接收到请求后会将请求分配到最合适的CDN服务器节点来获取数据。其每一个CDN节点就是一个页面缓存服务器。
分配方式:并不是普通的负载均衡,而是专门的CDN域名解析服务器在解析域名的时候就分配好的,一般的做饭是:ISP那里使用CNAME将域名解析到一个特定的域名,然后再将解析到的那个域名用专门的CDN服务器解析(返回给浏览器,再访问)到相应的CDN节点。每个节点可能也集群了多台服务器。
Cnd
- 避开互联网有可能影响数据传输速度和稳定性的瓶颈和环节。使内容传输的更快更稳定。
2.关键技术:内容存储和分发技术中
3.基本原理:采用各种缓存服务器,将这些缓存服务器分布到用户访问相对的地区或者网络中。当用户访问网络时利用全局负载技术 将用户的访问指向距离最近的缓存服务器,由缓存服务器直接相应用户的请求(全局负载技术)
- -webpack增量打包
刚开始的话,从入口文件,找出具有依赖关系的文件js/css,然后打包成一个js包,上线。
但有时候,产品会有另外需求,比如按钮颜色不对,样式不好看,然后就改,打包后就出问题了,就是将之前写的部分业务覆盖调了。
思考了下,考虑能不能重新打包一个文件,单独来处理,结果是不行的。
原因1,之前打包好的文件已经通过依赖关系。2,新的文件需要手动自己引入html中,这样会造成无法维护。
---改变webpack的输出结果
其实webpack关于缓存方面的功能,提供了很多功能强大的插件。
比如CommonsChunkPlugin可以用来在打包的时候提取公共js代码,还有其他插件
使用HappyPack多线程加速loader
ExtractTextPlugin可以用来从js中提出css,将其输出到一个独立的文件
能够将我们打包的精度加以划分,将公共引用的部分打包为一个单独的文件
使用chunkhash替代hash,根据模块内容来添加hash,只要文件没有改变,就不会生成新的hash
因为webpack打包的是有有一个默认模块就是manifest,所以通过默认的名字,来提取公共代码
项目中做过的性能优化
(1) 减少 HTTP 请求数
(2) 使用 CDN
(3) 使用外部 JavaScript 和 CSS
(4) 避免重定向
(5) 图片懒加载
(6) 使用 iconfont
(7) 尽量减少 iframe 使用
(8) 减少 DOM 元素数量
(9) 减少 DOM 操作
(10) 压缩 JavaScript 、 CSS 、字体、图片等
(11) 减少 DNS 查询
(12) js放在页面底部
(13)复用组件
(13) 避免图片src为空
优化 CSS Sprite
字体裁剪
我反问面试官
- 团队成员目前有多少人,是如何分工的呢?现在的核心工作是什么?
- 如果我来到公司之后pc 移动端,发展方向,主营业务
缓存
js缓存
使用缓存的好处:
(1).当页面渲染的数据过多时,为了减轻对内存的占用,对首次接收到的数据进行本地缓存,(是有着大好处的.)
(2).受网速等各种因素的影响,当渲染数据过多时,若存在频繁的切换页面,会造成用户体验效果不佳。
sessionStorage
localStorage
cookie
cookie兼容所有的浏览器,但其存储的数据是有大小限制的,一般同源是4kb
cookie本地存储的数据会被发送到服务器
http缓存
比如当客户端向服务器请求资源时,会先从浏览器缓存去找,如果浏览器有之前访问过的,就可以直接从浏览器缓存中提取而不是从原始服务器中提取这个资源
常见的http缓存只能缓存get请求响应的资源
浏览器缓存分为强缓存和协商缓存,
强缓存会直接从浏览器里面拿数据,
协商缓存会先访问服务器看缓存是否过期,再决定是否从浏览器里面拿数据。
浏览器加载一个页面具体流程
- 浏览器先根据这个资源的http头信息来判断是否命中强缓存。如果命中则直接加载缓存中的资源,就不会将请求发送到服务器。
比如某个css文件,如果浏览器在加载它所在的网页时,这个css文件的缓存配置命中了强缓存,浏览器就直接从缓存中加载这个css,连请求都不会发送到网页所在服务器
- 当强缓存没有命中的时候,浏览器会发送请求到服务器,通过另外一些http header验证这个资源是否命中协商缓存,如果协商缓存命中,服务器会将这个请求返回,但是不会返回这个资源的数据,而是告诉客户端可以直接从缓存中加载这个资源,这样的话浏览器就又会从自己的缓存中去加载这个资源
- 强缓存与协商缓存的共同点是:如果命中,都是从客户端的缓存中加载资源,而不是从服务器加载资源数据;
- 区别是:强缓存不发请求到服务器,协商缓存会发请求到服务器
- 当协商缓存也没有命中的时候,浏览器直接从服务器加载资源数据
浏览器
浏览器适配问题
不同浏览器的环境中呈现出不一致的页面展现效果
使用的是css hack来解决IE适配
CSS Hack大致有3种表现形式
属性前缀法
选择器前缀法(即选择器Hack)
IE条件注释法(即HTML条件注释Hack)
浏览器缓存
浏览器缓存分为强缓存和协商缓存,
强缓存会直接从浏览器里面拿数据,
协商缓存会先访问服务器看缓存是否过期,再决定是否从浏览器里面拿数据。
控制强缓存的字段有:Expires和Cache-Control,Expires 和 Cache-Control。
控制协商缓存的字段是:Last-Modified / If-Modified-Since 和 Etag / If-None-Match,
其中 Etag / If-None-Match的优先级比Last-Modified / If-Modified-Since高。
浏览器兼容问题
1,浏览器兼容问题一:不同浏览器的标签默认的margin和padding不同,
2,浏览器兼容问题二:块属性标签float后,又有横行的margin情况下,在IE6显示margin比设置的大
第一类:块状元素float后,有添加了横向的margin,在IE6下比设置的值要大(属于双倍浮动的bug)
解决方案:给float标签添加display:inline,将其转换为行内元素
第二类:表单元素行高不一致
解决方案:给表单元素添加float:left(左浮动);或者是vertical-align:middle;(垂直对齐方式:居中)
第三类:设置较小高度的容器(小于10px),在IE6下不识别小于10px的高度;
解决方案:给容器添加overflow:hidden;
第四类:当在a标签中嵌套img标签时,在某些浏览器中img会有蓝色边框;
解决方案:给img添加border:0;或者是border:none;
浏览器渲染原理及流程
流程:解析html以及构建dom树 -> 构建render树 -> 布局render树 -> 绘制render树
概念:
1.构建DOM树: 渲染引擎解析HTML文档,首先将标签转换成DOM树,生成内容树
2.构建渲染树: 解析对应的css样式文件信息(包括js生成的样式和外部的css)
3.布局渲染树:从根节点递归调用,计算每一个元素的大小,位置等。给出每个节点所在的屏幕的精准位置
4.绘制渲染树:遍历渲染树,使用UI后端层来绘制每一个节点
重绘:当渲染树中的元素外观(比如颜色 )发生改变,不影响布局,产生重绘
回流:当渲染树元素的布局(尺寸,位置)发送改变,产生重绘回流。
因为浏览器需要通过回流计算最新值回流必将引起重绘,但重绘不一定引起回流。
最小化重绘和回流?
需要对元素进行复杂的操作时候,可以先隐藏(display:none),操作完后再显示需要创建多个dom节点。
git
远程仓库、本地仓库、本地缓存区、本地工作区
git版本控制开发(分支管理)
----master分支,上线使用master
----develop是开发分支,用于生成测试分支release,
----hotfix是紧急分支,从master生成,bug修正后自动合并到master和develop并且生成tag
----release常规分支,测试并且bug修改结束后生成该版本tag,可以查看版本和回滚
如何解决git冲突
merge tool,出现对比界面,左边的代码是服务器最新的代码,而右边就是你自己的代码,这时候你需要去对比服务器代码和你的代码哪里不一致然后修改放在左边保存。然后将代码合并,之后commit提交代码。如果出资安箭头的话冲突就解决了。
回滚
# 取消暂存
git reset HEAD fileName
# 撤销修改
git checkout fileNam
设计模式
1、js工厂模式 2、js构造函数模式 3、js原型模式 4、构造函数+原型的js混合模式 5、构造函数+原型的动态原型模式 6、观察者模式 7、发布订阅模式
-----什么是单例模式
是一种常用的软件设计模式,在应用这个模式时,单例对象的类必须保证只有一个实例存在,整个系统只能使用一个对象实例。
优点:不会频繁地创建和销毁对象,浪费系统资源。
使用场景:IO 、数据库连接、Redis 连接等。
-----工厂模式
就是建立一个工厂类,对实现了同一接口的一些类进行实例的创建。比如,一台咖啡机就可以理解为一个工厂模式,你只需要按下想喝的咖啡品类的按钮(摩卡或拿铁),它就会给你生产一杯相应的咖啡,你不需要管它内部的具体实现,只要告诉它你的需求即可。
优点:有必要的判断逻辑,可以决定在什么时候创建哪一个产品类的实例
缺点:不易拓展,一旦添加新的产品类型,就不得不修改工厂的创建逻辑
-----观察者模式
定义对象间的一种一对多依赖关系。
观察者模式又叫做发布-订阅模式
优点:以实现表示层和数据逻辑层的分离
缺点:如果在观察者和观察目标之间有循环依赖的话,观察目标会触发它们之间进行循环调用,可能导致系统崩溃
-----装饰器模式
是指动态地给一个对象增加一些额外的功能,同时又不改变其结构
一、观察者模式:
在软件开发设计中是一个对象(subject),维护一系列依赖他的对象(observer),当任何状态发生改变自动通知他们。强依赖关系
简单理解:数据发生改变时,对应的处理函数就会自动执行。一个Subjet,用来维护Observers,为某些event来通知(notify)观察者
发布-订阅者 有一个信息中介,过滤 耦合性低
它定义了一种一对多的关系,可以使多个观察者对象对一个主题对象进行监听,当这个主题对象发生改变时,依赖的所有对象都会被通知到。
-两者的区别:
- 观察者模式中,观察者知道Subject ,两者是相关联的,而发发布订阅者只有通过信息代理进行通信
- 在发布订阅模式中,组件式松散耦合的。正好和观察者模式相反。
3.观察者大部分是同步的,比如事件的触发。Subject就会调用观察者的方法。而发布订阅者大多数是异步的()
4.观察者模式需要在单个应用程序地址空间中实现,而发布订阅者更像交叉应用模式。
组件化与模块化
组件化与模块化的不同:
模块化:是从代码逻辑的角度进行分析,方便代码分层开发,保证每个功能模块的只能单一
组件化:是从UI界面的角度进行划分,前端的组件化,方便UI组件的重用。
跨域
同源策略: 同协议同域名同端口
有几种方法
jsonp :
利用 <script> 标签,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。
缺陷 只能get方法
Cors
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
实现 CORS 通信的关键是后端,服务端设置 Access-Control-Allow-Origin 就可以开启 CORS
Nginx代理跨域
iframe
node.js中间件代理跨域
webSocket协议跨域
Proxy代理
postMessage是html5引入的API,可以解决跨域通信。
前端页面优化
- 减少HTTP请求
- 资源合并与压缩
比如 html压缩 css压缩 js压缩等等
- 合并CSS图片,减少请求数的又一个好办法。
- 图片懒加载 路由懒加载
- 减少DOM操作
- 利用浏览器缓存
- 在js中尽量减少闭包的使用
首屏加载速度优化
首屏不需要展示的较大尺寸图片,请使用lazyload
减少CSS背景图片的HTTP请求次数,使用雪碧图
http静态资源尽量用多个子域名
尽量减少HTTP Requests的数量
前端和后端是如何交互的
1,前端请求数据地址,是由后端返回,前端提供相关的查询参数
2,接口文档由后端返回,是最清楚数据是什么格式,前端只是被动接受,数据由后端修改
3,数据格式大多数为JSON,前端可以通过json.parse转为js对象
4,前端如何拒绝不属于自己的需求和任务?
前端只是负责把数据展示在页面上,清晰的知道自己要做的什么
5,后端返回的数据不是前端需要的?
前端需要后端倾诉需求,修改
Node
让JavaScript也能用于服务端编程,作为独立服务器运行,主要用于编写像Web服务器
Node.js是事件驱动的。可以在不使用线程的情况下开发出一个能够承载高并发的服务器。
微信小程序
WXSS是一套样式语言,用于描述 WXML 的组件样式, js逻辑处理,网络请求 json 小程序设置
app.json 必须要有这个文件,如果没有这个,项目无法启动,因为微信框架把这个作为配置入口,整个小程序的全局配置。包括页面注册,网络设置,以及小程序的window 背景色,配置导航条样式,配置默认标题。
app.js 必须要有这个文件,没有也是会报错!但是这个文件创建一下就可以 什么都不需要写以后我们可以在这个文件中监听并处理小程序的生命周期函数、声明全局变量。
app.wxss 配置全局 css
小程序与vue区别
1,声明周期不一样,微信小程序声明周期比较简单
2,数据绑定也不同,小程序数据绑定需要使用{{}} ,vue直接冒号
3,显示与隐藏,vue中 使用v-if show 控制,小程序使用vx-if hidden
4,数据双向绑定不一样
-----
Ios 安卓 这个是做混合app ,uniapp框架用vue开发,打包 ,安卓ios套个壳,里面用h5写,我觉得没有什么区别
微信小程序授权问题
从输入url地址到页面相应都发生了什么?
- 浏览器查找当前URL是否存在缓存,并比较缓存是否过期。
2、DNS解析URL对应的IP。 (dns就是解析地址)
3、根据IP建立TCP连接(三次握手)
4、HTTP发起请求。
5、服务器处理请求,浏览器接收HTTP响应。
6、渲染页面,构建DOM树。
7、关闭TCP连接(四次挥手)
1,客户端向服务端发送请求,要求建立连接。
2,服务器向客户端发送,可以建立连接。
3,客户端向服务端发送请求,服务器验证,建立连接。
1,客户端发送报文给服务端数据。
2,服务器收到消息,数据还没有完毕
3. 服务器已经完成,发消息给客户端
4,客户端发送消息,关闭连接
看过什么源码
状态码
2XX(成功处理了请求状态)
200 服务器已经成功处理请求,并提供了请求的网页
201 用户新建或修改数据成功
202 一个请求已经进入后台
204 用户删除成功
3XX(每次请求使用的重定向不要超过5次)
304 网页上次请求没有更新,节省带宽和开销
4XX(表示请求可能出错,妨碍了服务器的处理)
400 服务器不理解请求的语法
401 用户没有权限(用户名,密码输入错误)
403 用户得到授权(401相反),但是访问被禁止
404 服务器找不到请求的网页,
5XX(表示服务器在处理请求的时候发生内部错误)
500 服务器遇到错误,无法完成请求
503 服务器目前无法使用(超载或停机维护)
301/302/303都表示重定向
301表示永久重定向,表示请求的资源分配了新url,以后应使用新url。
302表示临时性重定向,请求的资源临时分配了新url,本次请求暂且使用新url。
302与301的区别是,302表示临时性重定向,重定向的url还有可能还会改变。
303 表示请求的资源路径发生改变,使用GET方法请求新url。
她与302的功能一样,但是明确指出使用GET方法请求新url。
Hybrid App(混合模式移动应用)
是介于 web-app(套壳)、native-app (原生)这两者之间的 app
因为 App 需要适应 android 跟 ios 双平台,需要开发两套系统,导致开发成本高以及版本迭代慢。
Hybrid App 是运用既包含类似移动端浏览器打开网站的相关技术,又包含原生应用调取底层接口(摄像头、传感器等等)的相关技术开发出来的应用。
优点
1.门槛低 ---> 只要了解前端三大件,就可以进行开发,不需要掌握 Android、IOS 相关知识。
2.速度快 ---> 如果应用中 HTML、CSS、JS 代码占比极大,那么,写应用界面就和写网页没区别,速度极快。
3.跨平台 ---> 一套代码搞定多平台,不用为了多个平台而准备多套代码。当然,适配及体验是肯定不如 Native ,但代码写的好的话,其实在主流机型上的适配和体验也都不错。