实习学习

294 阅读11分钟

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组件嵌套

juejin.cn/post/684490…

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指令之一;

1import { 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;

2window.name
将信息写在window.name中父窗口打开一个新窗口时直接将信息放入window.name中,子网页得到父窗口的信息,子网页跳回与父窗口同源的窗口中,父网页同样能够获取到子网页中的信息;
这种方法的优点是,window.name容量很大,可以放置非常长的字符串;缺点是必须监听子窗口window.name属性的变化,影响网页性能。  

3window.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 - 数字。最多可以缓存多少组件实例。