缓存 浏览器缓存和http缓存
浏览器缓存:
1,简单的缓存方式有cookie,localStorage和sessionStorage。
2,vue中keep-alive缓存动态组件:
全部缓存:使用<keep-alive>标签包裹缓存路由,router里设置name要与组件的name一致。
缓存部分:同上且在router里路由设置里meta:{keep Alive:true},然后在app.vue里
<keep-alive><router-view v-if=”$route.meta.keepAlive” /></keep-alive>
<router-view v-if=”!$route.meta.keepAlive” />
页面缓存了,有的功能需要再进入后,仍然重新执行:当引入keep-alive时,页面第一次进入,钩子的触发顺序时created->mounted->activated,退出触发deactivated,再次进入时只触发activated。因为当组件在keep-alive里切换时,组件里的activated和deactivated两个生命周期钩子函数被执行。
所以事件挂载的方法,只执行一次的放再mounted中;组件每次进去执行的方法放在activated中。
执行前进刷新,后退时缓存:router.js中a路由设置:meta:{ keepAlive:true } 组件钩子函数中设置:beforeRouteleave(to,from,next){ if(from.name=“c的路由名字”) to.meta.keepAlive = false } //c跳转到a时让a不缓存,即刷新,to表示要跳转的a
http缓存:
强缓存:cache-control。如Cache-Control:max-age=300
对于不常变化的资源:
通常在处理这类资源时,给它们的 Cache-Control 配置一个很大的 max-age=31536000 (一年),这样浏览器之后请求相同的 URL 会命中强制缓存。
对与频繁变动的资源:
使用 Cache-Control: no-cache,
引申问题:
浏览器如何实现图片缓存
Image对象的src属性来加载图片,并将其存储在浏览器的缓存中。
将图片路径赋值给src属性,浏览器将自动加载并缓存图片。当需要这张图片时,可以直接从缓存中取。
const image = new Image()
image .src=’path/to/image.jpg’
原理:Image对象是js中的内置对象,它代表嵌入的图像。当我们创建一个Image对象时,就相当于给浏览器缓存了一张图片。在HTML中<img>标签每出现一次,也就创建了一个Image对象。
3,Service Worker
使用 Service Worker 对项目静态资源进行离线加载,用户第二次进入页面直接从本地读取资源,速度飞快。
传输协议必须为 HTTPS
Service Worker 的缓存与浏览器其他内建的缓存机制不同,它可以让我们自由控制缓存哪些文件、如何匹配缓存、如何读取缓存,并且缓存是持续性的。
Webpack基本配置
Webpack实现懒加载
Webpack性能优化
Bable-runtime和babel-polyfill的区别
Webpack题:webpack:loader plugin 启动 打包体积
一:webpack构建流程:
在webpack根据配置,识别入口文件。在打包过程中,对资源进行处理,如压缩图片,scss转成css,es6语法转es5语法,typescript转javascript。Webpack的主要工具就是分析代码,转换代码,编译代码,最后输出打包代码。
一:谈谈你对webpack的理解或loader和plugin区别:
webpack 是一个静态文件打包器,只能处理js文件,对样式是没有办法的,因此要引入loader解析器,如css-laoder style-loader。就像一条生产线,要经过一系列处理流程(loader)后才能将源文件转换成输出结果。
Plugin插件就像是一个插入到生产线中的一个功能,在特定的时机改变生产线的运作。
1,webpck中的loader作用
webpack只能解析js和json文件,其他需要loader加载,所以Loader相当于翻译官,将其他类型资源进行预处理,最终变为js代码。如:
less-loader 将less文件编译成css文件。
style-loader 将js中的样式资源插入到标签内。
2,webpck中的plugin作用
Plugin功能更强大,主要目的是解决loader无法实现的事情,如打包优化和代码压缩。如:
Html-webpack-plugin 处理html,引入打包后的所有js和css
Clean-webpack-plugin 每次打包时,自动把上次打的包删除。
3,Babel是什么
Babel是js转码编译工具,把高版本语法编译成低版本语法。(即把低版本浏览器不认识的语法,编译成浏览器认识的语法)
二:Webpack性能优化项目启动提速-缓存 和 项目打包速度
1,首先可以安装一个插件分析启动速度speed-measure-webpack-plugin
缓存:局部缓存插件cache-loader和全部缓存插件hard-source-webpack-plugin
(npm run build,可以看到每个插件loader的耗时,
在一些性能开销较大的loader前面添加cache-loader,将结果缓存在磁盘中减少编译时间,
我的项目中,babel-loader耗时比较长,所以我给它配置了’cache-loader’:
module:{ rules:[ { use:[‘cache-loader’,’babel-loader’] } ] }
全部缓存,安装hard-source-webpack-plugin,安装后直接在plugins中new就可以。
)
局部缓存就是安装局部缓存插件然后在vue.config.js里配置规则
全部缓存就是通通缓存
2,打包体积优化 productionSourceMap:false、图片压缩、代码压缩、路由懒加载、noParse
首先安装一个bundle-analyser 打包项各个地方的大小。
Vue配置里productionSourceMap:false 打包时不要生成sourcemap>文件
安装图片压缩插件 image-webpack..
安装代码压缩插件 uglify-webpack..
路由懒加载,使用es6的resolve异步加载机制,require代替import。或用commonjs的import加载组件都可以实现路由的按需加载。
3,在vue.config.js里配置noParse配置不需要解析哪些文件,例如elementui,jquery
三:webpack配置
打包前会读取这文件: vue.config.js 或 webpack.config.js
vue-cli-service serve 启动的是 vue.config.js
webpack-dev-serve 启动的是 webpack.config.js
entry指定打包入口,output指定打包出口
proxy代理里的target指向新的http地址
webpack-dev-serve 配置热更新>
build 打包
引申问题:
webpack中的source map是什么?生产环境怎么使用?:
source map生产环境调试工具,将编译,打包后的代码映射回源代码的过程。
因为webpack打包后的代码不具备可读性,而有了source map,加上浏览器的dev tools,打开console控制台就能看到代码抛出的错误。
热更新原理:
安装webpack-dev-server
在vue.config.js里设置devServer { inline:true }
当我们设置了热更新后,打包生成的bundle文件不会真实的生成到dist目录下,而是在内存里。
- 删除过期模块
- 将新的模块添加到modules中
- 通过webpack_require 执行相关模块的代码
四:提升开发效率的webpack插件5个
图片插件:vue-lazylaod、image-webpack-loader、sprites
remove-console、productionSourceMap:false
- Vue-lazyload 图片懒加载插件:vue-lazyload
- Image-webpack-loader 图片压缩插件:image-webpack-loader,npm install image-webpack-loader,在vue.config.js中配置,设置压缩比率,如0.7
Config.module
.rule(‘images’)
.use(‘image-webpack-loader’)
.loader(‘image-webpack-loader’)
3, sprites 精灵图自动合成插件:sprites, 安装sprites插件, 1:配置中添加 精灵图地址,2,在代码中直接引用图片,例:‘assets/images/sprites/logo.png’
4, px转rem 自适应屏幕。Viewport插件:
5,remove-console 生成环境中控制台不打印console.log
安装 remove-console插件
在配置里配置,如果是生成环境则使用去掉console的插件
6,productionSourceMap:false 生产环境调试工具source-map
因生产环境代码被压缩,转译。而source map是将编译,打包后的代码映射回源代码的过程。
Sourcemap配合chrome可以提供一个debug线上项目的功能。只在打开控制台时才加载。
配置中: productionSourceMap:false
打开控制台右击add source map,出现webpack://,就可以调试对应的源码。
五:webpack模块打包原理
Webpack中的各种资源模块进行打包合并成一个或多个包(bundle),如javascript,css,图片,json等各个模块。在打包过程中,对资源进行处理,如压缩图片,scss转成css,es6语法转es5语法,typescript转javascript
vue常见性能优化方案:
vue属性 vue组件 html js css webpack
- 合理使用v-show,v-if,computed
2,v-for加key,避免与v-if同时使用。Diff算法通过tag和key确认是否sameNode。所以key的唯一性能让diff>算法更快的找到需要更新的dom。
3,Data层级不要太深,图片懒加载插件:vue-lazyload
4,组件:使用vue-router异步加载组件,路由懒加载,降低首次加载压力
5,组件:使用keep-alive缓存组件
6,自定义事件:DOM事件,定时器及时销毁:例如使用防抖和节流时使用lodash库,移除组件时在beforeDestroy销毁定时器。
7,清除页面死代码,如console.log,注释的代码等。
8,封装常用js,例如axios请求,日期转换
9,Css:封装css,增加复用性;减少css嵌套,最好不要嵌套3层以上;减少通配符*的使用;减少css表达式,表达式只是让代码显得更加酷炫,但对性能的浪费超乎想象。简化选择器;避免使用 !important;使用0而不是0px;使用十六进制而不是颜色名称。
10,Html:标签语义化;避免不必要的dom操作;相似的逻辑封装成组件;
11,webpack层面优化:① productionSourceMap:false 提升构建速度
vue.config.js 中设置productionSourceMap:false 在构建生产环境时 不要生成sourcemap文件,提高构建速度。
引申问题:
内存泄露:
自定义事件,定时器,在移除组件时beforeDestory销毁定时器;
闭包引起的内存泄露,在闭包函数内对引用变量置为null;
全局变量引起的内存泄露,不再需要时及时销毁;
diff算法:
1,将dom抽象为虚拟dom,diff算法对比新旧dom,只把变化的部分重新渲染。
Diff算法是通过js层面的计算,返回一个patch补丁对象,之后解析这个patch补丁对象,渲染>到页面上。
因为传统的dom渲染慢,消耗性能。Js在浏览器上运行快。
- 表示虚拟dom的js对象有3个属性:tag(元素标签名),props(元素属性),children(元素下级)
{ “tag”:”div”,props:{“color”:”red”,”id”:”idi”},children:[{}]}
3,diff算法规则:diff即比较,同层树节点进行比较。
只比较同一层级,不深度比较;如tag不同,则删掉重建;如tag和key都相同,则认为是相同节点,不再深度比较。
组件渲染/更新过程:render-vnode-patch
初次渲染组件:解析模板为render函数,生成vnode,并执行patch;
更新组件:同上面diff算法;
异步渲染组件:$nextTick()是异步渲染组件,汇总data的修改,一次性更新视图。好处:减少dom操作次数,提高性能。
模板编译:转js
模板不是html标签语言,模板有插值,指令,js表达式。所以模板一定是js代码。
一:谈谈对重构的理解
老的框架在新的业务形态下不再适应了,会进行重构,差不多就是重新实现一次吧,业务逻辑不变,主要时间花在理解代码上。
vue
一:Object.defineProperty和proxy区别
Object.defineProperty:vue2实现数据监听、响应的核心api;
遍历监听对象中的所有属性:data,props,computed。给每个属性添加getter和setter操作,当属性变化时更新视图。
缺点:1,只对对象劫持,递归到底,一次性计算量大。2,无法监听数组,vue重写了数组方法。
- 无法监听新增,删除属性,要调用vue.set(),vue.delete()方法。
proxy:vue3实现数据监听、响应的核心api;
对目标对象操作前设置了拦截,通过操作对象的代理来间接操作对象;
可监听数组变化;
可监听新增,删除属性
优点:性能更好,获取到哪一层,那层才会触发响应式。例如访问到a,不会再访问a里面更深内容。
区别:两者是否需要key属性
前者需要知道key,Object.defineProperty(data,’count’,{ get(){},set(){} })
后者不需要知道key, new Proxy(data,{ get(key){},set(key){} })
因为proxy无法兼容IE,vue检测就降级为Object.defineProperty的监听数据。
二:MVVM
数据驱动视图
View视图层,model数据层,viewmodel通过数据绑定,把视图层和数据层连接起来。
View和model层完全解耦,view展示的是viewmodel的数据,model层与viewmodel进行交互。
开发者只需要关注业务,无需手动操作dom
三:组件生命周期
BeforeCreate:el和data是undefined
Created:data有,el没有
BeforeMount:dat和el都有,但还没有虚拟dom
Mounted:实例挂载好,数据渲染好
BeforeUpdate:虚拟dom打补丁之前
Updated:patch打补丁好了,视图更新之后的操作在这里执行。
BeforeDestory:实例销毁前调用,如清定时器
Destroyed:实例销毁后,如移除监听器,子实例销毁
Keep-alive缓存时( activated、deactivated )
Router.js中某路由meta:{keepAlive:true}时( beforeRouteLeave )
四:父子组件生命周期钩子顺序
渲染:父beforeMount — 子beforeCreate— …… — 子mounted —父mounted
更新:父beforeUpdate — 子beforeUpdate — 子updated — 父updated
销毁:父beforeDestroy — 子beforeDestroy — 子destroyed — 父destroyed
五:ajax请求应放在哪个生命周期
1放在mounted里:实例已挂好,数据渲染好;
2放created里,使用$nextTick()完成数据绑定。
六:computed 缓存,data不变不会重新计算
七:keep-alive 缓存组件,不需要重复渲染,如多个静态tab切换
八:slot 缓子组件中放占位符<slot></slot> (或具名占位符),父组件中给占位符填充内容
九:v-show、v-if 缓v-show通过css的display控制显示和隐藏;v-if是真正的渲染和销毁。频繁切换用v-show,否则用v-if。
十:v-for的key diff算法通过tag和key确认是否为samenode,所以key的唯一性,能让diff算法找到需要更新的dom。
十一:何时使用beforeDestory 解除自定义事件this.$off();清除定时器;
自定义事件:1,子组件触发父组件的方法;2,dom事件如window和scroll
项目实例:
康兮项目里,有个页面需展示心电图表数据。设置定时器,展示完一分钟的心电数据后再次请求。之前没有清除定时器,导致占内存占的越来越大,页面很卡。之后改为再次进行下次请求前清除定时器并在离开此页面时在beforeDestory里清除定时器。
十二:组件的data必须是一个函数
组件中的data是一个class类,每个地方用的时候相当于这个类的实例化,实例出的data在一个闭包里,数据不会相互影响。如果data不是一个函数,那么每个组件的数据共享了,一个地方改其他地方跟着改。
组件的根实例只有一个,所以没有这方面的影响。
十三:如何将组件所有的props传递给子组件
$props 如:<User v-bind=”$props”>
三十七:dict字典
场景:固定下拉菜单内容。代码:dictTag组件里根据传入的tagType判断标签元素时radio还是radio-button还是select。根据传入的请求参数去请求数据。
……四十一:Vue.config.productionTip = false
四十二:Vue优缺点
缺点:1,vue2不支持ie8一下的,vue3不支持ie,如果是ie,会自动降为Object.defineProperty
2,因为是spa单页面应用,所以也不利于SEO
- 首屏加载时间长。
优点:1,双向数据绑定;2,组件化开发;3,轻量级数据框架
四十三:渐进式框架的理解
vue不要求我们一次性接受并使用它的全部功能。例如在已经做好的jquery项目上的某个页面种引入vue.js,
便可以直接在这个页面上使用它的声明式渲染功能。
四十四:为什么抛弃jquery,使用vue
- dom操作
A: jquery是操作dom,操作dom会给浏览器带来损耗,特别是大片的操作dom,浏览器会出现白屏或者等待很长时间。
B:Vue使用虚拟dom,不用频繁操作dom,提升了效率
- 业务
A:vue通过脚手架很好的整理项目文件,解决了业务分层的问题
B:jquery没有解决业务问题,依旧很乱。
四十五:第一次页面加载会触发哪几个钩子?
beforeCreate,created,beforeMount,mounted
四十六:computed、methods 、watch区别
Computed是属性调用,methods是函数调用,
Computed带有缓存功能,依赖于data中的数据,只有依赖的属性发生改变时,才会重新计算;methods不会被缓存。Computed的getter和setter。默认只有get,在需要的时候也可以设置set方法
Watch 1,监听data中数据。( firstname:function(new,old){} )
2,监听路由的变化( ‘$route.path’:function(new,old){})
四十七:vuex是什么?vuex的五个属性?怎么使用?哪些功能场景使用到?
给vue提供的数据管理库;
5个属性:state、getter、mutation、actions、module:
state:存放数据,类似于data。是共享的,但不可以直接修改state。
getter:类似于计算属性,主要用于过滤数据。
Mutations:定义方法,唯一更新state数据方式;mutation是同步操作,每次只能提交一个操作。
Action:将mutations里方法变成异步操作数据,可以提交多个mutation。View层通过store.dispath
来触发action。
Module:模块化管理store,如在module文件里包含user.js,shop.js等等模块,每个模块有自己的state,getter,mutations,action。
Vuex缺点:存储在xuex中的状态,刷新页面,会丢失。解决办法:安装插件 vuex-persistedState
场景:1,用户个人信息管理模块;2,购物车模块;3,订单模块:订单列表点击取消订单,然后更新对应订单的列表,state存储一个状态,监听这个状态,变化时更新对应的列表;
从订单结算页,进入选择优惠券的页面,选择优惠券的页面。如何保存选择的优惠券信息?state保存优惠券信息,选择优惠券时,mutations提交,在订单结算页,获取选择的优惠券,并更新订单优惠信息;
四十七:vuex和localStorage区别
vuex存储在内存中,组件之间传值,刷新页面时值会丢失;
localstorage存在本地,页面之间传值,刷新页面值不会丢失。
四十八:vue-router
route,routes,router三者区别:route是一条路由;routes是一组路由;router是一种机制,用来管理路由;
钩子函数三种:全局守卫,路由守卫,组件守卫
1,全局钩子:beforeEach、afterEach
页面加载之前执行beforeEach
router.beforeEach((to,from,next)=>{ })
页面加载之后执行afterEach
Router.afterEach((to,from)=>{ })
例如:路由守卫用到的RBAC权限控制思想:登录成功后,首先进入路由守卫,从后台获取用户权限获取用户权限菜单,展示左侧菜单。(src里创建permission.js权限控制里,import到main.js里。router.beforeEach()结合router.addRoutes()从后台获取权限菜单,使用addRoutes方法添加到动态路由里,完成菜单展示。)
2,路由钩子:beforeEnter、beforeLeave
指定路由跳转时逻辑
const routes = [
{
path:”/home”,component:Home,
beforeEnter: ( to,from,next)=>{},
beforeLeave: ( to,from,next)=>{}
}
]
3,组件内部钩子:beforeRouteEnter() 该组件对应的路由被进入之前调用
beforeRouteLeave()离开该组件的路由时调用
beforeRouteUpdate()该组件路由改变或复用时调用,如带有参数的路由/foo/:id,在/foo/1和/foo/2之间跳转时,组件被复用,这个钩子就会调用。
Vue-router有两种模式:hash模式和history模式
- hash指#后面的字符串,刷新不会重载页面
- history模式下会刷新当前页面,因此如果后端没有处理好,会报404页面。因此history需要后端配合重定向到首页路由。
路由守卫
1,登录成功后,首先进入路由守卫,从后台获取用户权限,在vuex中保存菜单信息。
路由守卫RBAC权限设计思想:根据用户权限动态生成左侧菜单。
在src里创建permission.js权限控制,import到main.js里。
思路:router.beforeEach() 结合 router.addRoutes() 使用,当用户登录成功后,首先进入路由守卫,调用接口获取该用户的权限菜单,使用addRoutes方法动态添加路由配置,完成页面菜单展示。
2,动态路由进行路由鉴权,结合vuex实现动态路由的路由鉴权,分为任意路由(都可以看到的路由),404路由(无法看到的路由),异步路由(根据不同权限展示不同路由组件)
四十九:使用路由来实现页面跳转的方式
1 <router-link to=”/path” />
2 this.$router.push() 跳转到指定url,会向history里添加一个记录
3 this.$router.replace() 跳转到指定url,不会像history里添加记录
4 this.$router.go(n) 前进或后退几个页面,类似于window.history.go(n)
五十:组件间5种通信方式
1 props 2 $on,$emit 3 事件总线$bus 适用场景万能 4 vuex 适用场景万能 5 slot 插槽
五十一:vue-cli用到了哪些技术6
vue-cli:vue脚手架,快速生成vue工程化项目
技术:1 vue.js 2 vue-router 3 vuex 4 axios 4 elementui 5 webpack
五十二:v-if和v-for不能同时使用
v-for的优先级高于v-if,先渲染再判断条件,所以,会渲染这个列表,造成性能浪费。
五十三:arr[index]为什么无法更新视图
Vue实现数据监听响应的核心api是object.defineProperty,不能监听数组变化。
Vue重写了数组方法,可以使用vue.splice()方法改变原数据。let arr = [1,2,3,4] arr.splice(1,1,22) //[1, 22, 3, 4]
五十四:相同的路由组件如何重新渲染
vue处于性能原因,共享组件将不会重新渲染,如果在使用相同组件的路由之间进行切换,则不会发生任何变化。如果想重新渲染,可以使用key。
路由:
const routes=[
{ path:”/a”,component:MyComponent },
{ path:”/b”,component:MyComponent }
]
相同组件渲染:使用key
<router-view :key=”$route.path”></router>
五十五:服务端渲染SSR
相因为vue构建的是SPA单页面应用,会导致SEO问题,加载速度慢等问题。为了解决这个问题,vue提供了一个叫做服务端渲染SSR方式。
SSR:vue应用程序在服务端上呈现为HTML,然后将HTML发送给浏览器端。
这样就能解决SPA渲染慢和SEO问题。
(搜索引擎只能读取HTML;在SSR种,HTML是在服务器上生成并发送到浏览器,因此加载更快。)
SSR缺点:加重了服务器额负担,当用户量多的时候,因为要在后端创建全新的vue实例,所以比请求数据浪费性能。
并不是所有网站都需要seo,比如企业网站,后台管理网站。
五十:热更新
安装webpack-dev-server
在vue.config.js里设置devServer { inline:true }
TypeScript
安装typescript是javascript的超集,typescript有着严格的类型系统。
一:如何在typescript中定义类
登录 ①token:1登录,token 2登录、退出 3token无感刷新 ②cookie记住密码、rsa加密 ③路由守卫
token,token无感刷新
登录是不需要token的,所以首先在封装axios时,请求拦截器里要设置是否需要设置token,其他请求里是需要携带token的。
登录退出会统一写在store的action里,登录成功后把token使用vuex-persistedstate做数据持久化,防止刷新数据没有。之后的请求放在header的 Authorization 属性里
token设置无感刷新:使用双token的方式进行无感刷新,流程:登录后客户端得到两个token(access_token,refresh_token)其中access_token用来鉴别身份,refresh_token刷新access_token;它过期时,再发送refresh_token,获取到新的access_token和refresh_token,有点懒加载的意思。
token过期:axios拦截请求判断后台token是否过期,过期则跳转到登录页。
记住密码,rsa加密:
cookie记住密码:使用cookie插件把token存在cookie里。下次登录时再取出来登录。
rsa加密:使用jsencrypt.js加密,公钥和私钥两把钥匙。公钥字符串在前端,私钥在后端解密。使用公钥对密码进行加密发送给后端。一般认为md5加密不太安全,一般用来做数字签名,rsa一般用于密码加密。
路由守卫
1,登录成功后,首先进入路由守卫,从后台获取用户权限,在vuex中保存菜单信息。
路由守卫RBAC权限设计思想:根据用户权限动态生成左侧菜单。
在src里创建permission.js权限控制,import到main.js里。
思路:router.beforeEach() 结合 router.addRoutes() 使用,当用户登录成功后,首先进入路由守卫,调用接口获取该用户的权限菜单,使用addRoutes方法动态添加路由配置,完成页面菜单展示。
2,动态路由进行路由鉴权,结合vuex实现动态路由的路由鉴权,分为任意路由(都可以看到的路由),404路由(无法看到的路由),异步路由(根据不同权限展示不同路由组件)
svn
- Svn安装
安装svn客户端软件tortoiseSvn
Svn建好后,发送url给其他人拉取资源
别人在svn上checkout后填入url,拉取资源
之后每次上传文件前,都要update更新下文件再add,commit
2,使用
①在svn上创建目录
②在本地文件目录checkout,会有个.svn文件
③把本地代码文件复制到这个checkout了的文件目录里,submit提交。
冲突解决步骤:
如果按提示update,之后还显示冲突。Edit conficts 编辑冲突,打开之后窗口里有三个文档,左右下。下面是最后成果,需要左右两份不同版本,合成最终版,Theirs为服务器上当前最新版本,Mine窗口为本地版,Merged窗口为合并后的文件内容。Resolved 冲突解决,报告给svn。Commit黄色警告不见了,变为平时的红色已修改标记,现在可以正常commit了。
git
1,Svn安装
安装svn客户端软件tortoiseSvn
Svn建好后,发送url给其他人拉取资源
别人在svn上checkout后填入url,拉取资源
之后每次上传文件前,都要update更新下文件再add,commit
2,使用
①在svn上创建目录
http
http是超文本传输协议。基于TCP/IP通信协议传输数据。工作于客户端-服务端上
- 客户端通过url向服务端请求数据
- 服务端传输超文本到本地浏览器
https是http的安全版,SSL位于TCP/IP协议与应用层之间
- http是明文传输,https是密文传输
- http默认端口80,https默认端口443
一:http的请求报文由三部分组成:请求行,请求头,请求体(请求参数)
请求行:Request URL
Request url> : 请求地址
Request Method:请求方式
Status Code:200 状态码>
请求头,Request Header
Host:主机ip地址或域名
Authorization:权限认证,如token
Cookie:cookie信息
Content-Type:请求体内容类型,如 content-Type:application/javascript 还有 multipart/form-data 在使用表单上传文件时,必须要<form enctype=“multipart/form-data” />必须要是这个值。
Cache-Control:如 cache-control:no-cache (防止页面缓存)
……
响应头 Response Header
Server:Http服务器的软件信息
Date:响应报文时间
Expires:缓存过期时间
Set-Cookie: 由服务器发送一个Hppt-cookie 到浏览器
Content-Type:响应的类型
二:get和post区别
相同:get和post底层也是TCP/IP>协议,get和post能做的事情都是一样一样的。你要给
Get加上request body,给post加上url参数,技术上完全行的通。但是由于http的规定和服务器的限制,导致他们在应用过程中体现出一些不同。
get一般用于请求数据,post一般用于发送数据
不同:get不安全(url直接暴露在url上)
get参数长度限制(2083字符)post请求参数没有大小限制
三:http请求报文和响应报文格式
请求报文:请求行,请求头,请求参数
响应报文格式:状态行,消息报文,响应报文
引申问题:
状态码:
100:信息响应 101mqtt>链接成功
200:成功响应
300:重定向
400:客户端错误 404服务器未找到请求页面 401未授权
500:服务端错误
浏览器输入URL之后的过程(页面加载过程)
如果浏览器有缓存,直接显示在页面上;
否则发送http请求,发送http请求前,域名被解析获取响应的ip地址;
服务器与浏览器建立tcp三次握手>;
握手成功后,浏览器向服务器发送http请求;
服务器将数据返回给客户端浏览器,浏览器解析渲染到页面上。
TCP/IP协议三次握手四次挥手
三次握手:
客户端和服务器建立连接,作用是双方的接收能力和发送能力是否正常。
第一次握手:客户端 发送报文 给服务端 (客户端发送正常,服务端接收正常)
第二次握手:服务端 应答报文 给客户端 (服务端发送正常,但服务端不知客户端接收正常,)
第三次握手:客户端 发送报文 给服务端 (服务端知客户端接收正常)
客户端 服务端
客户端 服务端
客户端 服务端
四次挥手:
客户端和服务器终止连接:
客户端发送fin给服务端 (客户端对服务端说:我要关闭)
服务端发送ack给客户端 (服务端说:我知道了)
服务端发送fin给客户端 (服务端说:你关吧)
客户端发送ack给服务端 (客户端对服务端说:我关闭了,服务端收到后也关了)
客户端 服务端
客户端 服务端
客户端 服务端
客户端 服务端
Mqtt和websocket:
是都是应用层协议,底层都是tcp协议确保传输数据,支持双向通信
websocket是为了h5设计,取代长轮询,浏览器都支持,不用引用单独js,发消息不需要对方确认。
mqtt是为了物联网设计,比较复杂,需要引用mqtt的js,需要设置主题,账号密码,链接成功需要订阅,才能收到消息。这个我之前在项目里做过,例如我之前做的梦宇小程序,上传头像成功后,mqtt链接接口地址,等待接收到后生成3d人偶,接收到后台返回的3d人偶数据进行页面展示。算法由美国团队提供。
websocket更简单,灵活,mqtt相对复杂,但功能强大。
跨域:
解释:不同域之间相互请求资源,就是跨域。跨域只是浏览器把请求结果给拦截了,服务端能收到请求并返回结果。跨域不是问题,而是一种安全机制,协议、域名、端口相同的同源策略,是为了保证用户安全。
- 允许跨域加载资源的标签:<img> <link> <script>
- 同源策略限制的内容:cookie,localstorage存储,dom节点,ajax请求
解决跨域:
- jsonp跨域: callback函数返回给浏览器。浏览器解析执行,前端拿到callback返回的数据。
原生js;ajax;axios
- cors跨域:在请求头中设置origin字段,accsee-control-allow-origin:* 接收任意域名的请求
3,vue的 webpack.config.js 设置proxy代理
跨二级域名共享cookie:一级域名相同,二级域名不同
document.cookie = “name = value;domain=.google.com”
所有google.com下的主机都可以访问该cookie;
Cookie,sessionStorage,localStorage区别:本地,大小,有效期,作用域
- cookie数据发送给服务器,sessionStorage和localStorage保存在本地
- cookie存4kb,sessionStorage和localStorage存5M
- cookie设置有效期,sessionStorage关闭窗口前有效,localStorage设置有效期或永久保存
- cookie和localStorage同源窗口共享,sessionStorage不在不同的窗口中共享
mqtt和websocket相同和不同:
相同:1都是应用层协议;2底层都使用TCP协议确保传输数据;3支持双向通信
不同:1websocket是为了H5设计,取代长轮询,报文结构简单,发消息不需要对方确认;
2mqtt是为了物联网设计,报文结构复杂,发消息需要对方确认;
多个标签页之间的通信:本质上是通过中介者模式实现的
方式1:websocket 发送消息给服务器,服务器把消息推送给所有链接的客户端
方式2:localStorage 在另一个浏览器中去执行添加删除操作会触发storage事件,可以监听storage事件实现标签之间的通信。
四:http优化
1,减少cookie:
每次请求都会被发送到服务端,所以尽量减少臃肿的消息首部。
2,使用connection:keep-alive:
一定程度上复用tcp,减少tcp连接的建立。
(一个网页打开后,客户端和服务器之间用于传输http数据的tcp连接不会关闭)
微信小程序
一:setData数据太大解决方法
微信小程序文档中规定setData的单次渲染数据大小不超过1024kb
解决方法:1,分页请求数据;2,二维数组,避免一次性渲染数据太大
二:登录流程 wx.login
调用微信wx.login api 返回code传给后端服务器,返回openid等信息,这时候就登录成功了。
三:支付流程 wx.requestPayment
1,请求后端获取支付所需要的参数,如 appId,nonceStr,signType,package,paySign,totalFee
之后客户端发起微信支付请求调用 wx.requestPayment
2,微信公众平台准备:管理员填写商户号,微信支付的银行卡账号等。
四:授权信息和获取用户手机号
五:分享
六:发布流程
首先小程序开发工具要填写微信公众号注册的appid,代码由微信小程序开发软件提交至微信公众平台上,进入微信公众平台提交审核,审核通过会有个体验版,再正式发布就可以了。
审核不通过原因:1,服务类目不匹配。(在初次提交审核时,会要求填写相关信息,如业务范围,用途等,所以应该时没有选择相应的类目,如果时食品行业需要提交食品经营许可证,上次做惠点菜就是)
2,有的服务内容不支持,例如虚拟支付(例如,梦元空间的小程序,虚拟支付就不行)
七:生命周期函数
应用生命周期函数在app.js中声明:
onLaunch:小程序初始化完成时触发,全局只触发一次。先于页面触发。
OnShow:小程序启动,或从后台进入前台显示时触发。先于页面触发。
OnHide:从前台进入后台时触发。
OnError:小车关系发生脚本错误或api调用报错时触发。
OnPageNotFound:打开的页面不存在
页面声明周期:
页面加载->渲染->销毁的过程
OnLoad:页面创建时执行,一个页面生命周期中只调用一次。
OnReady:页面首次渲染完毕后执行,一个页面生命周期只执行一次。
OnShow:页面出现在前台执行
OnHide:从前台变为后台时执行
OnUnload:页面销毁时执行
OnPullDownRefresh:下拉刷新时
OnReachBottom:页面触底
OnShareAppMessage:分享页面
OnPageScroll:页面滚动
八:小程序内页面5种跳转
1,<navigator /> 相等 <a/>标签
2,wx.navigateTo 相等 写在js里,功能同上
3, wx.redirectTo 相等 window.open(‘…’) 关闭当前页面跳转其他页面
4,wx.reLaunch 关闭所有页面,跳到其他页面
5,wx.switchTab 跳转到tabBar页面
html5和css
一:html5新特性
分语义化标签:header、nav、article、section、footer
音频视频:audio、video
地理位置,本地存储、会话粗存:geolocation、localstorage、sessionstorage
多任务、双工通信:webworker、websocket
二:css有哪些基本选择器,执行先后顺序?
类选择器(class),id选择器,标签选择器
!Important 10000 > 内联样式 1000 > id 100 > class、属性选择器、伪类选择器(:hover) 10 > 标签1 > 通配符* 、子选择器、相邻选择器等等为0
三:css两栏布局,左边固定宽度,右边自适应
flex布局:容器设置display:fle;左侧元素设置宽度;右侧元素flex:1
js
一:怎么理解this
使用场景:1,全局作用域中this指向window
2,普通函数中this指向当前对象
3,箭头函数中this指向上级作用域
4,apply、call、bind中this指向传入的对象
二:短路运算符
逻辑&&和逻辑||
vue-devtools 调试工具
Chrome 浏览器插件vue-devtools :下载好devtools插件,拖入到chrome扩展插件里面,安装完成。
检测内存泄露:
控制台选择perfomance下的memory点击选择 Collect JavaScript CPU Profile 单选按钮过二十几秒后点击stop按钮停止。
用Heap snapshot快照的方式,记录几次快照,比较前后的内存中,各个对象的数量变化,如果有大量该对象,或比对中,数量差异明显,则可能存在泄漏。之后点击memory查看占比情况。
检测内存泄露:
1:控制台选择perfomance
2:勾选memory
3:点击左上角record(小红点)
4:在页面上模拟用户操作
5:一段时间后,点击对话框中的stop按钮,面板上就会显示这段时间的内存占用情况。
6:控制台选择Memory
7: 点击第二个按钮Allocation instru...... 然后点击Start按钮
8:观察几分钟查看这个蓝色波动是否有逐渐消失
8.1有消失证明没有泄露
8.2没有消失证明页面有内存泄露
Devtools:
在main.js里设置Vue.config.devtools === true时才可使用devtools
开发版默认为true,生产版本默认为false。
如下图,Vue开发者工具主要分为3大部分,依次是上侧的功能选择区域---用于切换组件、Events等功能,
当你给每个组件设置了name属性后,可以通过这一点,快速定位组件。
左侧的组件选择区域---用于选择组件,右侧的数据筛选区域---用于查看当前组件的数据,包括props、data、Vuex、computed。
1,左侧组件区域使用技巧
在数字1处的输入框,可输入组件名进行快速定位组件。点击组件名前的小三角,可以展开它的子组件
2,右侧数据区域使用技巧
右侧数据区域展示了props、data、computed、$route里的数据。
2.1 如图,可在数字3处的filter inspected data的输入框中,输入你想查找的数据名,比如test,此时就会将当前组件含有test的数据过滤出来,包括含有test的对象和数组。
2.2 如果你想抓取一个数据,只需要将鼠标放在这条数据上,点击竖向排列的三个点按钮,就可以copy这个值。我经常用这个功能,将复杂的数据抓取出来,放到查看器中查看。
调试vuex
点击components右边的vuex按钮,可以调试store里的数据。可以实时查看当前store中的值状态,以及每次commit的历史记录。
三、常见问题
1、修改完代码,界面热更新后,数据展示空白了。
此时点击一下左侧任意组件名即可。或者关闭F12再打开。
2、有时无法通过select点击选择想要的组件。
多是被vue内置组件transition遮盖了,此时不要执着于一次选中想要的组件,可以尝试select目标组件的父、子组件,然后再在左侧的组件选择区域一层层查找一下即可。
async、await
async返回一个promise对象,await命令后是一个promise对象。
必须等到内部所有await命令后面的promise对象执行完,才会执行then方法指定的回调函数。Await命令后面的promise对象如果变为reject状态,则reject的参数会被catch方法的回调函数接收。
①如果希望即使第一个异步操作失败,也不要终端后面的异步操作:将第一个await放在try...catch结构里面,这样不管这个异步操作是否成功,第二个await都会执行。
②如果有多个await命令,可以统一放在try...catch结构中。
③多个await命令后面的异步操作,如果不存在继发关系,最好让它们同时触发。
Let [ foo,bar ] = await Promise.all( [ getFoo(), getBar() ] )
项目中遇到的最大问题?
很多小程序登录都是授权登录,但是龙潭加水小程序需要账号密码登录(不调用需要授权的API--不需要openId)。图片验证去校验,直接插入html的验证码,但是前端无论怎么提交后端返回验证码错误,但我用postman测试一直能成功登录,放到小程序里就不行。
和后台交流问题,他截图说postman请求没问题。我让他返回base64的看看,但他说postman没问题,不愿意。
Pc端提交验证码无误,那么验证码的校验过程是什么样的?原来这个插入到html的验证码获取时候,浏览器会主动保持[‘Set-Cookie’]里面的值PHPSESSID,这个值就是后端加密的图片验证码数字的字符串。然后提交验证码时后端再取cookie的PHPSESSID解密。然后小程序论坛上发现,小程序不会主动存储【’Set-Cookie’】,所以后端一直拿不到这个PHPSESSID。
然后我手动存这个,我前端怎么手动存?下载图片,去请求中的取header【’Set-Cookie’】,保存起来,提交验证时把保存的header带上,然后验证成功,问题解决。
总结:要找到解决问题的方向和思路。
优秀博客
技术胖,这是个人网站 JSPang.com ,经常看vue相关内容。
阮一峰,经常看es6的相关知识。
CSDN社区,社区很活跃,很多人在这里分享。
vue项目文件结构8
打包:build、dist;主体:public、src、static、index.html; 插件:package.json、node_modules;配置:vue.config.js
- build:构建脚本目录
build.js 生产环境构建脚本
Utils.js 构建相关工具方法
Webpack.base.conf.js webpack开发环境配置
Webpack.dev.conf.js webpack开发环境配置
Webpack.prod.conf.js webpack生产环境配置
二,public 静态资源文件
存放不需要经过构建处理的静态资源文件。会被直接复制到最终打包后的输出目录中。
三,src:这里是我们开发的目录,基本上做的事情都在这个目录里。
assets 静态资源,放置图片字体等
Components 存放自定义组件
Router 路由目录(配置的路径写在index.js里)
Store vuex目录
Views 项目页面目录
App.vue 根目录(vue应用的根节点组件)
Main.js 应用入口文件(初始化vue应用,主要是引入vue框架,定义vue实例,挂载元素、路由、仓库。还会注册全局组件,全局方法。)
四,Static:公共js,公共css
五,Index.html 首页入口,可以添加meta信息
六,Package.json 依赖包信息
七,node_modules: npm加载的项目依赖模块
八,vue.config.js文件,是一个可选配置,1,如在根目录中,它会被@vue/cli-service自动加载。
九,dev.env.js 开发环境变量 Prod.env.js 生产环境变量
2,也可以使用package.json中的vue字段,需要尊周json格式。
uni-app中的应用生命周期,页面生命周期,组件生命周期
一、应用生命周期(写在app.vue中)
- onLaunch:当整个项目启动,渲染完成时触发(全局只触发一次)
- onShow:小程序显示出来(从后台进入前台显示,可以触发多次)
- onHide:小程序隐藏起来时触发(从前台进入后台,可以触发多次)
- onError: 出现异常时触发
- 页面生命周期(page.json配置路径)
onLoad 监听页面加载,
onShow 监听页面显示
onReady 监听页面初次渲染完成。
onHide 监听页面隐藏,通过tabbar切换页面
onPullDownRefresh 监听用户下拉动作,一般用于下拉刷新。
onReachBottom:上拉加载,页面滚动到底部的事件,在事件中可以加载下一页数据
- 组件生命周期
activated(): 当前组件被激活时显示,
beforeCreate(): 在实例初始化之后被调用,
created(): 在实例创建完成后被立即调用
beforeMount(): 在挂载开始之前被调用.
mounted(): 挂载到实例上去之后调用,
beforeUpdate(): 数据更新时调用,发生在虚拟 DOM 打补丁之前
updated(): 由于数据更改导致的虚拟 DOM 重新渲染和打补丁
beforeDestroy: 实例销毁之前调用
destroyed(): Vue 实例销毁后调用
如何区分页面和组件:组件是引用的,页面是跳转的且需要在pages.json中配置路径。
微信小程序应用生命周期
应用生命周期(写在app.js中)
onLaunch---监听小程序的初始化
onShow---监听小程序启动或切前台(展示小程序)
onHide---监听小程序切后台(隐藏小程序)
onError---错误监听函数
页面生命周期
onLoad---监听页面加载
onReady---页面初次渲染
onShow---页面显示
onHide---页面隐藏
onPullDownRefresh---用户下拉
onReachBottom---上拉触底
onShareAppMessage---右上角分享
组件生命周期 carmd
created---监听页面加载
attached---监听页面显示
ready---监听页面初次渲染完成
moved---监听页面隐藏
detached---监听页面卸载
微信小程序跳转微信公众号
三种方法
- 跳首页:直接放公众号二维码,在小程序里长按识别就能跳转。(最简单)
- 跳首页:公众号组件<official-account></official-account>跳转(场景有需求:弹框形式出现)
- 跳文章页:Webview内嵌的公众号文章链接(需在公众平台配置)
对Webpack的理解?
WebPack 是一个模块打包工具,可以使用WebPack管理模块,并分析模块间的依赖关系,最终编绎输出模块为HTML、JavaScript、CSS以及各种静态文件(图片、字体等),让开发过程更加高效。
对于不同类型的资源,webpack有对应的模块加载器loader,比如说:
CSS:解析CSS的css-loader、style-loader,解析less的less-loader,sass的sass-loader,
JS:解析将 TypeScript 转换成 JavaScript的ts-loader,解析ES6为ES5的babel-loader,解析JavaScript 代码规范的eslint-loader
Vue:解析.vue文件的vue-loader、
解析常用图片以及音视频资源的url-loader、
解析文件的file-loader,
解析 JSON 文件的json-loader等
Webpack的常用配置? entry,output / loader / plugin / resolve / devserve
1,配置入口和出口:entry指定了项目的入口,output指定了项目打包后的文件路径和文件名。
module.exports = {
entry: './src/main.js',
output: {
path: __dirname + '/dist',
filename: 'bundle.js'}};
2,配置loader:当webpack在编译时遇到以.css结尾的文件,就使用css-loader和style-loader来加载这个文件。
module: {
rules: [{ test: /\.css$/,use: ['style-loader', 'css-loader']}] }
3,配置plugin:使用hard-source-webpack-plugin全部缓存
module.exports = {
plugins: [new hardSourceWebpackPlugin()]
}
4,配置resolve:用于指定webpack在编译时要优先查找哪些文件或模块。比如,配置extensions可以让webpack将.vue、.js和.json文件视为模块,并且在import时可以省略后缀名。alias配置则是设置项目中的路径别名,在引入文件时简化路径。
module.exports = {
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {'@': resolve('src')}}
}
5,配置代理服务devServer:
用于host:服务器外部可以访问;port:指定监听的请求的端口号;open:自动打开页面;proxy:代理某些url
module.exports = {
devServer:{
host:0.0.0.0,
port:8080,
open:true,
proxy:{
'/api':{
Target:'http://127.0.0.10:3000'
}
}
}
}
http问题合集
1,谈下你对 HTTP 长连接和短连接的理解?分别应用于哪些场景?
长短连接指的是TCP连接。
HTTP/1.1 开始默认使用的长连接,只需要建立一次TCP连接就能进行多次HTTP通信。减少了TCP连接重复建立和断开所造成的开销。一般用于操作频繁、点对点的通讯,比如数据库连接采用的就是长连接,网络游戏这类应用也采用的长连接。
HTTP/1.0 默认使用的短连接。客户端每进行一次 HTTP 请求,就建立一次连接,任务结束就中断连接。WEB网站采用的短连接,因为网站上客户端的连接数会非常多,如果采用长连接,就会占用非常多的资源,所以一般采用短连接。
2,HTTP2.0与1.x的区别
多了四个新特性:二进制分帧层、服务端推送、首部压缩、多路复用
服务端推送: HTTP/2.0 在客户端请求一个资源时,会把相关的资源一起发送给客户端,客户端就不需要再次发起请求了。例如客户端请求 page.html 页面,服务端就把 script.js 和 style.css 等与之相关的资源一起发给客户端。而 HTTP 1.0 需要请求一次 html,然后再请求一次 css,然后再请求一 次 js。
3,HTTP与HTTPS有什么联系?它们的端口号是多少?
HTTP通常承载于TCP之上,在HTTP和TCP之间添加一个安全协议层(SSL或TSL),这个时候,就成了我们常说的HTTPS。HTTP默认的端口号为80,Https默认的端口号为443。
- 为什么https更安全
在网络请求中,需要有很多服务器、路由器的转发。其中的节点都可能篡改信息,而如果使用HTTPS,密钥在终点站才有。HTTPS之所以比HTTP安全,是因为它利用 SSL/TLS协议传输。它包含证书、卸载、流量转发、负载均衡、页面适配、浏览器适配、 refer传递等技术,保障了传输过程的安全性。
- 完整的HTTP事务流程是怎样的?
- 解析域名获取响应的ip地址
- 发起TCP的3次握手
- 建立TCP链接后发起HTTP请求
- 服务端返回数据给浏览器,浏览器解析html代码渲染到页面。
- 什么是HTTP?
HTTP是客户端和服务端之间数据传输的规范,表示“超文本传输协议”
- 什么是HTTP无状态协议?如何克服HTTP无状态协议的缺陷?
- 无状态协议对十五处理没有记忆能力
- 克服无状态协议缺陷的办法是通过cookie和会话保存信息。
- HTTP有哪些请求方式?
- GET:获取资源
- POST:传输信息给服务器
- PUT:传输文件
- DELETE:删除文件,与PUT方法相反
- HEAD:与get方法类似,但不返回报文主体,一般用于验证url是否有效
- OPTIONS:查询响应url支持的http方法
9,HTTP协议中1.0版本规范与1.1版本规范的区别是什么?
在HTTP1.0中,当建立连接后,客户端发送一个请求,服务器端返回一个信息后就关闭连接,当浏览器下次请求的时候又要建立连接。显然,这种不断建立连接的方式会造成很多问题。
在HTTP1.1中,引入了持续连接的概念。通过这种连接,浏览器可以在建立一个连接之后,发送请求并得到返回信息,然后继续发送请求再次等到返回信息。也就是说,客户端可以连续发送多个请求,而不用等待每一个响应的到来。
10,与HTTPS相比,HTTP有什么缺点?
(1)通信使用明文,不加密
(2)不验证通信方身份,可能遭到伪装
(3)无法验证报文完整性,可能被篡改
11,HTTP1.1版本的新特性有哪些?
(1)默认持久链接
(2)客户端可以发送多个HTTP请求,而不用一个个等待响应。
(3)断点续传原理
- 已经建立的tcp链接是否会自己主动断开。时间是多久?
一旦链路上没有数据发送,server端非常快的就关闭链接。
也就是说事实上http长链接非常容易在空暇后自己主动断开,一般来说这个时间是300s左右。
- 网络分层模型有哪七层?
(1)应用层:允许访问OSI环境的手段。
(2)表示层:对数据进行翻译、加密和压缩。
(3)会话层:建立、管理和终止会话。
(4)传输层:提供端到端的可靠报文传递和错误恢复。
(5)网络层:负责数据包从源到宿的传递和网际互联。
(6)数据链路层:将比特组装成帧并实现点到点的传递。
(7)物理层:通过媒介传输比特,确定机械及电气规范。
13,网络七层模型中,你所熟知的协议有哪些?
(1)ICMP,即因特网控制报文协议。是TCP/IP协议族的一个子协议,用于在IP主机、路由器之间传递控制消息。
(2)HTTP,即超文本传输协议,是一个属于应用层的面向对象的协议,由于其简捷快速的方式,适用于分布式超媒体信息系统。
14,讲讲304缓存的原理
304是HTTP状态码,服务器用它来标识这个文件没有修改,不返回内容,浏览器在接收到个状态码后,会使用浏览器已缓存的文件。
客户端请求页面A。服务器返回页面A,并给A加上一个ETag。客户端展现该页面,并将页面连同ETag一起缓存。
客户端再次请求页面A,并将上次请求时服务器返回的ETag起传递给服务器。
服务器检查该ETag,并判断岀该页面自上次客户端请求之后还未被修改,直接返回响应304(未修改一 Not modified)和一个空的响应体。
- Expires和Cache-Control的作用是什么?
Expires要求客户端和服务器端的时间严格同步。HTTP1.1引入Cache-Control来克服 Expires头的限制。如果max-age和 Expires同时出现,则max-age有更高的优先级。
Cache-Control:no-cache, private, max-age=0ETag:"8b4c-55f16e2e30000"Expires:Thu, 02 Dec 2027 11:37:56 GMTLast-Modified:Wed, 29 Nov 2017 03:39:44 GMT
16,反向代理?
反向代理( Reverse Proxy)是指通过代理服务器来接收互联网上的连接请求,然后将请求转发给内部网络上的服务器,并把从服务器上得到的结果返回给互联网上请求连接的客户端,此时代理服务器对外就表现为一个反向代理服务器。
uniapp常见面试题
1,uniapp与vue和微信小程序的异同点
Uniapp就是用着vue的指令和小程序的组件和api。
指令:v-for、v-if、v-show、v-model、v-on、v-bind
组件:view、icon、text、swiper、image、button
2,uniapp中配置tabbar的方式(pages.json里配置)
"tabBar": {
"color": "#7A7E83",
"selectedColor": "#3cc51f",
"borderStyle": "black",
"backgroundColor": "#ffffff",
"list": [
{
"pagePath": "pages/index/index",
"iconPath": "static/bottomTabBar/home2_icon.png",
"selectedIconPath": "static/bottomTabBar/home1_icon.png",
"text": "分享"
}]
}
3,注意下拉刷新和触底加载的使用
OnPullDownRefresh监听下拉刷新动作
OnReachBottom 监听触底加载数据
4,uniapp的配置文件,入口文件,主组件,页面管理
pages.json 配置文件,全局页面路径配置,应用的状态栏、导航栏、标题、窗口背景色。
main.js 入口文件,初始化vue实例,定义全局组件、使用需要的插件如vuex,但uniapp无法使用vue-router,路由必须在pages.json中进行配置。如果非要用vue-router,可以在插件市场里找到转换插件。
app.vue 主组件,所有的页面都是在App.vue下进行切换的,是页面入口文件。应用生命周期在App.vue中监听。
pages 页面管理,存放页面
manifest.json应用配置文件,例如微信小程序配置,有一些选项,如:是否es6转es5,是否上传代码自动压缩,是否检查安全域名
Package.json 安装的插件
5,uniapp的本地缓存
同步存储:uni.setStorageSync,获取:uni.getStorageSync
异步存储:uni.setStorage,获取:uni.getStorage
6,uniapp的全局变量怎么设置和获取
小程序里有globalData概念,可以在App上声明全局变量,Vue没有这概念,但uniapp引入了globalData概念,在App.vue中定义。
赋值:getApp(). globalData.text = “test”
取值:console.log( getApp().globalData.text )
<script>
export default {
globalData: {
text: 'text'
},
onLaunch: function() {
console.log('App Launch')
},
onShow: function() {
console.log('App Show')
},
onHide: function() {
console.log('App Hide')
}
}
</script>
7,vuex
1,在uni-app项目根目录下新建store目录,在store目录下创建index.js定义状态值
2,在main.js挂载vuex
3,在pages/index/index.vue使用
8,uniapp页面之间传值
- 地址后拼接:uni.navigateTo({url:’gettaskList?Id=${id}’})
接收时,在页面的onload函数中接收传递过来的参数 onload(option){}
- 值传递对象:由于url长度限制,需使用encodeURIComponent,接收同上
// item 为该列表的每一项的数据对象;encodeURIComponent 为uniapp 提供的api
getTaskList(item) {uni.navigateTo({url: `getTaskList?item=${encodeURIComponent(JSON.stringify(item))}`,});
}
- uni.setStorageSync和uni.getStorageSync
- Uni.$emit和uni.$on
9,uniapp选取位置信息
1, 首先在mainfest.json文件中添加定位权限,在permission权限对象中添加location权限。
{
"permissions": {
"location": {
"desc": "你的位置信息将用于地理位置选择功能"
}
}
}
2, 使用uni.chooseLocation实现地理位置选择
Uni.chooseLocation({
success:function(res){},
fail:function(error){}
})
vue项目引入svg图标的完整步骤
- 安装svg依赖
- 创建svgicon公用组件
- 在assets文件夹下创建icons文件夹存放本地svg图标和index.js导入所有svg图标,index.js里注册全局组件svgicon。
- Main.js中引入icon/index.js
- Vue.config.js中配置svg文件路径
1,安装svg依赖
npm install svg-sprite-loader --save-dev
3,创建index.js导入所有svg图标
4,main.js中引入index.js
5,vue.config.js中配置svg地址
6,创建svgicon公共组件
Webpack插件11个
// Html-webpack-plugin 处理html,引入打包后的所有js和css
speed-measure-webpack-plugin 分析启动速度
cache-loader 局部缓存插件
hard-source-webpack-plugin 全部缓存插件
bundle-analyser 打包项各个地方的大小
image-webpack-plugin 安装图片压缩插件
uglify-webpack-plugin 安装代码压缩插件
Vue-lazyload 图片懒加载插件
sprites 精灵图自动合成插件
remove-console console.log : 生成环境中控制台不打印
Clean-webpack-plugin dist : 每次打包时,自动把上次打的包删除。
Vue插件7个 文件vue-lazyload、vue-upload、vue-json、vue-infinite、moment、noprogress
1,上传 vue-simple-upload 文件上传,分片上传
支持拖拽文件、文件夹上传;可暂停、继续上传;支持秒传;上传队列管理,支持最大并发上传;分片上传;
2,Json展示 vue-json-viewer 实现json格式在页面展示,可折叠,高亮
3,时间 moment.js 时间组件库实现各地时间
4,滚动 vue-infinite-scroll 无限滚动插件,其作用是是当滚动条滚动到距离底部的指定高度时触发某个方法。
5,图片懒加载vue-lazyload 图片懒加载,就是需要用到图片的时候再去加载。
6,进度条组件noprogress 只需要调用start()和done()来控制进度条。
7,树形下拉框插件vue-treeselect 只需要调用start()和done()来控制进度条。
noprogress 使用方法:
nprogress 插件是在页面刷新和跳转时出现在浏览器顶部的进度条,它会随着页面的加载而显示进度状态。
1, npm install nprogress -S
2, 路由中使用
import NProgress from “nprogress”;import ‘nprogress/nprogress.css’
router.beforeEach((to,from,next)=>{ NProgress.start() })
router.afterEach( (to,from,next)=>{NProgress.done() } )
sprite使用方法
1,安装sprite-loader雪碧图插件
2,在webpack配置文件中添加loader
Model.exports={
Rules:[
{ test: /.(png|gif|jpeg|jpg)$/i,
Use:’sprit-webpack’
}
]
}
Rouyi的Vuetree插件 vue-treeselect 树型选择下拉框插件
后端返回parentId,前端处理成children嵌套数据
定义函数:handleTree(data,id,parentId,children)
前端如何知道是http几?
打开console控制台,查看network下的请求数据,在数据的表头部分右键勾选出’protocol‘,这个请求的列表就会多一列protocol展示是http几。
JS
(为什么有js事件循环机制;js基础 )
Js是单线程的
1,进程:进行中的程序 (多进程:同一时间多个程序运行)
2,线程:一个程序中的执行流 (多线程:一个程序中包含多个执行流)
3,Js是单线程的原因:是浏览器的脚本语言,js的用途与用户互动操作dom,所以只能是单线程的。
Js的worker线程:h5的web worker标准,允许js脚本创建多个线程,但是子线程受控于主线程,而且不得操作dom,所以这并没有改变js是单线程的本质。
Js事件循环机制
为什么有此机制:
先执行同步代码,再执行异步代码。于是js引入了事件循环来模拟多线程效果。
如何实现:
. 同步任务放入执行栈(规则先进后出
. 异步任务放入任务队列(规则先进先出)
. 浏览器的webApi,浏览器自己提供的api会在另一个线程处理,处理完后会自动塞到js的任务队列里来。
. 消息队列分为宏任务队列和微任务队列。
- 浏览器提供api是宏任务:setTimeout,setInterval,setImmediate,ajax,文件操作,…
- Js引擎提供微任务:promise.then、.catch和finally ;promise.nextTick…(promise中的异步体现在then和catch中,所以写在promise中的代码是被当作同步任务立即执行的。async,await是promise和generator的语法糖,所以await会当作同步任务执行,then会是放如异步微任务)
- Script中的js代码是宏任务
事件循环机制告诉了我们js代码的执行顺序,是一种解决js单线程运行时不会阻塞的一种机制。
题一:
async function async1() {
console.log('async1 start');
await async2();
console.log('async1 end');
}
async function async2() {
console.log('async2');
}
console.log('script start');
setTimeout(function() {
console.log('setTimeout');
}, 0)
async1();
new Promise(function(resolve) {
console.log('promise1');
resolve();
}).then(function() {
console.log('promise2');
});
console.log('script end');
/*
script start
async1 start
async2
promise1
script end
async1 end
promise2
setTimeout
*/
解析:script代码块宏任务的同步任务—>异步任务里的微任务—>异步任务里的宏任务
1,事件循环从宏任务(macrotask)队列开始。有一个script(整体代码)任务,执行整个代码块。
2,先执行同步任务:按顺序 console.log(“script start”);async1()函数,async函数中在await之前的代码是立即执行的,所以输出‘async1 start’,然后执行async2()函数,输出‘async2’,将cosnole.log(‘async1 end’)分配到microtask(微任务)队列中;遇到promise,promise中的代码被当作同步任务立即执行的,所以输出‘promise1’,然后执行resolve,将‘promise2’分配到microtask中;console.log输出‘script end‘,至此,全局任务执行完毕了。
3,然后执行微任务:每次执行完一个宏任务之后,会检查是否存在microtask;如果有,则执行microtask直至清空microtask queue。因此在script任务执行完毕之后,开始查找清空微任务队列。微任务队列中,promise队列中有两个任务async1 end和promise2,因此依次输出async1 end、promise2,所有的microtask执行完毕之后,表示第一轮的循环就结束了。
4,第二轮循环依旧从宏任务队列开始。此时宏任务中只有一个setTimeout,输出’setTimeout’。至此流程结束。
题二:
console.log(1)
setTimeout(() => { // 宏任务
console.log(2)
new Promise(() => {
console.log(11)
})
})
// 特殊说明: new Promise()属于主线程任务
let promise = new Promise((resolve,reject) => {
setTimeout(() => {
console.log(10)
})
resolve()
// 这个console也属于主线程任务
console.log(4)
})
fn()
console.log(3)
promise.then(() => { //微任务
console.log(12)
})
function fn(){
console.log(6)
}
结果是1、4、6、3、12、2、11、10
Js基础知识
1. js变量按存储方式有两种类型:值类型、引用类型(原始类型和对象类型)
原始类型6种:undefined、null、boolean、string、number、symbol
对象类型:Object,Array,Function、Date、RegExp
2. typeof 6种类型 4个原始类型undefined、boolean、number、string、2个对象类型object、function
3. 类型转换 只能转三种类型——转布尔值、转字符串、转数字
4. == vs === : == 类型转换 (null==undefined string boolean和number对比转数字 对象和对象比较引用地址是否为同一个 obj.a == null需要检测是否为null )
5. 浅拷贝 Object.assign() 如果属性值是对象的话,拷贝的是地址,所以是浅拷贝。
6. 深拷贝 JSON.parse(JSON.stringify(xxx)) 递归遍历 lodash库的 lodash.cloneDeep()
7. js的5种内置函数
常规函数:alert() , confirm() , isNaN() , parseInt() , parseFloat()
数组函数:push() , pop() , shift() , unshift() , reverser() , concat()
字符串函数:toLowerCase() , toUpperCase()
数字函数:Math.max() , Math.min() , Math.abs() , Math.round()
日期函数:getDate() , getTime() , getFullYear() , getMounth() , geDay() , getHours() , getMinutes() , getSeconds()
8. json 是js的一个对象,也是一种数据类型。JSON.parse() JSON.stringify()
9. 闭包 函数A内有一个函数B,函数B访问函数A里的变量。函数B就是闭包。
闭包的运用:
例如1:for循环中使用var定义变量问题
for(var i=0;i<10;i++){
(function(j){
setTimeout(function(){
console.log("zz")
},j*1000)
})(i)
}
for循环里不使用var声明变量,改为es6的let声明变量可以不用闭包的形式,因为es6中的let,const会自动形成闭包。
for(let i=0;i<10;i++){
setTimeout(function(){console.log(i)},i*1000)
}
例如2:vue组件的data是一个函数:就是一个闭包。(组件是一个class类,每个地方用到它就相当于这个class类的实例化,实例出的data在一个闭包里,那么实例的数据不会相互影响)i
10.原型和原型链
原型:也就是prototype(原型或显示原型)、constructor(构造函数)、__proto__(隐式原型)三者的关系。
1,当我们创建一个函数时,系统会自动分配一个prototype原型属性,这个原型对象包含所有实例共享的属性和方法,也包含一个constructor构造函数属性,指向它的构造函数(prototype包含contructor + 实例的属性、方法)
2,new一个实例对象时,它拥有__proto__隐式原型属性,指向它的原型对象。(__proto__)
原型链:prototype,object.prototype
1,js中所有对象都由它的prototype原型对象继承而来。而原型对象也有原型对象。这样层层上溯就形成了一个类似链表的结构,这就是原型链。
2,所有原型链的终点都是object.prototype属性,而object.prototype的原型对象指向是个null,null没有原型。
深拷贝:
1, JSON.parse( JSON.stringify(object) ):无法拷贝undefined和函数,大部分情况可用。
2, 递归深拷贝(考虑边缘情况):手写函数需要处理 1,原始数据类型;2,null;3,Date;4,RegExp;5数组对象
递归循环的解决问题:
手写递归深拷贝:
function deepClone(target){
if(typeof target !== 'object') return target //处理原始类型
if(target === null) return target //处理null
if(target instanceof Date) return new Date(target) //处理日期
if(target instanceof RegExp) return new RegExp(target)//处理正则
//处理对象和数组
let cloneTarget = new target.constructor() //利用target的constructor构造函数创建一个新的克隆对象或克隆数组
for(const key in target){ //递归拷贝每一层
cloneTarget[key] = deepClone(target[key])
}
return cloneTarget
}
原型链缺点:
由于原型链的存在,所有实例共享属性和方法。如果一个实例对原型属性进行了更改,那么所有的实例的这个属性都会更改。这就是原型共享属性造成的最大问题。
实例和原型之间的方法
1,instanceof 确定原型和实例的关系,检测的是原型。
2, hasOwnProperty 判断属性来自实例还是原型上
instance 实例的意思
function Person(){}
var p = new Person()
p instanceof Person //true 构造函数Person的实例P, 意思是p指向Person的原型对象
p instanceof Object //true
hasOwnProperty 拥有自己的属性
function Person(){}
Person.prototype.name = "lcky"
var p = new Person()
p.age = 12
p.hasOwnProperty('age') //true
p.hasOwnProperty('name') //false
New 一个对象的过程new一个对象时,js编译器会做4件事情:
1,创建一个空对象;
2,将构造函数的prototype原型对像和作用域赋值到这个新对象上。(因此this指向了这个新对象)
3,新对象可以访问构造函数中的属性和方法(传参)
4,return this(返回新对象)
自己实现一个new运算符:
function create(){
let Con = [].shift.call(arguments) //创建一个空对象
let obj = Object.create(Con.prototype) //给这个空对象链接到原型对象上
let ret = Con.apply(obj,arguments) //新对象可以访问到构造函数的属性和方法
return ret instanceof Object?ret:obj //返回新对象
}
11.变量与函数提升
1,在js运行之前,变量和函数的声明会提升到最顶部;
2,函数提升高于变量提升
- 匿名函数不会提升
12.Apply和call相同和不同
1,作用相同
都是a对象调用b对象的方法;改变函数内this指向;b.say.apply(a) ; b.say.call(a)
2,参数形式不同
apply参数:数组 b.apply(a,args) ; call参数:依次传入 b.call(a,arg1,arg2)
13.防抖、节流
作用:防抖和节流:防止频繁操作出现速度跟不上或卡死
1,防抖debounce :n秒后执行
触发事件后,延迟n秒再执行回调,若n秒内再触发事件,则重新计算。
应用场景:输入框输入一串数字,使用防抖只在输入完成后,执行查询操作。
2,节流throttle:n秒前执行
函数执行一次后,一段时间内失效,之后重新激活
应用场景:在单位时间内不断触发一件事,用节流只在单位时间内触发一次事件。(如:不断触发一个提交按钮,触发后按钮置灰n秒,之后再变为可点击状态。)
应用:在vue中使用lodash库实现防抖和节流
lodash库:对数据进行快速操作,如object,array,string,number等操作。如数组排序orderby方法
app.component("savebtn",{
methods:{
myDebounced: _.debounce( ( )=>{
//写方法内容
},500)
},
unmounted(){
this.myDebounced.cancel() //移除组件时取消定时器(vue优化)
},
template:`
<buttton @click="myDebounced" >save</button>`
})
14.ES6新方法7点(spli+解构、数组、箭头):
let includes set promise/async await 解构赋值 箭头函数 数组
1,let/const:自动生成代码块
es6之前想要形成代码块,一般采用闭包的方式。如for循环用var声明变量。
es6后,用let替代var会自动生成代码块。如for循环用let
2,includes:字符串,inculdes,数组或字符串判断是否包含某一字符
inculdes() 和 indexOf()
都是判断数组或字符串是否包含一个字符
判断的时候数组里项的类型是string
['5','pp'].indexOf('pp') //1 或者-1不存在
['22','p'].includes('p') //true
'skfjskfjsf'.indexOf('f') //2
'skfjskfjsf'.includes('f') //true
两者区别:
indexOf 能判断位置 √
includes 能判断NaN √ ['22',NaN].includes(NaN) //true
3,`` : 模板字符串:①使用tab上面的那个斜点` `包含。②使用 ${ }包裹变量
4, class类:
es6的class类就是es5原型的语法糖。(当面试问es6的class类型时的回答)
class的写法只是让对象原型的写法更加清晰,更像面向对象的写法而已。它的功能es5都能实现。
- set 数组去重
let arr = [ 1,2,3,5,6,9,7,8,9,8,5,6,2 ]
let res = [ ...new Set(arr) ]
res // [ 1, 2, 3, 5, 6, 9, 7, 8 ]
- 解构赋值:从数组和对象中分离出来值。把右边的对象解构的值赋值给左边变量。
数组解构
// ES5
var arr = [1, 2, 3, 4]
var a = arr[0]
var b = arr[1]
var c = arr[2]
var d = arr[3]
// ES6
//右边解构的值赋值给左边变量。左边是key,右边是数组
let [a, b, c, d] = [1, 2, 3, 4]
console.log(a) // 1
对象解构
// ES5
var luke = {occupation: 'jedi', father: 'anakin'}
var occupation = luke.occupation
// 'jedi'
var father = luke.father
// 'anakin'
// ES6
//右边解构的值赋值给左边变量。
let {occupation, father} = {occupation: 'jedi', father: 'anakin'}
console.log(occupation)
// 'jedi'
console.log(father)
// 'anakin'
8, 箭头函数:
1,继承上下文的this指向的对象(不是指向调用它的对象);
2不需要function关键字;
- 不需要return;
9,promise和async await区别
promise:容器,构造函数,层层回调
①是个容器,保存着未来才解决的事情。
②promise是一个构造函数,接收一个函数并传入resolve、reject参数。
then接收连个回调函数作为参数。
③作用:解决了回调地狱问题:层层嵌套的回调函数,因为它能将异步操作变为同步操作。
async、await:
使用async、await获取成功的结果。
②作用:解决了连个回调函数 ( .then().then().then() )
1,Promise构造函数接收一个函数,并传入resolve、reject作为参数。
let pro = new Promise(function(resolve,reject)=>{
if(//成功){
resolve(value)
}else{
reject(error)
}
})
pro.then(res=>{ })
2,async、await的使用基于promise。使得异步操作变得同步,async返回的是个promise对象。
function handler(){
return new Promise((resolve, reject)=>{
let sino = parseInt(Math.random() * 6 +1)
setTimeout(()=>{
resolve(sino)
},3000)
})
}
async function test(){
let n =await handler()
console.log(n)
}
test()
10,数组方法:filter、every、some、find、findindex、includes、map、forEach
Filter() 方法对每个元素执行一次filter中的回调函数,满足条件的返回一个新数组
Every() 方法必须所有都返回true才会返回true,哪怕有一个false,就会返回false
Some() 方法只要其中一个为true就会返回true的 一真即真
Find() 方法返回满足条件的第一个元素的值。否则返回undefined
FindIndex() 方法返回满足条件的第一个元素的索引。否则返回-1
Includes() 方法包含指定的值返回true,否则返回false
Map() 方法,map即映射,原数组映射成一个新的数组
forEach() 方法,遍历数组的每一项
15.箭头函数和普通函数的区别?构造函数可以使用new,但箭头函数不可以
new和this:
构造函数也是普通函数。可使用new命令和this;
箭头函数没有new命令,没有this。它会从自己作用域的上一层继承this,没有new命令(因为①没有this,无法调用call,apply。②没有prototype原型属性,而new的时候会把构造函数的prototype赋值给新对象的__proto__属性)
arguments:
箭头函数没有arguments,可以用rest参数替代
16.Es6代码转Es5代码的实现思路 es6代码的兼容性处理,babel原理
ES6代码 ——>转ES6 AST——>转ES5 AST——>转ES5代码
17.Var和let,const区别
1,var声明的变量提升成为window对象属性,可以重复声明变量。
2,let,const声明的变量不会提升,不可以重复声明变量。会自动生成块级作用域,也就是闭包。
------ 这里可延伸for循环的var和let。
let和const区别在于const声明的是常量—只读。
18.Promise和setTimeout() 执行顺序
先执行promise再执行setTimeout
19.Css改变引起的重绘和回流问题
重绘:
含义:元素的结构(宽高布局文字大小)没有改变,只是外观样式改变
例如:背景色,文字色,边框色... 导致页面重绘
回流:含义:元素的结构改变了,影响了自已和周边,导致整个页面重新渲染。发生回流
回流必将导致重绘,而重绘不一定引起回流。例如:元素颜色改变只会重绘不会回流
css :
1,避免设置多层内联样式
2,避免使用css表达式,如 calc()
js :
1,避免频繁操作样式,操作dom
- 可以设置元素 display:none ,操作之后再显示出来
20.几种循环方法
1,for循环,循环代码块一定的次数。
2,for/in循环,对象属性的遍历
3,while循环,只要满足一个条件,会一直执行while代码块里的内容。
4,do/while循环,满足条件循环代码块,但会在条件判断前先执行一次。
While
var text = "";
var i = 0;
while (i < 5) {
text += "<br>The number is " + i;
i++;
}
do…while
do{
执行代码
}while(condition) // condition条件必须。定义执行循环的条件。如果返回 true,循环会再次执行,如果返回 false,循环结束。
css3新特性
文字:text-overflow、text-shadow、word-break、word-wrap
边框:border-radius、box-shadow
变形:transform:translate(x,y,z)、translate3d(x,yz)、rotate(20deg)、scale(x,y)
过渡:transition:属性,时长 例如,div{ width:100px;transition:width 5s; }
Text-overflow 单行/多行文本溢出显示省略:
overflow:hidden;
white-space:nowrap;
text-overflow:ellipsis; (前三行单行样式,所有是多行样式)
Word-break:break-all;
Width:100px;
Height:40px;
Line-height:40px;
vue中package.json里面dependencies和devDependencies区别
dependencies:应用能正常运行所依赖的包;npm install 安装你的包时会自动安装这些依赖。
devDependencies:开发时所依赖的工具包。通常时一些开发、测试、打包工具,例如webpack、ESLint、Mocha,应用正常运行不会依赖这些包。
Npm install 命令默认会安装所有在package.json中列出的依赖,包括dependencies和devDependencies中的依赖。
执行npm run dev命令报错解决 在显示vue-cli-service不是内部命令或外部命令...... 原因可能只是下载了dependencies中的依赖,而没有下载devDependencies中的依赖。可以执行npm install --dev命令,这将会下载安装全部依赖。
使用css实现一个持续的动画效果
先定义动画move,再在元素上使用它。
@keyframes move {
0% {transform: translateX(0px);}
25% {transform: translateX(1000px);}
50% {transform: translate(1000px, 500px);}
75% {transform: translate(0px, 500px);}
100% {transform: translate(0px, 0px);}
}
.animation {
width: 100px;
height: 100px;
background-color: teal;
animation: move 5s infinite;
}
vue的transition标签结合css样式完成动画
.show-enter-active,.show-leave-active{ transition:all 2s ;}
.show-enter,.show-leave-to{ marge-left:100px; }
.show-enter-to,.show-leave{ margin-left:0px; }
<transition name=”show”><span>过渡</span></transition>
使用js实现一个持续的动画效果
requestAnimationFrame
const box = document.querySelector('.box');let move;let timer = requestAnimationFrame(function fn() {
move = parseInt(getComputedStyle(box).left);
if (move < 800) {
box.style.left = move + 8 + 'px';
requestAnimationFrame(fn);
} else {
cancelAnimationFrame(timer);
}});
Css-:nth-child 的用法
- 每行显示3个盒子:nth-child(3n+1)
重点代码: 3n+1 一行显示3个;2n+1 一行显示2个;
.item:nth-child(3n+1) {
width: 30%;
margin-left: 5px;
margin-right: 5px;
background-color: pink;
}
<div class="flex">
<div class="item">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
</div>
移动端效果:
浅谈amd和cmd的作用和区别
amd和cmd都是js的模块加载器;
Amd:提前加载依赖的模块,但并不立即执行。只有在依赖的模块都加载完成后,才按照依赖顺序执行模块。
Cmd:与amd不同,cmd是依赖就近,即当需要用到某个模块时再去加载它。
任意组件间触发事件,通信:事件总线$bus
在main.js中:
new Vue({
el: '#app',
render: h => h(App),
beforeCreate(){//带数据代理没有完成
Vue.prototype.$bus=this//安装全局事件总线,$bus就是当前的vm实例
}
});
B组件触发:this.$bus.$emit('自定义事件名称',数据)
A组件接收:
mounted() {
this.$bus.$on('自定义事件名称',(data)=>{console.log('A组件,收到了数据:',data)}
})}
A组件beforeDestroy销毁:this.$bus.$off('自定义事件名');//销毁
大文件切片上传
原理:
通过file.slice将大文件chunks切成许多大小相等的chunk。
将每个chunk上传到服务器
服务器收到多个chunk后,合并为chunks。
使用插件:vue-simple-uploader
uniapp的easycom自动引入组件规则
只要组件安装在项目的 components 目录下,并符合 components/组件名称/组件名称.vue 目录结构。
就可以不用引用、注册,直接在页面中使用。
//easycom配置
"easycom": {
"autoscan": true, // autoscan是否开启自动扫描,开启后将会自动扫描符合components/组件名称/组件名称.vue目录结构的组件
"custom": {
//表示components/em路径下,所有的em-开头文件下,所有的em-开头的vue文件
"em-(.*)": "@/components/em/em-$1/em-$1.vue"
}
}
接口api规范
只要组api主要包括四部分:url,请求方式,参数,返回值,一般就是对这个四部分做统一规范
接口url:是否是rest风格的,统一标识的。比如登录url:/login 、比如查询列表 /list结尾等
请求方式:get或者post
请求参数:参数名,参数类型,说明,是否必填
返回参数:对返回结果统一
{
“success”:true,
“code”:200,
“msg”:”success”,
“data”:’”token”
}
工具使用
Elementui
Mock
① npm install mockjs --save-dev
② 新建mock文件夹,新建mockServe.js和data.json文件。
在mockServe.js 里引入mockjs插件和data.json定义的数据,在此定义接口。
import Mock from "mockjs";
import videos from './videos.json';
Mock.mock('/mock/getVideo','get',{code:200,data:videos})
③ api文件夹里新建index.js里引入axios和定义接口
export const getVideoDetail = (vid)=>instance({url:`/getVideo`,method:'get',data:{vid}})
在main.js种引入 @/mock/mockServe.js
Websocket
如何连接:
1,websocket地址以 ws:// 或 wss:// 开头,分别表示非加密和加密连接。
2,使用js的websocket API来创建websocket对象。
var socket = new WebSocket(“ ws://example.com ”)
监听websocket事件:处理不同阶段:
①创建连接:onopen
②接受消息:onmessage
③关闭连接:onclose
var socket = new WebSocket(“ ws://example.com ”)
socket.onopen = function(){ }
socket.onmessage = function(){ }
socket.onclose = function(){ }
Flex
一, 容器属性5
flex
flex-direction 主轴方向 row、row-reverse、column、column-reverse
flex-wrap 换行 wrap、nowrap、wrap-reverse
justify-content 在主轴上的对齐方式 flex-start、flex-end、center、space-around、space-between
align-items 交叉轴对齐方式 flex-start、flex-end、center、baseline、stretch
align-content 交叉轴多行对齐方式 flex-start、flex-end、center、space-round、space-between
二, 项目属性3
order 排序 值越小越靠前,默认0
align-self 允许项目的对齐方式与其他项目不同 auto、flex-start、flex-end、center、baseline、stretch 默认值auto
flex-grow 放大 默认0
flex-shrink 缩小 默认1
flex-basis 计算主轴是否有多余空间 默认auto,项目本来大小
3,4,5 flex 这三个的缩写:0 1 auto