斌仔

斌仔 查看完整档案

北京编辑河北科技师范学院  |  前端 编辑QED  |  JS工程师 编辑填写个人主网站
编辑

前端开发攻城狮

个人动态

斌仔 赞了文章 · 2019-06-10

浅析Vue中computed与method的区别

其实官方文档对这个已经说的很清楚了,笔者不过是在其基础上进行归纳总结,各位看官还是先去读一下官方文档

1.computed区别于method的两个核心

在官方文档中,强调了computed区别于method最重要的两点

  1. computed是属性访问,而methods是函数调用
  2. computed带有缓存功能,而methods不是

OK,下面我们看一个具体的例子

<!--HTML部分-->
<div id="app">
    <h1>{{message}}</h1>
    <p class="test1">{{methodTest}}</p>
    <p class="test2-1">{{methodTest()}}</p>
    <p class="test2-2">{{methodTest()}}</p>
    <p class="test2-3">{{methodTest()}}</p>
    <p class="test3-1">{{computedTest}}</p>
    <p class="test3-2">{{computedTest}}</p>
</div>

<!--script部分-->
<script>
let vm = new Vue({
    el: '#app',
    data: {
        message: '我是消息,'
    },
    methods: {
        methodTest() {
            return this.message + '现在我用的是methods'
        }
    },
    computed: {
        computedTest() {
            return this.message + '现在我用的是computed'
        }
    }
})
</script>

image.png

2. computed的属性调用

细心的朋友可能已经发现了,在HTML的插值里

  1. computed定义的方法我们是以属性的形式访问的,和data里的属性访问形式一样,{{computedTest}}
  2. 但是methods定义的方法,我们必须要加上()来调用,如{{methodTest()}}否则,视图会出现test1的情况,见下图

clipboard.png

3. computed的缓存功能

首先,我们要明白缓存究竟有什么用?
相比大家都知道HTTP缓存,其核心作用就是对一些服务端未更新的资源进行复用,避免一些无谓的请求,优化了用户的体验

对于computed也是一样的:

在上面的例子中,methods定义的方法是以函数调用的形式来访问的
test2-1,test2-2,test2-3反复地将methodTest方法运行了三遍,如果我们碰到一个场景,需要1000个methodTest的返回值,那么毫无疑问,这势必造成大量的浪费
更恐怖的是,如果你更改了message的值,那么这1000个methodTest方法每一个又会重新计算。。。。

所以,官方文档才反复强调对于任何复杂逻辑,你都应当使用计算属性,例如一些复杂度很高的算法,应当使用computed

computed依赖于data中的数据,只有在它的相关依赖数据发生改变时才会重新求值

如上例,在Vue实例化的时候,computed定义computedTest方法会做一次计算,返回一个值
在随后的代码编写中,只要computedTest方法依赖的message数据不发生改变,computedTest方法是不会重新计算的
也就是说test3-1,test3-2是直接拿到了返回值,并不是是computedTest方法重新计算的结果。

这样的好处也是显而易见的,同样的,如果我们碰到一个场景,需要1000个computedTest的返回值,那么毫无疑问,这相对于methods而言,将大大地节约内存
哪怕你改变了message的值,computedTest也只会计算一次而已

4. computed的总结

  • computed其实是就是属性,之所以与data区分开,只不过为了防止文本插值中逻辑过重,会导致不易维护
查看原文

赞 100 收藏 52 评论 9

斌仔 回答了问题 · 2019-05-20

vant 引入Dialog组件报错

楼主问题解决了吗?请赐教

关注 7 回答 6

斌仔 关注了问题 · 2019-05-20

vant 引入Dialog组件报错

1、引入的dialog,注册了组件,但是会提示没有注册

clipboard.png

2、部分代码如下

                                                                                         html
      <van-dialog
            v-model="show"
            title="修改库存"
            confirm-button-text="保存">
             <van-row>商品名称:{{channel.goodsName}}</van-row>
             <van-row>库存:{{channel.stock}} / {{ channel.maxStock}}</van-row>
      </van-dialog>
import { Dialog, Button, Row, Col } from 'vant'                                             JS
export default {
  components: {
    [Dialog.name]: Dialog,
    [Button.name]: Button,
    [Row.name]: Row,
    [Col.name]: Col
  },

关注 7 回答 6

斌仔 关注了专栏 · 2018-12-19

手摸手系列

手摸手带你学习前端系列

关注 1775

斌仔 发布了文章 · 2018-11-09

微信公众号支付

1、未关注公众号的用户支付成功,无论金额大小均有推荐关注的复选框;

2、关于网络上以支付金额5元为临界点是否出现推荐关注复选框的帖子是官方2016年的文档,现已失效

3、目前最新的官方文档并未发布,以上为测试所得;
附图:

1、已关注:
图片描述

2、未关注:
图片描述

图片描述

图片描述

查看原文

赞 0 收藏 0 评论 0

斌仔 回答了问题 · 2018-11-07

微信H5支付成功后跳出的界面可以像美团扫码支付成功后的界面一样,增加小程序链接和关注按钮吗?

请问楼主这个问题有答案了吗?求指教

关注 5 回答 4

斌仔 赞了文章 · 2018-08-09

前端每日实战:100# 视频演示如何用纯 CSS 创作闪闪发光的霓虹灯文字

图片描述

效果预览

按下右侧的“点击预览”按钮可以在当前页面预览,点击链接可以全屏预览。

https://codepen.io/comehope/pen/GBwvxw

可交互视频

此视频是可以交互的,你可以随时暂停视频,编辑视频中的代码。

请用 chrome, safari, edge 打开观看。

https://scrimba.com/p/pEgDAM/cNLqJhR

源代码下载

每日前端实战系列的全部源代码请从 github 下载:

https://github.com/comehope/front-end-daily-challenges

代码解读

定义 dom,容器中的 3 个元素分别代表文本、渐变背景和光影,其中文本还包含一个数据属性 data-text

<div class="neon">
    <span class="text" data-text="thanks">thanks</span>
    <span class="gradient"></span>
    <span class="spotlight"></span>
</div>

居中显示:

body {
    margin: 0;
    height: 100vh;
    display: flex;
    align-items: center;
    justify-content: center;
    background-color: black;
}

设置文字样式:

.text {
    background-color: black;
    color: white;
    font-size: 180px;
    font-weight: bold;
    font-family: sans-serif;
    text-transform: uppercase;
}

用伪元素和数据属性增加文字,产生描边效果:

.text::before {
    content: attr(data-text);
    position: absolute;
    color: white;
    filter: blur(0.02em);
}

用混色模式产生描边效果:

.text::before {
    mix-blend-mode: difference;
}

设置渐变色背景:

.neon {
    position: relative;
}

.gradient {
    position: absolute;
    background: linear-gradient(45deg, red, gold, lightgreen, gold, red);
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
}

用混色模式把背景作用到文字上:

.gradient {
    mix-blend-mode: multiply;
}

用径向渐变制作光影背景:

.spotlight {
    position: absolute;
    top: 0;
    left: 0;
    right: 0;
    bottom: 0;
    background: 
        radial-gradient(
            circle,
            white,
            transparent 25%
        ) center / 25% 25%,
        radial-gradient(
            circle,
            white,
            black 25%
        ) center / 12.5% 12.5%;
}

设置光影移动的动画效果:

.neon {
    overflow: hidden;
}

.spotlight {
    top: -100%;
    left: -100%;
    animation: light 5s linear infinite;
}

@keyframes light {
    to {
        transform: translate(50%, 50%);
    }
}

用混色模式把光影作用到渐变背景上:

.spotlight {
    mix-blend-mode: color-dodge;
}

最后,调高亮度,并且使文字不能被选中:

.neon {
    filter: brightness(200%);
}

.text {
    user-select: none;
}

大功告成!

查看原文

赞 48 收藏 16 评论 18

斌仔 收藏了文章 · 2018-08-09

前端er怎样操作剪切复制以及禁止复制+破解等

前言

有时候我们经常会碰到这些场景:玩掘金、知乎的时候复制一段文字,总是会在内容后面加上一些版权信息,以及像小说网站等都有禁止选中,禁止复制这种功能,还有点击自动复制账号的功能。

我也经常遇到这些场景,有时候会去想这后面到底是怎么做,周末趁着有空去研究了一下,然后发现这些都跟操作剪贴板有关系,并且都不难,了解一下基本都知道怎么做了,整理分享一波给大家。

个人博客了解一下:obkoro1.com

目录:

  • API介绍
  • 实现类知乎/掘金复制大段文本添加版权信息
  • 实现类起点网的防复制功能
  • 破解防复制
  • 点击复制功能

API介绍:

复制、剪切、粘贴事件:

  1. copy 发生复制操作时触发;
  2. cut 发生剪切操作时触发;
  3. paste 发生粘贴操作时触发;
  4. 每个事件都有一个before事件对应:beforecopybeforecutbeforepaste;

这几个before一般不怎么用,所以我们把注意力放在另外三个事件就可以了。

触发条件:

  1. 鼠标右键菜单的复制粘贴剪切;
  2. 使用了相应的键盘组合键,比如:command+ccommand+v;

    就算你是随便按的,也会触发事件。高程中介绍在ChormeFirefoxSafari中,这几个before事件只会在真实会发生剪贴板事件的情况下触发,IE上则可以触发before。我实际测试的时候最新版chorme也会乱按也会触发,所以限制应该是在早一点的版本上。

    so 想说的是:before这几个事件最好不要用,有关于剪切板的处理最好放在copycutpaste上面。

使用姿势:

以copy为例:

    document.body.oncopy = e => {
        // 监听全局复制 做点什么
    }
    // 还有这种写法:
    document.addEventListener("copy", e => {
        // 监听全局复制 做点什么
    });

上面是在document.body上全局监听的,然而很多人不知道的是,我们还可以为某些dom单独添加剪切板事件:

    // html结构
    <div id="test1"></div>
    <div id="test2"></div>
    // 写法一样:
    let test1 = document.querySelector('#test1');
    test1.oncopy = e => {
        // 监听test1发生的复制事件 做点什么
        // test1发生的复制事件会触发回调,其他地方不会触发回调
    }

其他事件也是一样的,这里就不赘述了。

clipboardData对象:用于访问以及修改剪贴板中的数据

兼容:

不同浏览器,所属的对象不同:在IE中这个对象是window对象的属性,在ChromeSafariFirefox中,这个对象是相应的event对象的属性。所以我们在使用的时候,需要做一下如下兼容:

    document.body.oncopy = e => {
        let clipboardData = (e.clipboardData || window.clipboardData); 
        // 获取clipboardData对象 + do something
    }

对象方法:

对象有三个方法: getData()setData()clearData()

  • getData() 访问剪切板中的数据

    参数: getData()接受一个'text'参数,即要取得的数据的格式。

    在复制、剪切、粘贴触发的事件的数据:

    实际上在chorme上测试只有paste粘贴的时候才能用getData()访问到数据,用法如下:

    要粘贴的数据:

     document.body.onpaste = e => {
         let clipboardData = (e.clipboardData || window.clipboardData); // 兼容处理
         console.log('要粘贴的数据', clipboardData.getData('text'));
     }
    

    被复制/剪切的数据:

    在复制和剪切中的数据,需要通过window.getSelection(0).toString()来访问:

     document.body.oncopy = e => {
         console.log('被复制的数据:', window.getSelection(0).toString());
     }
    
  • setData(): 修改剪切板中的数据

    参数:第一个参数也是'text',第二个参数是要放在剪切板中的文本。

    剩下的留在下面仿知乎/掘金复制大段文本添加版权信息那里再说。

  • clearData() :

    这个方法就不太知道了,试了好久不知道怎么用(如果有大佬知道,可以在评论区指点一下)。

    如果只是为了禁止复制,或者禁止粘贴,在下面还有另外的方法可以做到,并且可以细粒化操作。


应用:

如果学习不是为了装X,那么一切将毫无意义,来看这个东西可以在哪些场景使用:

实现类知乎/掘金复制大段文本添加版权信息:

实现很简单:取消默认复制之后,主要是在被复制的内容后面添加信息,然后根据clipboardData的setData()方法将信息写入剪贴板。

可以直接复制这段代码到本地去试试。

    // 掘金这里不是全局监听,应该只是监听文章的dom范围内。
    document.body.oncopy = event => {
        event.preventDefault(); // 取消默认的复制事件 
        let textFont, copyFont = window.getSelection(0).toString(); // 被复制的文字 等下插入
        // 防知乎掘金 复制一两个字则不添加版权信息 超过一定长度的文字 就添加版权信息
        if (copyFont.length > 10) {
            textFont = copyFont + '\n'
                + '作者:OBKoro1\n'
                + '链接:https://juejin.im/user/58714f0eb123db4a2eb95372/posts\n'
                + '来源:掘金\n'
                + '著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。';
        } else {
            textFont = copyFont; // 没超过十个字 则采用被复制的内容。
        }
        if (event.clipboardData) {
            return event.clipboardData.setData('text', textFont); // 将信息写入粘贴板
        } else {
            // 兼容IE
            return window.clipboardData.setData("text", textFont);
        }
    }

然后command+c、command+v,输出:

你复制的内容
作者:OBKoro1
链接:https://juejin.im/user/58714f0eb123db4a2eb95372/posts
来源:掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

实现类起点网的防复制功能:

  • 禁止复制+剪切
  • 禁止右键,右键某些选项:全选,复制,粘贴等。
  • 禁用文字选择,能选择却不能复制,体验很差。
  • user-select 用css禁止选择文本。

可以把代码拷到本地玩一玩:

    // 禁止右键菜单
    document.body.oncontextmenu = e => {
        console.log(e, '右键');
        return false;
        // e.preventDefault();
    };
    // 禁止文字选择。
    document.body.onselectstart = e => {
        console.log(e, '文字选择');
        return false;
        // e.preventDefault();
    };
    // 禁止复制
    document.body.oncopy = e => {
        console.log(e, 'copy');
        return false; 
        // e.preventDefault();
    }
    // 禁止剪切
    document.body.oncut = e => {
        console.log(e, 'cut');
        return false;
        // e.preventDefault();
    };
    // 禁止粘贴
    document.body.onpaste = e => {
        console.log(e, 'paste');
        return false;
        // e.preventDefault();
    };
    // css 禁止文本选择 这样不会触发js
    body {
        user-select: none;
        -moz-user-select: none;
        -webkit-user-select: none;
        -ms-user-select: none;
    }

PS:

  • 使用e.preventDefault()也可以禁用,但建议使用return false这样就不用去访问ee的方法了。
  • 示例中document.body全局都禁用了,也可以对dom(某些区域)进行禁用。

破解防复制

上面的防复制方法通过js+css实现的,所以思路就是:禁用js+取消user-select样式。

Chrome浏览器的话:打开浏览器控制台,按F1进入Setting,勾选Disable JavaScript(禁止js)。

此时如果还不能复制的话,就要去找user-select样式,取消这个样式就可以了。

所以那些盗版小说手打的,我真的不太能理解,Excuse me???

点击复制功能:

不能使用clipboardData:

在IE中可以用window.clipboardData.setData('text','内容')实现。

上文提到过,在IE中clipboardDatawindow的属性。

而其他浏览器则是相应的event对象的属性,这实际上是一种安全措施,防止未经授权的访问,为了兼容其他浏览器,所以我们不能通过clipboardData来实现这种操作。

具体做法:

  • 创建一个隐藏的input
  • 点击的时候,将要复制的内容放进input框中
  • 选择文本内容input.select()

    这里只能用input或者textarea才能选择文本。

  • document.execCommand("copy"),执行浏览器的复制命令。

    function copyText() {
      var text = document.getElementById("text").innerText; // 获取要复制的内容也可以传进来
      var input = document.getElementById("input"); // 获取隐藏input的dom
      input.value = text; // 修改文本框的内容
      input.select(); // 选中文本
      document.execCommand("copy"); // 执行浏览器复制命令
      alert("复制成功");
    }
    

点击复制内容的demo在这里,可以点进去看看。


结语

工作之余了解一下这些东西还是很有趣的,也可以扩宽你的知识面。

事实上只要监听了这些事件,我们就可以对要剪切的内容进行各种各样的操作,比如:复制的时候更换文本,粘贴的时候查找有没有图片(上传图片),或者文本的长度进行剪切等等,唯一限制你的

希望看完的朋友可以点个喜欢/关注,您的支持是对我最大的鼓励。

个人blog and 掘金个人主页,如需转载,请放上原文链接并署名。码字不易,感谢支持!

如果喜欢本文的话,欢迎关注我的订阅号,漫漫技术路,期待未来共同学习成长。

以上2018.8.8

参考资料:

js高程 14.2.2操作剪贴板

网页上如何实现禁止复制粘贴以及如何破解

原生 js 实现点击按钮复制文本

查看原文

斌仔 收藏了文章 · 2018-07-04

移动端总结

1、移动端的字体

最开始的的方案是:

 body {
  font-family: 'Helvetica Neue', Helvetica, 'microsoft yahei', sans-serif;
 }

升级后的方案:

 body {
  font-family: -apple-system, BlinkMacSystemFont, "PingFang SC","Helvetica Neue",STHeiti,"Microsoft Yahei",Tahoma,Simsun,sans-serif;
 }

以前iOS版本降级使用 Helvetica。 中文字体设置为华文黑体STHeiTi, iOS 9+ 就开始支持 -apple-system 参数了, Chrome 使用 BlinkMacSystemFont ,兼容 iOS/MacOS。
现在很多设计师的字体都是PingFang,所以这里做了一个兼容。 顺便用"Microsoft Yahei"兼容了一下Window系统。
原生 Android 下中文字体与英文字体都选择默认的无衬线字体。 但是因为安卓系统可以去改系统的默认字体,而且每一个手机厂家也会内置字体,所以直接让他去选择默认的吧。不用单独去折腾安卓的字体了。

2、移动端的适配

移动端的适配方案各个厂商都一套方案,但是现在主流的方案是阿里的flexible,具体可以去看下这篇文章: 《使用Flexible实现手淘H5页面的终端适配》
阿里的方案我用过一段时间,但是对于每个device pixel ratio 都要写一个样式,虽然可以用sass、less的mixmin用法来处理,但是不同品尺寸屏幕下所显示的文字个数不一致的问题(如下图:商品的标题),往往会导致用户认为这是一个bug。
iPhone4的渲染图

rem-9.jpg

iPhone6的渲染图
rem-10.png

所以后面的开发就抛弃了这个方案,选中在以前项目中运用到的方案,思路是跟淘宝的思路大体上是一样的,根据750px的设计稿来换算成rem,1px == 0.01rem;

CSS单位rem
在W3C规范中是这样描述rem的:
font size of the root element.

也就是根节点的字体的大小,简单的理解,rem就是相对于根元素<html>的font-size来做计算。而我们的方案中使用rem单位,是能轻易的根据<html>的font-size计算出元素的盒模型大小。

具体怎么换算呢?
把750px的设计稿 1px对应0.01rem即可

思路:

var html=document.querySelector("html");
html.style.fontSize=html.offsetWidth/7.5+"px"
window.onresize=function(){
   var a=document.querySelector("html");a.style.fontSize=a.offsetWidth/7.5+"px";
};

注意:并不是所有的地方都用rem来处理。
移动端的1px边框。
在处理移动端1px边框的时候有两种方案,其中一种方案就是将initial-scale=0.5还有一种方案就是通过伪类来处理。

父级 {
    positon: relative;
}
父级:after {
    content: " ";
    width: 200%;
    height: 200%;
    position: absolute;
    top: -1px;//之所要写成-1px而不是0是因为这个会将整个框下移1px,所以为了避免整个问题将元素上移1px
    left: 0;
    z-index: 1;
    border: 1px solid #ddd;
    border-bottom: 1px solid #ddd;
    -webkit-transform: scale(0.5);
    transform: scale(0.5);
    -webkit-transform-origin: 0 0;
    transform-origin: 0 0;
}

优化后的方案:

;(function(designWidth, rem2px, fixedWidth) {
    //容错
   designWidth = designWidth || 750;//传入设计稿的宽度
   rem2px = rem2px || 100;//rem to px 的关系
   fixedWidth = fixedWidth || 0;//固定最大宽度
   //获取当前html文档
   var docEl = document.documentElement;
   //获取body
   var body = document.querySelector("body");
   //设置固定宽度的大小
   if (!Number(fixedWidth)) {
       //不存在固定值,或者固定值为0
      body.style.maxWidth = designWidth / rem2px + 'rem';
   } else {
     body.style.maxWidth = fixedWidth / rem2px + 'rem';
   }
   body.style.margin = 'auto';
   //这里不设置body的position,为了底部存在可以让positon:absolute的可以吸在键盘上
   //屏幕的宽度
   var tempWidth = window.screen.width;
   var tempHeight = window.screen.height;
   //最小的宽度,以这个宽度来渲染,可以保证旋转的时候字体大小不变 为什么不用文档的宽度, 因为浏览器或者默认的app有时候会占用导航栏,
   //这个时候宽度和高度就会被裁剪一部分,但是这个时候屏幕的宽高是不会因为浏览器或者app的导航栏而被裁剪
   var minWidth = tempWidth > tempHeight ? tempHeight : tempWidth;
   //手机方向
   var orientation = window.orientation;
   //获取当前默认字体的大小,因为安卓可以设置默认字体的大小来进行计算
   var tempDom = window.document.createElement('div');
   tempDom.style.width = '1rem';
   tempDom.style.display = "none";
   var head = window.document.getElementsByTagName('head')[0];
   head.appendChild(tempDom);
   var defaultFontSize = parseFloat(window.getComputedStyle(tempDom, null).getPropertyValue('width'));
   tempDom.remove();
   //设置字体的大小
   window.onresize = function() {
       //延时是因为屏幕旋转获取新的高度需要一定的时间去重新获取高度和宽度
       setTimeout(function() {
            if (typeof(orientation) == "undefined") {
                //如果不支持orientation 那么就根据屏幕的宽高来判断
                var newWidth = window.screen.width;
                if (newWidth != tempWidth) {
                       tempWidth = newWidth
                       //如果屏幕的宽度值改变了
                      ReSetFontSize();
                }
           }
          else {
                 if (orientation != window.orientation) {
                      //设置最新的屏幕方向 为什么要延迟,因为文档去重新并且渲染高度是有一个时间段的
                      orientation = window.orientation;
                        ReSetFontSize();
           }
      }
    }, 100);
};
function ReSetFontSize() {
            //设置body的高度,body的高度不能直接设置成100%会导致重绘,同时为了防止fiex的bug(键盘弹出)
            body.style.height = docEl.clientHeight + "px";
            //设置字体大小
            docEl.style.fontSize = minWidth / designWidth * rem2px / defaultFontSize * 100 + "%";
}
ReSetFontSize();
document.body.classList.remove('vhidden');
})(750, 100, 750);

3、移动端的line-height

为什么这个要单独讲呢,因为这个问题在移动端出现的几率是100%,写习惯了PC端页面的开发者刚开始上手移动端经常会遇到文本垂直居中的问题,明明在谷歌模拟器里面看到文本是垂直居中的,但是为什么在手机上看到文字向上偏移的,而且安卓的问题比较大。transform虽然可以实现,但是感觉写起来却非常的繁琐。
提供两种方法,
1、padding

p{
    /*高度为90px*/
    font-size: .26rem;
    padding: 0.22rem;
}

虽然上面的方法可以实现,但是用起来的时候经常每次都要去计算高度(padding值等于设计高度减去font-size之后再/2),这样就比较麻烦,而且,在针对多行的时候还得计算,于是我又采用了下面的方式。
利用 css3 flex布局的特性。

 p{  
    font-size: .26rem;
    height: 0.9rem;
    display: flex;
    display: -webkit-flex;
    -webkit-align-items:center;
    align-items:center;
    box-pack-align: center;
    -webkit-box-pack-align: center;
}

//同时水平居中也可以用下面的css3属性

box-pack: center;
-webkit-box-pack: center;
-webkit-justify-content: center;
justify-content: center;

4、移动端的布局

移动端的布局情况有点多, 切记移动端最好不要使用postion:fixed,因为这个属性会在ios下产生很多bug。最终我根据之前的项目经验简单做了以下2种分类:

  1. 无固定栏页面

什么叫无固定项,所谓的无固定项页面就是整个网页从上到下没有没有固定在页面上的按钮,头部没有固定的按钮,底部没有固定的按钮,左右两侧也没有侧边栏。用户唯一的操作就是滑动页面到底部。这一类直接跟写PC一样的写法就行了。

  1. 固定项栏页面

基本上市面上所看到的移动端的页面都是固定头部和底部,少量的会加入侧边工具栏。这里主要讲固定头部和底部的。
下面的例子主要把页面分为头部,内容,底部三部分。

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>test</title>
    <meta name="keywords" content="test">
    <meta name="description" content="test">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0,maximum-scale=1.0,user-scalable=no">
</head>
<style>
* {
    margin: 0;
    padding: 0;
    line-height: 1;
    border: 0;
    tap-highlight-color: transparent;
    -webkit-tap-highlight-color: transparent;
    -webkit-box-sizing: border-box;
    box-sizing: border-box;
}

body {
    font-size: 0;
    overflow: hidden;
    background-color: #f2f2f2;
}

.vhidden {
    visibility: hidden;
}

.flex-box {
    display: flex;
    display: -webkit-flex;
}

.vertical-center {
    box-pack: center;
    -webkit-box-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
}

.horizontal-center {
    -webkit-box-align: center;
    align-items: center;
}

input {
    display: block;
    height: 0.88rem;
    font-size: 0.26rem;
    border: none;
    width: 100%;
    text-align: center;
}

input:focus {
    border: none;
    outline: none;
}

header {
    height: 1rem;
    position: relative;
    z-index: 1;
    background-color: #fff;
}

header div {
    box-flex: 1;
    -webkit-box-flex: 1;
    font-size: 0.26rem;
    width: 100%;
}

main {
    -webkit-overflow-scrolling: touch;
    height: calc(100% - 2rem);
    overflow-y: scroll;
    overflow-x: hidden;
    position: relative;
    z-index: 1;
}

main::-webkit-scrollbar {
    display: none;
}

main p {
    padding: 0.2rem;
    font-size: 0.26rem;
    color: #333;
}

footer {
    height: 1rem;
    position: relative;
    z-index: 1;
    background-color: #fff;
}

footer div {
    height: 0.88rem;
    font-size: 0.26rem;
}

footer.bottom-input {
    position: absolute;
    left: 0;
    right: 0;
    bottom: 0;
    z-index: 2;
}

.test1 {
    font-size: .26rem;
    padding: 0.22rem;
    text-align: center;
    background-color: #fff;
    margin: 0.1rem auto;
}

.test2 {
    font-size: .26rem;
    height: 0.9rem;
    display: flex;
    display: -webkit-flex;
    -webkit-box-align: center;
    align-items: center;
    box-pack: center;
    -webkit-box-pack: center;
    -webkit-justify-content: center;
    justify-content: center;
    background-color: #fff;
    margin: 0.1rem auto;
}
</style>

<body class="vhidden">
    <header class="flex-box">
        <div class="flex-box vertical-center horizontal-center">导航栏一</div>
        <div class="flex-box vertical-center horizontal-center">导航栏二</div>
    </header>
    <main>
        <div class="test1">
            这是内容部分1
        </div>
        <div class="test2">
            这是内容部分2
        </div>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <input class="flex-box vertical-center horizontal-center" type="text" name="" id="Input" placeholder="输入点什么">
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
        <p>这是内容部分</p>
    </main>
    <!-- <footer class="flex-box vertical-center horizontal-center">
        <div class="flex-box vertical-center horizontal-center" id="tt">底部按钮</div>
    </footer> -->
    <!-- <footer class="flex-box vertical-center horizontal-center bottom-input">
        <input class="flex-box vertical-center horizontal-center" type="text" name="" id="Input" placeholder="输入点什么">
    </footer> -->
</body>
<script>
(function(designWidth, rem2px, fixedWidth) {
    //容错
    designWidth = designWidth || 750;//传入设计稿的宽度
    rem2px = rem2px || 100;//rem to px 的关系
    fixedWidth = fixedWidth || 0;//是否固定最大宽度,固定宽度

    //如果没有确定就默认设计稿的宽度
    //获取当前html文档
    var docEl = document.documentElement;
    //获取body
    var body = document.querySelector("body");
    //设置固定宽度的大小
    if (!Number(fixedWidth)) {
        //不存在固定值,或者固定值为0
        body.style.maxWidth = designWidth / rem2px + 'rem';
    } else {
        body.style.maxWidth = fixedWidth / rem2px + 'rem';
    }
    body.style.margin = 'auto';
    //这里不设置body的position,为了底部存在可以让positon:absolute的可以吸在键盘上
    //屏幕的宽度
    var tempWidth = window.screen.width;
    var tempHeight = window.screen.height;
    //最小的宽度,以这个宽度来渲染,可以保证旋转的时候字体大小不变 为什么不用文档的宽度, 因为浏览器或者默认的app有时候会占用导航栏,
    //这个时候宽度和高度就会被裁剪一部分,但是这个时候屏幕的宽高是不会因为浏览器或者app的导航栏而被裁剪
    var minWidth = tempWidth > tempHeight ? tempHeight : tempWidth;
    //手机方向
    var orientation = window.orientation;
    //获取当前默认字体的大小,因为安卓可以设置默认字体的大小来进行计算
    var tempDom = window.document.createElement('div');
    tempDom.style.width = '1rem';
    tempDom.style.display = "none";
    var head = window.document.getElementsByTagName('head')[0];
    head.appendChild(tempDom);
    var defaultFontSize = parseFloat(window.getComputedStyle(tempDom, null).getPropertyValue('width'));
    tempDom.remove();
    //设置字体的大小
    window.onresize = function() {
        //延时是因为屏幕旋转获取新的高度需要一定的时间去重新获取高度和宽度
        setTimeout(function() {
            if (typeof(orientation) == "undefined") {
                //如果不支持orientation 那么就根据屏幕的宽高来判断
                var newWidth = window.screen.width;
                if (newWidth != tempWidth) {
                    tempWidth = newWidth
                    //如果屏幕的宽度值改变了
                    ReSetFontSize();
                }
            } else {
                if (orientation != window.orientation) {
                    //设置最新的屏幕方向 为什么要延迟,因为文档去重新并且渲染高度是有一个时间段的
                    orientation = window.orientation;
                    ReSetFontSize();
                }
            }
        }, 100);
    };
    function ReSetFontSize() {
        //设置body的高度,body的高度不能直接设置成100%会导致重绘,同时为了防止fiex的bug(键盘弹出)
        body.style.height = docEl.clientHeight + "px";
        //设置字体大小
        docEl.style.fontSize = minWidth / designWidth * rem2px / defaultFontSize * 100 + "%";
    }
    ReSetFontSize();
    document.body.classList.remove('vhidden');
})(750, 100, 750);
</script>

</html>

Phone手机在滑动overflow-y: scroll的元素上滑动的时候会顿卡,需要加入如下的css代码就可以了

-webkit-overflow-scrolling:touch;

上面的demo在中间部门有输入框并且在底部的时候去点击输入框,弹出的键盘会把输入框盖住,只有在输入部分内容之后输入框才会出现在视窗中。遇到这种情况需要加入如下代码。

var element = document.getElementById("box");
element.scrollIntoView();
//element.scrollIntoView(false);
//scrollIntoView 可选参数是 true false,默认是true
//true 元素的顶端将和其所在滚动区的可视区域的顶端对齐。
//false 元素的底端将和其所在滚动区的可视区域的底端对齐。

5、移动端的bfc

这个bfc不是格式化上下文,而是back forward cache(往返缓存),这个特性最早出现在Firefox和Opera浏览器上,可以在用户使用浏览器的“后退”和“前进”按钮时加快页面的转换速度。
原理就是浏览器会把之前访问的页面缓存到浏览器内存里面,当用在进行“后退”和“前进”操作的时候,浏览器会直接从缓存里面把页面展现到前台,从而不去刷新页面。
但是这样会导致用户在子页面与上一个页面之前存在管理的时候,操作后返回上个页面的状态并没有更改。
这个时候我们就需要去检测页面是不是从缓存里面读取出来的页面。

$(window).on('pageshow', function(event) {
    if (event.persisted) {
        location.reload(true);
    }
});

或者

window.addEventListener("pageshow", funtion(event){
    if (event.persisted) {
        location.reload(true);
    }
});

6、移动端与客户端的交互

现在内嵌H5开发的页面越来越多,前端跟客户端的交互也就越来越多,现在运用得最多的方式是用JSBridge来通信,其主要原理就是就是通过某种方式触发一个url(iframe)的改变,原生捕获到url,进行分析,得到自己想要的数据信息。
之所以要考虑用JSBridge来通信是考虑到
Android4.2以下,addJavascriptInterface方式有安全漏掉
iOS7以下,无法用到ios提供给前端最新的api messageHandlers
因为现有的手机基本上都是4.2以上以及iOS7以上,所以我们可以放心大胆使用上面两个属性。

var ua = navigator.userAgent.toLowerCase();
window.isAndroid = /android/.test(ua);
window.HtmlWebviewCallNative = function(par) {
    if (/客户端ua标识/.test(ua)) {
 //判断是否在客户端打开的页面
        if (isAndroid) {
            //Android这个是安卓向浏览器注入的对象,这个看安卓客户端给的是什么
            Android.HTMLCallNative(JSON.stringify(par));
        } else {
            window.webkit.messageHandlers.HTMLCallNative.postMessage(par);
        }
    } else {
        console.log(JSON.stringify(par))
    }
};

//调用方法eg

HTMLCallNative({
   functionName: 'callPhone',
   params: ['13883785984', '18323270482'],
   callback: 'callbackFunctionName'
});

原理以及参数说明
1.通过向window注册一个名字为HTMLCallNative的对象,以后每次向这个函数传递要通信的函数名和函数所需的参数即可;安卓是通过addJavascriptInterface直接注入页面,ios是通过WKWebView的新特性MessageHandler来这个对象来实现JS调用原生方法。
2.约定HTMLCallNative这个方法名为app中默认用来接受新交互规则的入口函数,安卓和ios分别拿到HTMLCallNative传过来的function名字和参数。
3.客户端通过反射机制,查找字符串函数名对应的函数并执行函数,此时通信成功。
4.functionName: 必为字符串,驼峰式命名,这个字符串为真正调用的方法,需要前端跟客户端共同来定义。
5.params:方法需要的参数,无需对参数进行encodeURIencodeURIComponent, 支持字符串,arrayobject
6.callback: 有回调函数时,传入这个参数,只需要传入函数名称即可,若回调函数需要传入参数,app端在调用的时候传入即可,跟当时业务相关,这里就不约定格式了。

相比JSBridge的优点:
1.在JS中写起来简单,不用再用创建iframe然后触发URL的方式那么麻烦了。
2.JS传递参数更方便。使用拦截URL的方式传递参数,只能把参数拼接在后面,如果遇到要传递的参数中有特殊字符,如&、=、?等,必须得转换,否则参数解析肯定会出错。
例如传递的url是这样的:
http://www.baidu.com/share/op...
使用拦截URL 的JS调用方式

loadURL("firstClick://shareClick?title=分享的标题&content=分享的内容&url=链接地址&imagePath=图片地址"); }

将上面的url 放入链接地址这里后,根本无法区分share_uuid是其他参数,还是url里附带的参数。
但是使用MessageHandler 就可以避免特殊字符引起的问题。

7、移动端唤起手机app

首先,我们看下安卓的配置文件和Scheme

<activity android:name = ".MainActivity">
    <intent-filter>
        <action android:name = "android.intent.action.MAIN" />
        <category android:name = "android.intent.category.LAUNCHER" />
    </intent-filter>
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <data android:host="xxx.com" android:scheme="abraham"/>
    </intent-filter>
</activity>

重点关<data android:host="xxx.com" android:scheme="abraham"/>,前端就需要根据这个字来唤起app

<a href="abraham:/xxx.com/?pid=1">打开app</a>

schema拼接协议的格式:[scheme]://[host]/[path]?[query]
当然ios的也有自己的协议,通常在写唤起app之前需要跟客户端的同事进行对接一下,拿到他们的协议。

注意schema协议要小写,否则会有不能响应的异常!

当然我们可以整合一下代码,把ios的也加进来:

var u = navigator.userAgent;var isAndroid = u.indexOf('Android') > -1 || u.indexOf('Linux') > -1; //android终端或者uc浏览器var isiOS2 = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/); //ios终端if (isAndroid) {
    window.location.href = "安卓提供协议url";
    /***打开app的协议,有安卓同事提供***/
    window.setTimeout(function() {
        window.location.href = '下载的地址';
    }, 2000);
} else if (isiOS2) {
    window.location.href = "IOS提供协议url";
    /***打开app的协议,有ios同事提供***/
    window.setTimeout(function() {
        window.location.href = '下载的地址';
    }, 2000);
} else {
    window.location.href = '下载的地址';
}

简单的唤起方法没有解决在其他应用唤起的bug,可以通过下面的唤起 [https://github.com/sunhaikuo/js-arouse-app][4]

查看原文

斌仔 收藏了文章 · 2018-07-04

[杂谈]了解一些额外知识,让前端开发锦上添花

劝了别人无数次,让别人喝了鸡汤,帮别人填坑,自己却掉了坑

1.前言

在前端学习里面,很多人都是注重学习代码(html,css,js)。或者是一些框架,库(jquery,vue,react),或者是各种工具(webpack,gulp)。在以往的文章里面,或者自己和别人交谈,都有建议过别人多练,不要闷头就写代码,多深入了解当中的原理,学习其中的思想。但是除了代码方面的知识之外,还有哪一些是作为一个前端,应该扩展学习的呢?下面简单罗列和整理了一下最近学习的资源。如果大家还有其它的推荐,欢迎在评论区留言。

下面的知识,可能不需要太过于深入,详细的掌握,但是必须要有所了解,这样在开发上遇到问题,解决问题的时候即使不是如虎添翼,也是锦上添花。

2.http,https

前端而言,不可避免的要和接口打交道。除了和后台对接口,请求数据,渲染页面,之外。对http的请求,也是要有一个了解,比如http协议,请求方式,请求过程,结果状态码等。了解这些,对开发的时候可能遇到的问题,就可以大概知道问题是怎么产生的,更快的知道怎么解决,避免。

2-1.请求

首先一个请求,包含有请求头,请求行,请求正文。具体是怎样境,看下面的代码

axios({
  method: 'post',
  url: '/user/12345',
  headers:{
    'Content-Type':'application/x-www-form-urlencoded'  
  },
  data: {
    firstName: 'Fred',
    lastName: 'Flintstone'
  }
});

如上所述

methodurl就是这个请求的请求行(这里是请求行部分信息,其实请求行还包括http协议的版本等信息)。headers中的属性就是请求头,里面的属性,全部包含在请求的header里面,是服务端获取客户端版本,缓存等信息的一个途径。data对应的就是请求正文,也就是平常所说的参数。

2-2.响应

在请求发出去,并且响应已经回来的时候,就时候信息可分为响应行,响应头,响应正文。

响应行

引用看云的一个请求作为实例,如下代码就是这个请求的响应行,返回请求的http协议及版本,状态码,请求状态等描述信息。

Request URL:https://www.kancloud.cn/yunye/axios/comment?article_id=234845&page=1
Request Method:GET
Status Code:200 OK
Remote Address:117.23.61.221:443

响应头

响应头和请求头格式一致,返回版本,缓存等信息。

响应正文

平常接触最多的就是响应正文,也就是日常开发需要用到的数据。开发者拿到这些数据之后,再进行相应的处理。

2-3.关于https

关于 https 。下面可以先了解下 http 的缺点,https就是http基础上做的加密处理。

1.通信使用明文不加密,内容可能被窃听
2.不验证通信方身份,可能遭到伪装
3.无法验证报文完整性,可能被篡改

2-4.相关资料

关于http与https就简单说到这里,详细的推荐看下下面的资料。

HTTP教程

HTTP协议【详解】——经典面试题

一个故事讲完https

3.响应状态码

上面提到响应状态码,在这里也简单写下。在前端方面,请求接口可能会接触到各种情况,常见的有下面几个,应该怎么解决,就是具体问题,具体分析。

状态码意义
200请求成功
400参数错误
403拒绝或者禁止访问(无权限访问)
404地址不存在
405客户端请求中的方法被禁止(一般是请求方式错误)
500服务器报错
502请求超时,无效网关
503服务器超载或者维护,无法响应

3-1.参考资料

详细的状态码请参考下面内容。

HTTP状态码

4.前端方面的安全性

4-1.XSS

XSS(Cross Site Scripting)是跨站脚本攻击,为了区分CSS,所以缩写为XSS。XSS攻击方式是往Web页面插入恶意的 JavaScript 代码,当用户浏览网页的时候,插入的代码就是被执行,从而达到攻击的目的。

其中应用比较多的一个就是,在网页一些公用的交互区域。比如搜索的文本框,除了可以输入一些关键字,还可以输入一些 JavaScript 代码,一旦代码点击搜索,代码就会被执行,达到攻击的目的。如下例子

<script>alert(document.cookie);</script>

在文本框中输入以上代码,然后点击提交,就会把用户的cookie弹出来。

XSS防范

1.将重要的cookies标记为HTTP ONLY,让JavaScript代码无法调用,只有http能调用。或者将重要的信息保存在session里面。

2.只允许用户输入我们期望的数据。如消费金额框只能输入数字和小数点。

3.对数据进行加密处理。

4.过滤或者移除特殊的HTML标签,过滤JavaScript代码等。

4-2.CSRF

CSRF(Cross-site request forgery)是跨站请求伪造。XSS利用站点内的信任用户,与XSS不同,CSRF是通过伪装来自受信任用户,在受信任的网站进行请求,盗取信息。其实就是攻击者盗用了受害者的身份,以受害者的名义向网站发送恶意请求。

CSRF攻击的思想

引用CSRF攻击原理及防御的一张图进行解释。

图片描述

图片来自:CSRF攻击原理及防御

根据步骤,看了图,相信不难理解,就是在一个网站里面保留了cookie,然后访问了一些危险网站,然后被危险网站盗用了用户信息。

CSRF的防御

1.在表单里增加Hash值,以认证这确实是用户发送的请求,然后在服务器端进行Hash值验证。

2.验证码:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串。

3.修改,增加重要信息,比如密码,个人信息的操作,尽量使用post。避免使用get把信息暴露在url上面。

4-3.反爬虫

和之前的防护XSS和CSRF攻击目的不一样,反爬虫是为了防止网站重要的数据被别人拿走,比如电商的交易额,电影网站的票房统计,音乐网站的评论等。

反击爬虫,前端工程师的脑洞可以有多大?

5.渲染过程,原理

1.浏览器通过DNS对URL进行解析,找出对应的IP地址;

2.向IP地址发起网络请求,进行http协议会话:客户端发送报头(请求报头),服务端回馈报头(响应报头)

3.服务器根据请求,交给后台处理,处理完成后返回文件数据,浏览器接收文件数据(HTML、JS、CSS、图象等);返回一个页面(根据页面上的外链的URL重新发送请求获取)

4.浏览器接收文件完毕,对加载到的资源进行语法解析,以及相应的内部数据结构(网页渲染)

6.跨域

跨域这方面,平常接触的不多,我们这边遇到也是让后台允许跨域(跨域资源共享),但是这个跨域,也是一个绕不开的话题,受限于篇幅,下面简单进行讲解。

6-1.情形分析

URL说明是否允许通信
http://www.example.com/a.js,http://www.example.com/lab/b.js同一域名,不同文件或路径允许
http://www.example.com:8000/a.js,http://www.example.com/b.js同一域名,不同端口不允许
http://www.example.com/a.js,https://www.example.com/b.js同一域名,不同协议不允许
http://www.example.com/a.js,http://192.168.2xx.2x/b.js域名和域名对应相同ip不允许
http://www.example.com/a.js,http://x.example.com/b.js,http://domain.com/c.js主域相同,子域不同不允许
http://www.example.com/a.js,http://www.demo.com/b.js不同域名不允许

6-2.解决方案

网上的针对跨域的解决方案有很多,大家参考着看就好。虽然罗列这么多,但是我只用过两种。

1、 jsonp

2、 document.domain + iframe

3、 location.hash + iframe

4、 window.name + iframe

5、 postMessage

6、 跨域资源共享(CORS)

7、 nginx代理

8、 nodejs中间件代理

9、 WebSocket协议

6-3.参考资料

前端常见跨域解决方案(全)

前端跨域知识总结

7.性能优化

这里只讲个大概,具体操作得靠自己自行问搜索引擎。

7-1.首屏优化

按需加载,非首屏图片使用预加载或懒加载,DNS,压缩代码,合并图片,减少请求等。

7-2.算法优化

减少沉余的代码,控制循环的次数,避免巨大函数等。

8.SEO

作为前端开发者,在SEO方面接触得应该不少。前端方面,注意SEO的点也不少。下面简单写下,在我开发的项目里面,也有几个项目是需要做SEO的,个人的建议如下几点:

8-1.meta标签

可定义关键词、网站描述

< meta name="keywords" content="关键词1,关键词2" />

< meta name="description" content="描述词1,描述词2" />

8-2.语义化html标签

一方面是,利用html标签,达到语义化的目的,比如列表使用ul,ol。表格使用table等,不建议什么元素都使用div。

另一方面是尽可能使用html5提供的具有语义化的标签。

以前写法

<div class="header"></div>
<div class="main"></div>
<div class="footer"></div>

建议写法

<header></header>
<main></main>
<footer></footer>

8-3.html嵌套级别不宜过多

这一点就是尽量使html做到扁平化,避免嵌套过多,但是这点相对而言,难度比较大。

8-4.img标签四大属性不能省

<img data-original="" alt="图片描述" width="" height=""/>

alt属性是为了让图片因网速慢、src引用错误、浏览器禁用图像、用户使用屏幕阅读器等情况,未成功显示时候,仍可以显示文本,让用户可大概知道这张图片大概是什么。

width和height是为了防止因为图片无法显示,造成页面重新渲染,或者布局错乱。

8-5.h1-h6标签的使用

1.一个页面建议只出现一个h1标签,而且一般是放在网页log上面使用。

2.h2标签一般用于详情页的主标题。详情页没有logo,标题使用h1。如有副标题,使用h3。

3.h1-h6标签自带权重,如果只为了设置字体大小,或者区分样式,不适合使用h1-h6。

8-6.其它方面

关于SEO的其他方式,在网上看到有这样的方法,但是我自己在开发上面没尝试过这样做,这里就简单罗列下,大家参考下。

避免 iframe 标签

重要内容谨慎使用 display:none;

a标签尽量添加title属性

利用布局,把重要内容HTML代码放在最前

使用”rel=nofollow”属性,集中网站权重

最近一段时间很流行前后分离,以及单页应用。但关于前后分离和单页应用这个怎么做SEO现在不清楚(目前我了解的是没法做)。我们现在的做法就是需要做SEO的项目,前端只负责切图,然后后台铺数据,服务端渲染,不是前端渲染。

9.堆、栈?

栈(stack)会自动分配内存空间,会自动释放。堆(heap)动态分配的内存,大小不定也不会自动释放。

基本类型:Undefined、Null、Boolean、Number 和 String,这5中基本数据类型可以直接访问,他们是按照值进行分配的,存放在栈(stack)内存中的简单数据段,数据大小确定,内存空间大小可以分配。

如下例子

let a=1;
let b=a;

clipboard.png

如果修改了b

b=2;

clipboard.png

虽然b一开始是通过a赋值,但是a和b是独立的储存在栈内存里面,修改其中一个,不会对另一个有任何影响。

引用类型:即存放在堆(heap)内存中的对象,变量实际保存的是一个指针,这个指针指向另一个位置。

如下例子

let a={name:'守候'};
let b=a;

clipboard.png

如果修改了b

b.name='sh';

clipboard.png

b通过a赋值,a和b就共用了一个堆内存,修改了a或者b,都直接修改了堆内存的值,就会对另一个产生影响。

10.响应式和自适应

关于这两个的概念,现在没怎么听说了。可能是因为现在主流的就是PC和手机是分开两个项目的原因,也可能是因为这两个概念更应该是设计图的工作。上一次和别人谈论这个问题,还是在一年前,那个时候我还是切图仔。

但是关于这两个概念的区别,大家知道一下就好,下面看两张图片估计就差不多懂了。

clipboard.png

clipboard.png

图片来自:响应式和自适应有什么区别?(这篇文章估计也是抄袭的,但是由于图片我也找不到出处了,就声明这个了)

简单来说:

自适应:一个网页,根据屏幕宽度的改变而改变。代码只有一套。在个别的屏幕上,排版这个比较丑,但是设计,开发成本低。

响应式:一个网页,根据屏幕的宽度的改变而展示不同的效果,代码基本是两套以上。在所有屏幕上都展示很好的效果,但是设计,开发成本高。

自适应实例:携程

响应式实例:segmentfault

11.小结

之所以要发这么一片,总结这一些概念,是因为我和别人交谈的时候,遇到这些总是有一个是是而非的概念。所以最近就抽空看了下这些概念,也和大家分享下这一些知识。这些概念知识,可能只是了解一下,大概知道就好,有些可能要深入了解下,这个就看个人所需了。最后,如果大家还有什么要推荐的概念知识是比较重要,需要了解的,欢迎在评论区留言。

-------------------------华丽的分割线--------------------

想了解更多,关注关注我的微信公众号:守候书阁

图片描述

查看原文

认证与成就

  • 获得 11 次点赞
  • 获得 16 枚徽章 获得 1 枚金徽章, 获得 2 枚银徽章, 获得 13 枚铜徽章

擅长技能
编辑

开源项目 & 著作
编辑

(゚∀゚ )
暂时没有

注册于 2016-10-31
个人主页被 732 人浏览