1,代码规范问题
2,vue
$t是调用挂到了Vue.prototype下面的方法
3,proxyTable拦截
同源策略是浏览器需要遵循的标准,而如果是服务器向服务器请求就无需遵循同源策略
vue-cli的proxyTable用的是http-proxy-middleware中间件,该中间件本质上是在本地开了一个服务器dev-server,
所有的请求都通过这里转发出去,即把浏览器的发送请求代理转发到代理服务器上,
再由代理服务器发送请求给目标服务器,从而解决跨域问题。
dev:{
proxyTable:{
"/api": {
target: "http://seller.jd.id/api/",//直接把/api的接口通过代理一下换成目标域名访问;
ws: true,//指的是是否开启websocket;
secure: false,
changeOrigin: true,//是否允许跨域
pathRewrite: {
"^/s": "/"
}
},
}
}
4,vue中的computed计算属性的使用
computed实际上不是一个方法,而相当于一个需要经过较为复杂计算的属性,只有其依赖的响应式属性的值发生变化时,才会调用;
5,vuex
state,
mutations,
actions,
getters,
modules
mutations中用于同步修改数据;state实例
actions中用于异步修改数据,context对象
actions通常不直接修改state的值,而是调用mutations中的方法;通过store.dispatch()分发方法;
getters可以把state中的数据暴露出去;
modules允许将store分割成多个模块,每个模块有自己的state,mutations,actions,getters,
store.state;store.
6,Object.extend()用静态方法实现了js的继承
Object.extend=function(destination,source){ for(var prototype in source){ destination[property] = source[property]; } return destination; }
7,vue-router
component:(resolve)=>require(['../pages/home.vue'], resolve)
组件按需加载,只有跳转到该路由时才会加载该组件
8,keep-alive,websocket区别
可以在一次TCP连接就实现多次http请求
keep-alive持久连接
9,优雅降级和逐渐增强
优雅降级:一开始就根据浏览器构建完整的页面,然后对低版本的浏览器进行兼容;
逐渐增强:先针对低版本的浏览器进行开发,保证了页面最基本的功能,然后针对高版本的浏览器进行样式,效果,交互的增加,从而达到更好的用户体验;
10,高阶函数
- 高阶函数:接受一个或多个函数为参数,返回一个函数;如:Array.prototype.map();
- 组合函数:将两个或两个以上函数组合生成一个新函数;
juejin.cn/post/689288…
11,cli组件嵌套
12,vue-i18(多语言)
i18n.js中
new VueI18n({
locale:'',//设置地区
messages:{
//''中是设置的地区,后面是具体的字段及其对应的翻译
'':{
}
}
})
在main.js中
引入i18n,
Vue.use(i18n);
引用new Vue({i18n}).$mount('#app');
$t是vue扩展的实例中的方法,可以全局灵活引用;(缺点:每次重新渲染时都要执行,有翻译成本)
v-t自定义指令预编译(使用不方便)
13,如何优雅的只在当前页面中覆盖ui库中组件的样式
通过深度选择器解决。例如修改上图中组件里的van-ellipsis类的样式,可以这样做: .van-tabs /deep/ .van-ellipsis { color: blue};
14,vue表单验证v-validate
v-validate是vue指令之一;
1,import { Validator } from "vee-validate";//npm install vee-validate 后
2,在main.js中use
3,Vaildator.addLocale()选择语言方式
4,required:true/false判断是否需要进行自定义校验
5,Validator.extend("针对不同参数进行不同的校验", {
getMessage (filed) {
return "This filed can not be special characters.";
},//校验失败的提示语
validate (value) {
if (value && (("" + value).indexOf("<") > -1 || ("" + value).indexOf(">") > -1 || ("" + value).indexOf("\\") > -1)) {
return false;
}
return true;
}//校验的正则表达式
});
6,$validator.validateAll()//对表单进行终极认证,验证对应部分校验规则是否填写正确
15,process.env
vue文件中可能会出现多种环境
process.env用于记录当前环境的环境变量
process.env 通常是默认环境,在所有文件中都存在
process.env.local 在git中会被忽略
改变环境
方法一:
package.json中scripts下 {"serve":vue-cli-service serve} 通常相当于设定了.env .env.pre (后者覆盖前者)
{"build": vue-cli-service build} 通常相当于设定了.env .env.production(后者覆盖前者) 、
方法二:
package.json中scripts{"serve":vue-cli-service serve --mode development} 通常相当于设定了.env .env.development (后者覆盖前者)
16,formData()上传文件
创建实例
普通创建:let formData=new FormData();
vue中创建:let formData=new window.FormData();
表单中创建:let formData=new FormData(form)
操作方法
获取:formData.get('key');
追加或修改:formData.append('key',value');//如果key值存在则修改key对应的value,不存在则添加一个key值为value;
修改:formData.set(key,value);
删除:formData.delete('key');
检查数据是否存在:formData.has(key)
上传文件
获取文件内容
创建formData()实例
formData.append()将文件追加到formData()实例中
this.$axios.post({
url,formData})
url是文件上传的接口 formData是上传文件的formData()对象
17,编码:escape,encodeURI,encodeURIComponent,解码:unescape,decodeURI,decodeURIComponent (UTF-8编码)
escape对字符串进行编码,不针对URL,作用是让它们在所有电脑上可读。
其中 ASCII字母 数字 @/+ 这几个字符不会被编码,其余的都会
unescape对字符串进行解码
encodeURI编码整个URI,但是编码之后不可用(除去 ASCII字母 数字 ~!@#$&()=:/,;?+')
encodeURIComponent编码URL中的参数(除去ASCII字母 数字 ~!*()')
18,结合vue-cli3.0打包npm包
修改vue.config.js,将入口文件更改
pages: {
index: {
entry: 'examples/main.js',
template: 'public/index.html',
filename: 'index.html'
}
}
1,在vue-cli中增加目录example作为例子
2,在组件中src下加入index.js为组件设置一个install方法,将组件暴露出来
3,在组件的目录下加如index.js写组件的install方法,并将调用,然后将install和组件暴露出去;
4,在入口文件main.js中引入组件目录下的index.js Vue.use()
5,在App.vue中引入
6,在package.js中配置
"lib": "vue-cli-service build --target lib --name test --dest lib scroll/index.js"
test是自定义的名字,scroll/index.js是入口文件路径
name -----> 包的名称,必须唯一,不能跟已有的npm包重名,否则发布不上去;
version -----> 包的版本,当你需要迭代版本时,必须修改这个值(可手动修改,可运行以下命令修改)
npm version patch 会增加小版本 1.0.1:属于小修改,不更改功能使用
npm version minor 会增加二级 1.1.0:可能添加了一些功能,不影响以前的使用。
npm version major 会增加大版本 2.0.0:可能改了API,输入大范围的修改。
main -----> 包的入口,当你使用import xx from 'xxxx'的时候默认引入的就是main文件;
private -----> 是否为私有包,如果传到npm上必须改为false;
license ----->开源协议
npm log =>npm punlish
npm link可以用于进行本地包的调试[注:安装依赖包和link命令最好使用相同的命令(如都使用npm或jnpm)]
步骤:
1,包文件中npm link;
2,项目中npm link @包文件的名称
解除:包文件 npm unlink 或项目npm unlink --no-save package && npm install
19,关于同源策略和跨域问题
同源策略同源策略指的是协议,域名,端口号三者相同;
同源策略的目的 保证用户信息安全,防止恶意网站窃取用户信息;(阻止了不同网页之间共享cookie);
同源策略的限制
(1) Cookie、LocalStorage 和 IndexDB 无法读取。
(2) DOM 无法获得。
(3) AJAX 请求不能发送。
同源网页之间共享cookie,dom的方式
浏览器允许将两个一级域名相同,二级或三级域名不同的网页设置document.domain等于一个相同值或在设置cookie时,将其domain指向它的一级域名下(domain=.example.com),使得两个网页能共享cookie;
不同源网页之间数据共享dom的方式
1,片段标识符(fragment identifier)
2,window.name
3,跨文档通信API(Cross-document messaging)
1,片段标识符
父窗口将信息写进字窗口的片段标识部分(在原链接后#+data)
var src = originURL + '#' + data;
document.getElementById('myIFrame').src = src;
子窗口通过监听onhashchange事件,获取父窗口传递的数据
window.onhashchange = checkMessage;
function checkMessage() {
var message = window.location.hash;
// ...
}
子窗口改变父窗口的片段标识符
parent.location.href= target + "#" + hash;
2,window.name
将信息写在window.name中父窗口打开一个新窗口时直接将信息放入window.name中,子网页得到父窗口的信息,子网页跳回与父窗口同源的窗口中,父网页同样能够获取到子网页中的信息;
这种方法的优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。
3,window.postMessage()
html5应用一个全新的API跨文档通信
在window对象中加入了window.postMessage()方法,组件之间可以通信,不管同不同源;
window.postMessage()第一个参数是具体的信息,第二个参数是接受信息的源;
子窗口向父窗口发送信息
var popup = window.open('http://bbb.com', 'title');
popup.postMessage('Hello World!', 'http://bbb.com');
父窗口向子窗口发送信息
window.opener.postMessage('Hello','http://aaa.com');
然后父子窗口通过message事件,监听对方发送的消息
window.addEventListener('message', function(e) {
console.log(e.source);//发送消息的窗口
console.log(e.origin);//消息发向的网址
console.log(e.data);//消息的内容
},false);
window.postMessage()使得不同窗口之间共享localStorage成为了可能
子窗口接受消息并存入自己的localStorage中:
window.onmessage = function(e) {
if (e.origin !== 'http://bbb.com') return;
var payload = JSON.parse(e.data);
switch (payload.method) {
case 'set':
localStorage.setItem(payload.key, JSON.stringify(payload.data));
break;
case 'get':
var parent = window.parent;
var data = localStorage.getItem(payload.key);
parent.postMessage(data, 'http://aaa.com');
break;
case 'remove':
localStorage.removeItem(payload.key);
break;
}
};
父窗口发送消息
var win = document.getElementsByTagName('iframe')[0].contentWindow;
var obj = { name: 'Jack' };
// 存入对象
win.postMessage(JSON.stringify({key: 'storage', method: 'set', data: obj}), 'http://bbb.com');
// 读取对象
win.postMessage(JSON.stringify({key: 'storage', method: "get"}), "*");
window.onmessage = function(e) {
if (e.origin != 'http://aaa.com') return;
// "Jack"
console.log(JSON.parse(e.data).name);
};
AJAX跨域请求
解决方法
1,服务器代理: 浏览器请求同源服务器,同源服务器向外发送请求
2,JSONP:浏览器动态添加script标签,将跨域的URL写入script的src中,同时服务器收到请求后,将数据放入一个回调函数中返回;
function addScriptTag(src) {
var script = document.createElement('script');
script.setAttribute("type","text/javascript");
script.src = src;
document.body.appendChild(script);
}
window.onload = function () {
addScriptTag('http://example.com/ip?callback=foo');
}
function foo(data) {
console.log('Your public IP address is: ' + data.ip);
};
优点:简单适用,老式浏览器全部支持,服务器改造非常小。
缺点:只能够支持get请求。
3,WebStocket
WebSocket是一种通信协议,使用ws://(非加密)和wss://(加密)作为协议前缀。该协议不实行同源政策,只要服务器支持,就可以通过它进行跨源通信。
请求头信息
GET /chat HTTP/1.1
Host: server.example.com
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==
Sec-WebSocket-Protocol: chat, superchat
Sec-WebSocket-Version: 13
Origin: http://example.com
Origin:代表请求的域,因此webSocket不受浏览器同源策略限制;服务器根据该字段,来判断是否允许该域的请求; 请求成功后的返回
HTTP/1.1 101 Switching Protocols
Upgrade: websocket
Connection: Upgrade
Sec-WebSocket-Accept: HSmrc0sMlYUkAGmm5OPpG2HaGWk=
Sec-WebSocket-Protocol: chat
4,CORS
CORS跨域资源共享,需要浏览器和服务器同时支持。目前,所有浏览器都支持该功能,IE浏览器不能低于IE10。
浏览器将CORS请求分为两类,简单请求和非简单请求
简单请求的限制:
(1) 请求方法是以下三种方法之一:
HEAD
GET
POST
(2)HTTP的头信息不超出以下几种字段:
Accept
Accept-Language
Content-Language
Last-Event-ID
Content-Type:只限于三个值application/x-www-form-urlencoded、multipart/form-data、text/plain
简单请求流程
1,浏览器发现这次跨源AJAX请求是简单请求,就自动在头信息之中,添加一个Origin字段。服务器根据origin字段得到请求的域,决定是否同意这次请求。
2,如果请求的域在服务器允许的范围之外,服务器会返回一个正常的http响应
如果在服务器的允许范围之内,服务器会返回一个响应增加了以下字段
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Credentials: true
Access-Control-Expose-Headers: FooBar
Content-Type: text/html; charset=utf-8
Access-Control-Allow-Origin:[必选]值是请求的origin或者*(表示所有)
Access-Control-Allow-Credentials:[可选]值是true/false 表示是否允许发送cookie
Access-Control-Expose-Headers: [可选]CORS请求时,XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段:Cache-Control、Content-Language、Content-Type、Expires、Last-Modified、Pragma。如果想拿到其他字段,就必须在Access-Control-Expose-Headers里面指定。上面的例子指定,getResponseHeader('FooBar')可以返回FooBar字段的值
3,CORS默认不发送cookie和HTTP认证信息,如果想要发送cookie给服务器
在AJAX中设置如下:
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
在服务器端设置如下:
Access-Control-Allow-Credentials: true
Access-Control-Allow-Origin就不能设为星号,必须指定明确的、与请求网页一致的域名
非简单请求的流程
非简单请求:请求方法是PUT或DELETE,或者Content-Type字段的类型是application/json。
1,非简单请求的CORS请求,会在正式通信之前,增加一次HTTP查询请求(检查域名是否在白名单中,且请求动词是否接受),称为"预检"请求(preflight)
2,预检请求的js脚本:
var url = 'http://api.alice.com/cors';
var xhr = new XMLHttpRequest();
xhr.open('PUT', url, true);
xhr.setRequestHeader('X-Custom-Header', 'value');
xhr.send();
3,如果浏览器自动识别是预检请求,在请求头自动添加,除了Origin字段,"预检"请求的头信息包括两个特殊字段。
(1)Access-Control-Request-Method[必选]用来列出浏览器的CORS请求会用到哪些HTTP方法,上例是PUT。
(2)Access-Control-Request-Headers[可选]该字段是一个逗号分隔的字符串,指定浏览器CORS请求会额外发送的头信息字段,上例是X-Custom-Header。
4,预检请求成功后的响应,失败时返回一个正常的http响应
HTTP/1.1 200 OK
Date: Mon, 01 Dec 2008 01:15:39 GMT
Server: Apache/2.0.61 (Unix)
Access-Control-Allow-Origin: http://api.bob.com
Access-Control-Allow-Methods: GET, POST, PUT
Access-Control-Allow-Headers: X-Custom-Header
Content-Type: text/html; charset=utf-8
Content-Encoding: gzip
Content-Length: 0
Keep-Alive: timeout=2, max=100
Connection: Keep-Alive
Content-Type: text/plain
Access-Control-Allow-Methods[必选]表示服务器所支持的跨域请求的方法
Access-Control-Allow-Headers[可选]表示服务器所支持的请求头信息
Access-Control-Max-Age[可选]表示本次预检请求的有效期,单位为秒
20,window.open
window.open(URL,name,specs,replace);
URL打开指定的页面的URL。如果没有指定URL,打开一个新的空白窗口
name指定target属性或窗口的名称
_blank - URL加载到一个新的窗口。这是默认
_parent - URL加载到父框架
_self - URL替换当前页面
_top - URL替换任何可加载的框架集
name - 窗口名称
specs一个逗号分隔的项目列表
例如:width=pixels
replace
Optional.Specifies规定了装载到窗口的 URL 是在窗口的浏览历史中创建一个新条目,还是替换浏览历史中的当前条目。支持下面的值:
true - URL 替换浏览历史中的当前条目。
false - URL 在浏览历史中创建新的条目。
应用场景需要用post方法向一个链接上传参数,链接返回值是一个Excel表格,需要直接用window.open打开;
解决方式
构建一个form表单,默认样式为隐藏,将提交的url做为target,将传递的参数遍历,默认提交方式为post,将其插入原有页面,在原有页面的基础上打开一个新页面,excel页面下载完毕后自动关闭;先删除原有表单,每次默认提交的都是第一个表单;也就是最新创建的表单。
/ 构建form发送post请求
let url = baseUrl;
let formStr = "";
// 设置样式为隐藏,打开新标签再跳转页面前,如果有可现实的表单选项,用户会看到表单内容数据
formStr = "<form style=\"visibility:hidden;\" method=\"POST\" action=\"" + url + "\">";
for (var key in param) {
formStr += "<input type=\"hidden\" name='" + key + "' value='" + param[key] + "' style='display: none'>";
}
formStr += "</form>";
let newWin = window.open(url, name, "height=500");
// newWin.document.body.innerHTML = formStr;
let form = newWin.document.getElementsByTagName("form");
// 遍历数组删除每一个form表单
for (let i = 0; i < form.length; i++) {
newWin.document.body.removeChild(form[i]);
}
//将form表单插入到页面的最后
newWin.document.body.insertAdjacentHTML("beforeend", formStr);
newWin.document.forms[0].submit();
return newWin;
21,lottie
Lottie 是一个跨平台的动画库。设计小姐姐使用 AE 制作并导出的动画文件( json 格式),Lottie 可以在各个终端快速解析这个 json 文件,从而还原动画,简单快速。
实现动画的几种方式及优缺点:
Gif 图简单粗暴,但是 Gif 图是位图,不方便控制动画,放大会虚。
Js + Canvas/svg。无论是 Js 操作 Dom 还是用 Svg API 来实现。都算是比较良好的方案,但是成本较高。
css3 anima tion 会导致放大失帧,图片加载过慢,甚至不方便一些稍微复杂的动画处理
实现过程
1,npm install --save vue-lottie
2,以组件的方式全局或局部引入
3,<lottie :options="defaultOptions" :width="24" :height="24" v-on:animCreated="handleAnimation"/>
width,height一定要设置,默认为0;
defaultOptions 参数
container:element,//要包含该动画的dom元素
animationData:award,//award为json格式的数据
renderer:'svg',//渲染方式,svg、canvas、html(轻量版仅svg渲染)
loop:true,//是否循环播放,true表示循环,false表示不循环
autoplay:true,//是否自动播放,true表示自动播放
animCreated用于创建一个lottie对象
有很多默认的API来操作这个对象
mounted:{}可以设置监听函数,这个Lottie对象进行监听
22,将返回的标签字符串渲染到DOM中
方法一,<div v-html="data.str">data.str</div>
方法二,<div ref="div"></div>通过this.$refs['div']获取到这个元素,向其中利用innerHTML将代码填入
23,BigInt
场景:后端返回数据类型是long,是一个19位的雪花ID,JS由于精确度问题导致收到的数据不准确,后面的几位都是零;
定义方式:在一个整数字面量的后面直接加n;(如:const bigInt=12345678n);
BigInt 是一种内置对象,它提供了一种方法来表示大于 253 - 1 的整数(大概是15位以上)
24,Keep alive
场景:当填写完一个页面的信息,跳转到下一个页面时,再次返回,页面信息能够保留下来
方式一:同一个页面,使用组件的显示与隐藏
方式二:使用本地化存储
方式三:keep alive
组件之间切换的时候,你有时会想保持这些组件的状态,以避免反复重渲染导致的性能问题;
keep-alive能够让失活组件缓存起来
用法:
<keep-alive>
<component>
</keep-alive>
将组件用keep-alive包裹起来,即便其失去活性,返回该页面时也能拿到刚刚操作该组件
属性:include, exclude,max
include - 字符串或正则表达式。只有名称匹配的组件会被缓存。
exclude - 字符串或正则表达式。任何名称匹配的组件都不会被缓存。
max - 数字。最多可以缓存多少组件实例。