Vue组件之间传值
1. 父传子:
基本数据类型传值,对象的话传引用,子组件改变对象,父组件中的相应数据也改变。
<template>
<div class="mobile-container">
<router-view :sendtoSon="toSon"></router-view>
</div>
</template>
data(){
return {
toSon :'hello son',
}
}
子组件用props数组接收
data(){
return{
}
},
props:['sendtoSon'],
mounted(){
console.log(this.sendtoSon) // hello son
}
2. 子传父
子组件使用emit触发父亲的函数,通过参数来传递数据
this.$emit('SonToParent','父组件,我要登陆了')
父组件绑定函数
<div class="mobile-container">
<router-view @SonToParent = acceptData></router-view>
</div>
methods:{
acceptData(data){
console.log(data) // 父组件,我要登陆了
}
},
3. 兄弟组件之前传值
- 先传给父组件,再传给兄弟组件。
- vuex (推荐)
provide和inject
类似props传值,但不限定于父子组件,还可以祖父->孙子这样传递。
传递方:provide:{ 'name' : 'ljp' }
接收方: inject: ['name'] -> this.name = 'ljp'
BFC
触发bfc的条件(满足任意一条):
- float的值不为none
- .overflow的值不为visible
- display的值为table-cell、tabble-caption和inline-block之一
- position的值不为static或则releative中的任何一个
触发了bfc后的效果:
- 浮动的元素会被父级计算高度(父级触发了BFC)
- 非浮动元素不会覆盖浮动元素位置(非浮动元素触发了BFC)
- margin不会传递给父级(父级触发了BFC)
- 两个相邻元素上下margin会重叠(给其中一个元素增加一个父级,然后让他的父级触发BFC)
exam1:浮动的元素会被父级计算高度(父级触发了BFC)
<div class="bfc">
<div class="box"></div>
</div>
.box{
float: left;
width: 100px;
height: 100px;
background-color: yellow
}
box设置了float, 正常情况下,父元素高度会坍塌,变为0px。但只要让父元素触发bfc,高度就可以被子元素撑开。
.bfc{
/*position: absolute;*/
/*overflow: auto;*/
/*float: left;*/
/*display: inline-block;*/
}
.box{
float: left;
width: 100px;
height: 100px;
background-color: yellow
}
exam2: 非浮动元素不会覆盖浮动元素位置(非浮动元素触发了BFC)
<body>
<div class="box1"></div>
<div class="box2"></div>
</body>
<style type="text/css">
.box1{
width: 100px;
height: 100px;
background-color: blue;
float: left;
}
.box2{
width: 150px;
height: 150px;
background-color: yellow;
/*position: absolute;*/
/*overflow: auto;*/
/*float: left;*/
/*display: inline-block;*/
}
</style>
若box2没有触发bfc,效果如下
让box2触发bfc,效果如下
exam3
父元素触发bfc后,子元素的margin会重叠
<div class="bfc-box">
<div class="box1"></div>
<div class="box2"></div>
</div>
<style>
.box{
overflow: auto
}
.box1,.box2{
width:100px;
height:100px;
margin:50px
}
.box1 {
background-color: red
}
.box2{
background-color:blue
}
</style>
如果不希望子元素重叠,可将子元素分别包裹在不同的bfc容器中
<div class="bfc-box">
<div class="box1"></div>
</div>
<div class="bfc-box">
<div class="box1"></div>
</div>
<style>
.box{
overflow: auto
}
.box1,.box2{
width:100px;
height:100px;
margin:50px
}
.box1 {
background-color: red
}
.box2{
background-color:blue
}
</style>
三列布局(左右固定两边自适应)
1 . flex 实现
<body>
<div class="container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
</body>
<style type="text/css">
.container div{
height: 500px;
}
.container{
display: flex;
}
.left{
flex:0 0 200px;
background-color: yellow
}
.right{
flex:0 0 200px;
background-color: yellow
}
.middle{
flex:1; // flex:1 = flex-shrink : 0; flex-grow:1 ; flex-batis:auto
background-color: blue;
}
</style>
2. calc实现
<body>
<div class="container">
<div class="left"></div>
<div class="middle"></div>
<div class="right"></div>
</div>
</body>
<style type="text/css">
.container div{
height: 500px;
display: inline-block;
}
.left{
width:200px;
background-color: yellow
}
.right{
width: 200px;
background-color: yellow
}
.middle{
background-color: blue;
width: calc(100% - 400px)
}
</style>
3.float + margin实现 (也可以float+calc)
这个方法要注意先放left和right,middle放最后,不然middle直接把整行占了,right只能到下一行
<body>
<div class="container">
<div class="left"></div>
<div class="right"></div>
<div class="middle"></div>
</div>
</body>
<style type="text/css">
.container div{
height: 500px;
}
.left{
float: left;
width:200px;
background-color: yellow
}
.right{
float: right;
width: 200px;
background-color: yellow
}
.middle{
background-color: blue;
margin-left: 200px;
margin-right: 200px;
}
</style>
跨域方式总结
1. jsonp
原理:利用浏览器对<script>中的src引入没有跨域限制,网页可以得到从其他来源动态产生的 JSON 数据。JSONP请求一定需要对方的服务器做支持才可以。
优缺点:jsonp优点是简单兼容性好,可用于解决主流浏览器的跨域数据访问的问题。缺点是仅支持get方法具有局限性,不安全可能会遭受XSS攻击。
function jsonp({ url, params, callback }) {
return new Promise((resolve, reject) => {
let script = document.createElement('script')
// 设置全局函数show()
window[callback] = function(data) {
resolve(data)
document.body.removeChild(script)
}
// 拼接url和参数
let arrs = []
params = { ...params, callback }
for (let key in params) {
arrs.push(`${key}=${params[key]}`)
}
// 标签赋值
//http://localhost:3000/test/getData?wd=Iloveyou&callback=show
script.src = `${url}?${arrs.join('&')}`
// 标签插入DOM,执行请求
document.body.appendChild(script)
// 请求成功,后台传回来一个 show('i don love you'),执行全局函数show(data)
})
}
jsonp({
url: 'http://localhost:3000/test/getData',
params: { wd: 'Iloveyou' },
callback: 'show'
}).then(data => {
console.log(data)
})
服务端
router.get('/getData',(req,res)=>{
// let { wd, callback } = req.query;
res.end(`${callback}('i don love you')`)
});
使用jsonp必须设置回调函数,服务端中传回来的是一个字符串 show('i don love you'),但该字符串会放到请求的<script>中,即执行该回调函数。
2. CORS
CORS 需要浏览器和后端同时支持。IE 8 和 9 需要通过 XDomainRequest 来实现。
浏览器会自动进行 CORS 通信,实现 CORS 通信的关键是后端。只要后端实现了 CORS,就实现了跨域。
服务端设置 Access-Control-Allow-Origin 就可以开启 CORS。 该属性表示哪些域名可以访问资源,如果设置通配符则表示所有网站都可以访问资源。
router.get('/getData',(req,res)=>{
res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
res.header('Access-Control-Allow-Methods', 'GET'); //设置方法
res.json({'info':'GET okok'})
});
router.post('/submitData',(req,res)=>{
res.header('Access-Control-Allow-Origin', 'http://localhost:8080');
res.header('Access-Control-Allow-Methods', 'POST'); //设置方法
res.json({'info':'POST okok'})
});
前端直接请求即可
this.$axios.get('http://localhost:3000/test/getData').then(res=>{
console.log(res)
});
let data = {
name:'liujiapeng'
};
this.$axios.post('http://localhost:3000/test/submitData',this.$qs.stringify(data)).then(res=>{
console.log(res)
});
3. postMessage
postMessage是H5的新api,主要用于以下情形
- 页面和其打开的新窗口的数据传递
- 多窗口之间消息传递
- 页面与嵌套的iframe消息传递
- 上面三个场景的跨域数据传递
4.WebSocket
Websocket是HTML5的一个持久化的协议,它实现了浏览器与服务器的全双工通信,同时也是跨域的一种解决方案。WebSocket和HTTP都是应用层协议,都基于 TCP 协议。但是 WebSocket 是一种双向通信协议,在建立连接之后,WebSocket 的 server 与 client 都能主动向对方发送或接收数据。
客户端
let socket = new WebSocket('ws://localhost:3001');
socket.onopen = function () {
socket.send('我爱你');//向服务器发送数据
}
socket.onmessage = function (e) {
console.log(e.data);//接收服务器返回的数据
}
服务端
let WebSocket = require('ws');//记得安装ws
let wss = new WebSocket.Server({port:3001});
wss.on('connection',function(ws) {
ws.on('message', function (data) {
console.log(data);
ws.send('我不爱你')
});
});
还有一些跨域方式如:iframe,nginx等等,总结以下:
- CORS支持所有类型的HTTP请求,是跨域HTTP请求的根本解决方案
- JSONP只支持GET请求,JSONP的优势在于支持老式浏览器,以及可以向不支持CORS的网站请求数据。
- 不管是Node中间件代理还是nginx反向代理,主要是通过同源策略对服务器不加限制。
- 日常工作中,用得比较多的跨域方案是cors和nginx反向代理
HTTP缓存
可以在页面meta标签中设置,也可以在第一次请求时在响应头中设置。
router.get('/getData',(req,res)=>{
let { wd, callback } = req.query;
res.writeHead(200, {
'Cache-Control': 'max-age=999'
});
res.end(`${callback}('i don love you'+ ${new Date().getTime()})`)
});
可以看到在响应数据中加入了时间戳,如果不设置缓存,每次刷新时间戳会变。但设置了缓存后,再次刷新结果都是第一次请求的时间戳。
正则表达式题目
给String对象设置一个format方法,使得
"{0} Hello! My name is {1}".format('John','Mary') = 'John Hello! My name is Mary'
其中,展位模板可以为{0}、{{0}}、{{{0}}} .......
String.prototype.format = function(...args){
let str = this+'';
args.forEach((value,index)=>{
// 正则匹配需要变量时,用RegExp对象
let reg = new RegExp("{+"+index+"}+")
str = str.replace(str.match(reg)[0],value)
})
return str;
}
let result = '{{0}} Hello,{1} am {2} years old'.format('Lily','I','17')
console.log(result)
Array.from
// arrayLike:必传参数,想要转换成数组的伪数组对象或可迭代对象。
// mapFunction:可选参数,mapFunction(item,index){…} 是在集合中的每个项目上调用的函数。返回的值将插入到新集合中。
// thisArg:可选参数,执行回调函数 mapFunction 时 this 对象。这个参数很少使用。
Array.from(arrayLike[, mapFunction[, thisArg]])
let s = Array.from([1,2,3,4],(value,index)=>{
return value * 2;
}) // s : [2, 4, 6, 8]
// 2.将类数组转为数组 : 比如DOM集合,arguments对象
// 或者形如 { 0:'liu', 1:'jia', 2:'peng',length:3 }的类数组
let dom_list = document.getElementsByClassName('box')
let dom_arr = Array.from(dom_list);
(function(){
// 当然也可以直接传入 ...args参数,args就是多个参数自动拼接成数组
let args_arr = Array.from(arguments) // [1,2,3,4,5,6,7]
})(1,2,3,4,5,6,7)
// 3 拷贝数组 深拷贝
let a1 = [1,2,3,4];
let a2 = Array.from(a1);
a1 = [11,22,33,44]
console.log(a2) // 1,2,3,4
// 4 填充数组
// 创建一个长度为3的类数组
let empty = {
length:3
}
let fill = Array.from(empty,()=>{
return 0; // 每项设置为0
})
console.log(fill) //[0,0,0]
// 当然也有专门的填充函数
let length = 10 , initValue = 0;
let fill2 = Array(length).fill(initValue,0,length) // (初始值,填充起始索引,填充结束索引) [起始,结束) 左开右闭
console.log(fill2) // [0,0,0,0,0,0,0,0,0,0]
箭头函数中的this
箭头函数中的this在定义的时候就已经确定。
function Person(name){
let self = this;
this.name = name;
(function(){
(()=>{
console.log(this) // window
})();
}).call();
(function(){
(()=>{
console.log(this === self) // True
})();
}).call(self);
(()=>{
console.log(this === self) //True
})();
}
new Person('jiapeng');
HTML转义字符
在xss攻击中,攻击者常会将一段恶意脚本作为字符串提交到服务器中,若服务器没有对输入或输出数据做过滤处理,很容易让其他用户遭受脚本攻击。对于用户的一些输入,不能直接做处理,因为会影响用户体验,那么可以在从数据库取数据时对某些符号做转义。< 对应<、 >对应>
<body>
<div><script>console.log('hello11111')<\script></div>
<div><script>console.log('hello')</script></div>
</body>
可以看到上面一个div直接输出,没有作为脚本执行,而没有转义的第二个div中的脚本执行了。
原生ajax
function ajax_method(url,method,data){
// 新建xhr对象
var xhr = new XMLHttpRequest();
if (method == 'GET') {
xhr.open(method,url);
xhr.send();
}
if (method == 'POST') {
// 调用xhr的
xhr.open(method,url)
xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xhr.send(JSON.stringify(data))
}
xhr.onreadystatechange = function(){
if (xhr.readyState==4 &&xhr.status==200) {
console.log(JSON.parse(xhr.responseText))
}
else{
console.log('wrong');
}
}
}
let data = {
"name":"jiapeng"
}
ajax_method('http://localhost:3000/test/submitData','POST',data)
ajax_method('http://localhost:3000/test/getData','GET')
readyState状态码
-
0- (未初始化)还没有调用send()方法
-
1- (载入)已调用send()方法,正在发送请求
-
2- (载入完成)send()方法执行完成,
-
3- (交互)正在解析响应内容
-
4- (完成)响应内容解析完成,可以在客户端调用了
CSS和JS的加载解析
- css加载不会阻塞DOM树的解析。
- css加载会阻塞DOM树的渲染,即要所有css加载完才会进行渲染
- css加载会阻塞后面js语句的执行、
清除浮动
<head>
<style type="text/css">
.box{
float: right;
width: 100px;
height: 100px;
background-color: red
}
.clearfix:after,.clearfix:before{
content: "";
display: table;
}
.clearfix:after{
clear: both;
}
.clearfix{
*zoom: 1;
}
</style>
</head>
<body>
<div class="clearfix">
<div class="box"></div>
</div>
</body>