Coder Social home page Coder Social logo

myblog's Introduction

myblog's People

Contributors

mamba-1024 avatar

Watchers

 avatar

myblog's Issues

HTML input中type='file' Accept的值

  • .csv
    <input type="file" accept=".csv" />
  • .xls
    <input type="file" accept="application/vnd.ms-excel" />
  • .xlsx
    <input type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
  • .txt
    <input type="file" accept="text/plain" />
  • .jpg、.jpeg、.png
    <input type="file" accept="image/jpeg" /> image/png
    image/jpeg包含 .jpg文件
  • .html
    <input type="file" accept="text/html" />
  • .avi, .mpg, .mpeg, .mp4
    <input type="file" accept="video/*" />
  • .mp3, .wav, etc
    <input type="file" accept="audio/*" />
  • .pdf
    <input type="file" accept=".pdf" />

前端Nginx服务配置

前端Nginx服务配置

本文示例使用的是阿里云的服务器

  1. 在本地终端找到我们需要上传的文件
  2. 使用Linux的scp命令将本地文件上传到Nginx服务器的特定目录下
    通常情况下服务器放置前端资源的目录是 /usr/share/nginx/html
    Linux scp命令:scp -r /tmp/local_dir username@servername:remote_dir
eg: scp -r ./monitor root@servername:/usr/share/nginx/html/
  1. 当我们的文件上传到服务器后,需要配置Nginx服务
  2. 找到Nginx服务的配置文件 =>> cd /etc/nginx
  3. 使用 ls 命令可以看到一个名字叫做 nginx.conf 的文件
  4. 编辑配置文件添加新的server配置 =>> vim nginx.conf
  5. 在配置文件中插入以下配置
配置的端口号根据实际情况自己确认,我的示例使用的 801
# add new nginx web server for monitor
    server
         {
        listen       801 default_server; 
        listen       [::]:801 default_server;
        server_name  _;
        root         /usr/share/nginx/html/monitor/;

        # Load configuration files for the default server block.
        include /etc/nginx/default.d/*.conf;
       
       # location redirect
        location / {
                try_files $uri $uri/ /index.html;
        }

        error_page 404 /404.html;
            location = /40x.html {
        }

        error_page 500 502 503 504 /50x.html;
            location = /50x.html {
        }
    }
  1. 保存退出 =>> esc :wq
  2. 这样我们的Nginxweb服务器就配置完成了,重新启动Nginx服务 =>> service nginx reload
  3. 在浏览器查看我们的web网页,在浏览器输入服务器的IP+端口号即可
    eg: servername:801

以上纯属个人实践所得,如有不妥之处还请指教

two sum

给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那两个整数,并返回他们的数组下标。

你可以假设每种输入只会对应一个答案。但是,你不能重复利用这个数组中同样的元素。

示例:

Given nums = [2, 7, 11, 15], target = 9,
Because nums[0] + nums[1] = 2 + 7 = 9,
return [0, 1].

将数组转存为object,数组的 value 作为 object 的 key,数组的下标作为 object 的 value,
然后去使用 for in 遍历 object,只用 in 判断 value 是否在 object 中。
in使用说明

var twoSum = function(nums, target) {
    let result = {};
    let length = nums.length;
    for (var i = 0; i < length; i++) {
        let difference = target - nums[i];
        if (difference in result) {
            return [result[difference], i]
        }
        result[nums[i]] = i;
    }
};

React生命周期和hock 的一些使用心得

React生命周期

官方介绍

  • componentWillMount()
  • componentDidMount()
    组件已经挂在完成,代表着组件的DOM已经挂载到页面的DOM树上,即使是获取数据后操作DOM也是安全的。
    我们一般会在此生命周期中去进行网络请求,获取数据
  • componentWillReceiveProps(nextProps)
    父组件的更新导致了组件props发生了变化,如果子组件的数据请求依赖了props,那么组件就需要重新请求数据。
  • shouldComponentUpdate(nextProps, nextState) 返回Boolean
  • componentWillUpdate(nextProps, nextState)
  • componentDidUpdate()
  • componentWillUnmount()

react 16.3 版本删除了

componentWillMount()
componentWillReceiveProps(nextProps)
componentWillUpdate(nextProps, nextState)

react hock

useEffecteffects的心智模型和componentDidMount以及其他生命周期函数式不同的。它的心智模型更接近于状态同步,而不是响应生命周期事件

react Hooks性能优化:

  • 减少rerender次数 。当父组件重新属性更新触发重新渲染的时候,子组件也会重新渲染
    1. 其实我们的子组件属性没有任何变化,此时我们不希望子组件重新渲染,我们可以将子组件使用memo将子组件包一下。
    2. 当父组件的方法通过props传给了子组件是,对子组件只使用memo是不行的,我们需要将父组件的方法通过useCallback钩子包一下,同时需要将钩子的依赖设置为[]空依赖。
  • 减少rerender复杂度。使用memoize-one,来减少数据计算,如果入参不发生变化的话
    // 在上一次render后,如果参数没有发生改变,memoize-one 会重复使用上一次的返回结果
      const filterList = this.filter(this.props.list, this.state.filterText);
    

我们可以说useEffectuseCallback是有返回值的,它的返回称之为memoize,它可以根据钩子的第二个参数(依赖数组),来确定是否重新执行钩子中的函数。

useCallback: 不会随着组件更新而重新创建callback方法

开发自己的cli工具

天下武功唯快不破...
cli的目的就是为了提高开发效率,把自己常用的React脚手架使用cli来初始化。

记录一下自己cli的心路历程:
新建一个文件夹kt-cli

  • 初始化项目配置文件 package.json

进入kt-cli文件夹中 执行 npm init 初始化默认配置;

  • 配置入口文件

在package.js文件中,需要新增

"bin": {
    "kt-cli": "bin/kt-cli.js"
  }
  • 安装必须的依赖

npm install commander --save 
npm install git-clone --save
npm install shelljs --save
npm install tracer --save
  • 编写kt-cli.js文件

#!/usr/bin/env node

const clone = require("git-clone");
const program = require("commander");
const shell = require("shelljs");
const log = require("tracer").colorConsole();

program.version("1.0.0").description("我的React—cli");

program.command("create [project]").action(function( project) {
  log.info("准备生成react模板;");
  if (project) {
    let pwd = shell.pwd();
    log.info(`正在拉取模板代码,下载位置:${pwd}/${project}/ ...`);
    clone(
      `https://github.com/huangketong/umi-react-admin.git`,
      pwd + `/${project}`,
      null,
      function() {
        shell.rm("-rf", pwd + `/${project}/.git`);
        log.info("模板建立完成");
      }
    );
  } else {
    log.error("正确命令例子:kt-cli create myUmi");
  }
});
program.parse(process.argv);

到此我的cli就已经完成了。
接下来就需要把cli发布到npm上。

JavaScript数据类型、this、按值传递

数据类型

  • 基本数据类型包含: undefined,null,Boolean,Number、String

    它们的值保存在栈空间,我们通过按值来访问的.
  • 引用类型: 对象Object、数组Array、函数function 等,

    对应的值,则必须在堆内存中为这个值分配空间。由于引用类型值得大小不固定(对象有很多属性和方法),因此不能把它们保存在栈内存中。但是内存地址大小是固定的,因此可以将内存地址保存在栈内存中。

    简而言之:栈内存中存放的是基本数据类型值,堆内存中存放引用类型值,引用类型值在内存中的地址存放在栈中,也就是我们常说的对象引用(指针)。
var a = 5;
var b = a;
console.log(a+"---"+b); // 5---5
b = 6; // 这里重新给b赋值,a值并没有改变
console.log(a+"---"+b);// 5---6

var obj = { name: "lisi" };
var obj2 = obj; // 这里是引用赋值,obj和obj2指向同一个对象
console.log(obj.name + "---" + obj2.name); // lisi---lisi
obj2.name = "wangwu";
console.log(obj.name + "---" + obj2.name);//wangwu---wangwu

从上面例子可以看出:在变量复制方面,基本类型和引用类型也有所不同,基本类型复制的是值本身,而引用类型复制的是内存地址。

JavaScript继承

几种JavaScript继承方法

1. 原型链继承

让子类的原型指向父类的实例

function Parent () {  // 父类构造函数
  this.name = "Jarry";
}
Parent.prototype.getName = function () { // 给Parent添加getName的属性方法
 console.log(this.name);
}
function Child () {  // 定义子类
}
// 每一个JavaScript对象(null除外)在创建的时候就会与之关联另一个对象,这个对象就是我们所说的原型,每一个对象都会从原型"继承"属性。
Child.prototype = new Parent(); 

var new_child = new Child();
console.log( new_child.getName() );  // Jarry

引入的问题:
1、引用类型的属性被所有实例共享。

function Parent () {
  this.names = [ 'Tom', 'Jarry' ];
}
function Child () {
}
Child.prototype = new Parent();

var child1 = new Child();
console.log(child1,name); //  [ 'Tom', 'Jarry'  ];
child1.names.push( 'Ketong' );
console.log(child1,name); //  [ 'Tom', 'Jarry',  'Ketong'  ];

console.log(child2.names === child1.names); // true 属于同一个引用

var child2 = new Child();
console.log(child2.name);//  [ 'Tom', 'Jarry',  'Ketong'  ];

2、在创建 Child 实例的时候,不能向Parent 传参

|

初探二叉树

二叉树作为一种很基础但是又很重要的数据结构,在某些场景下还是比较重要的。所以掌握二叉树的重要性就不言而喻了。

二叉树

二叉树是由根节点,左子树,右子树组成,左子树和友子树分别是一个二叉树

举个栗子:

var binaryTree = {
  value: 1,
  left: {
    value: 2,
    left: {
      value: 4
    }
  },
  right: {
    value: 3,
    left: {
      value: 5,
      left: {
        value: 7
      },
      right: {
        value: 8
      }
    },
    right: {
      value: 6
    }
  }
}

遍历二叉树

递归遍历

  1. 先序遍历:访问根–>遍历左子树–>遍历右子树;
var preListRec = []; //定义保存先序遍历结果的数组
var preOrderRec = function(node) {
    if (node) { //判断二叉树是否为空
        preListRec.push(node.value); //将结点的值存入数组中
        preOrderRec(node.left); //递归遍历左子树
        preOrderRec(node.right); //递归遍历右子树
    }
}
preOrderRec(tree);
console.log(preListRec)
  1. 中序遍历:遍历左子树–>访问根–>遍历右子树;
var inListRec = []; //定义保存中序遍历结果的数组
var inOrderRec = function(node) {
    if (node) { //判断二叉树是否为空
        inOrderRec(node.left); //递归遍历左子树
        inListRec.push(node.value); //将结点的值存入数组中
        inOrderRec(node.right); //递归遍历右子树
    }
}
inOrderRec(tree);
console.log(inListRec);
  1. 后序遍历:遍历左子树–>遍历右子树–>访问根;
var postListRec = []; //定义保存后序遍历结果的数组
var postOrderRec = function(node) {
    if (node) { //判断二叉树是否为空
        postOrderRec(node.left); //递归遍历左子树
        postOrderRec(node.right); //递归遍历右子树
        postListRec.push(node.value); //将结点的值存入数组中
    }
}
postOrderRec(tree);
console.log(postListRec);

非递归遍历

  1. 广度优先遍历

广度优先遍历是从二叉树的第一层(根结点)开始,自上至下逐层遍历;在同一层中,按照从左到右的顺序对结点逐一访问

实现原理:

使用数组模拟队列,首先将根结点归入队列。当队列不为空时,执行循环:取出队列的一个结点,如果该节点有左子树,则将该节点的左子树存入队列;如果该节点有右子树,则将该节点的右子树存入队列

var breadthList = []; // 定义保存广度遍历结果的数组
var breadthTraversal = function(node) {
    if (node) { // 判断二叉树是否为空
        var que = [node]; // 将二叉树放入队列 var que = []; que.push(node);
        while (que.length !== 0) { // 判断队列是否为空
            node = que.shift(); // 从队列中取出一个结点
            breadthList.push(node.value); // 将取出结点的值保存到数组
            if (node.left) que.push(node.left); // 如果存在左子树,将左子树放入队列
            if (node.right) que.push(node.right); // 如果存在右子树,将右子树放入队列
        }
    }
}
breadthTraversal(tree);
console.log(breadthList);

微信授权登录解密手机号失败

微信小程序开发时候,使用手机号授权登录,会遇到手机解密失败的情况。

后端抛出错误如下:

javax.crypto.BadPaddingException: pad block corrupted

问题收集:

  1. javax.crypto.BadPaddingException: pad block corrupted
  2. 解密用户信息报错pad block corrupted
  3. 微信登录授权偶尔出现第一次解密失败,第二次解密成功,报错为pad block
  4. 小程序登录第一次总是会失败,第二次肯定成功pad block corrupted

总结原因:

问题还是处在微信的 sessionKey

当我在getPhoneNumber中使用wx.login的时候,第一次总是手机号机密失败,第二次可以成功。

解决方案:

在页面 onShow 中先调用一次 wx.login 将临时 code 暂存,然后在 getPhoneNumber先使用code,这样就能保证每次sessionKey是最新的。

微信小程序的消息订阅功能,不能放在异步函数中

参考

谈一谈自己对跨域的理解

跨域

指一个域下的文档或脚本试图去请求另一个域下的资源

常见跨域场景

URL                                      说明                    是否允许通信
http://www.domain.com/a.js
http://www.domain.com/b.js         同一域名,不同文件或路径           允许
http://www.domain.com/lab/c.js

http://www.domain.com:8000/a.js
http://www.domain.com/b.js         同一域名,不同端口                不允许
 
http://www.domain.com/a.js
https://www.domain.com/b.js        同一域名,不同协议                不允许
 
http://www.domain.com/a.js
http://192.168.4.12/b.js           域名和域名对应相同ip              不允许
 
http://www.domain.com/a.js
http://x.domain.com/b.js           主域相同,子域不同                不允许
http://domain.com/c.js
 
http://www.domain1.com/a.js
http://www.domain2.com/b.js        不同域名                         不允许

千分位格式化

千分位格式化

通常我们前端拿到后端给的金额数据都是保留两位小数的字符串

此时就需要我们把它转为市面上标准的千分位显示格式

例如:将金额字符串转化为千分的逗号分隔形式 "1,000,000.00"

使用正则表达式

function toThousands (price: string) {
  if(price) {
    return price.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",")
  } else {
    return ''
  }
}
``

moment.js工作中常用的api

工作遇到过的moment.js的api

  1. isBefore
if(moment(startDate).isAfter(endDate)) {
    return Toast.fail('开始时间不能晚于结束时间')
}
  1. diff

比价两个date的差

var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b, 'days') // 
  1. add

增加

moment().add(7, 'days');

  1. subtract

减少

moment().subtract(7, 'days');

axios拦截器处理重定向

前端请求后端接口的时候,会涉及当前用户信息已经过期的问题。

通常后端定义重定向都是使用 302 状态码,然后附带重定向的地址。但是,

类似于 401、403、500 等状态码都可以在error回调中捕获到,但是 302 状态码是捕获不到的,因为当状态时 302 时,浏览器自行根据redirectUrl进行了跳转,所以无法在 success 或者 error 回调中捕获到这个 302 信息。

针对上面前端无法获取 302 的问题,可以前后端约定一个 401 等等的状态码,然后使用 axios 的拦截器去处理响应。
具体处理方式:

// Add a response interceptor
axios.interceptors.response.use(function (response) {
    // Any status code that lie within the range of 2xx cause this function to trigger
    // Do something with response data
    return response;
  }, function (error) {
    // Any status codes that falls outside the range of 2xx cause this function to trigger
    // Do something with response error
   if(error.response.status === 302) {
     window.location = '/login';
   } else {
     return Promise.reject(error);
   }
  });

browserslist参数理解

使用它的意义

根据提供的目标浏览器,智能添加css前缀,js的polyfill,来兼容浏览器。

可以共享browserslist 的组件

  • Autoprefixer postcss ( 添加 css 前缀组件)
  • bable-preset-env (编译预设环境 智能添加 polyfill 代码)
  • eslint-plugin-compat
  • stylelint-no-unsupported-browser-features
  • postcss-normalize
  • Babel (external config in package.json or browserslist will be supported in 7.0)

基本语法

只要package.json配置了browserslist对象,需要的组件将自动匹配到并使用,也可以配置到具体的组件参数上

   {
            'browserslist': [
                 '> 1%',  // 全球超过1%人使用的浏览器
                 'last 2 version', // 所有浏览器兼容到最后两个版本
                 'Firefox > 20', // 指定浏览器的版本范围
             ]
    }

拥抱正统

browserslist官方地址

排序算法

基础的排序算法

冒泡排序(BubbleSort)

冒泡排序是比较经典的算法之一,也是排序最慢的算法之一。
冒泡排序的基本思路如下(升序排序):

  1. 比较相邻的元素,如果第一个比第二个大,就交换它们两个位置;
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样最终最大数被交换到最后的位置;
  3. 除了最后一个元素以外,针对所有的元素重复以上的步骤;
  4. 重复步骤1~3,直到排序完成。
// 冒泡排序
function bubbleSort ( data ) {
    var temp = 0;
    for ( var i = data.length ; i > 0 ; i -- ){
        for( var j = 0 ; j < i - 1 ; j++){
           if( data[j] > data[j + 1] ){
               temp = data[j];
               data[j] = data [j+1];
               data[j+1] = temp;
           }
        }
    }
    return data;
}
// 运行结果如下:
> var arr = [99,77,87,100, 6, 38, 69, 32, 2, 6, 9, 55, 69];
> bubbleSort(arr);
> [2, 6, 6, 9, 32, 38, 55, 69, 69, 77, 87, 99, 100]

选择排序(SelctionSort)

选择排序是一种比较简单直观的排序算法。它的算法**是,从数组的开头开始遍历,将第一个元素和其他元素分别进行比较,记录最小的元素,等循环结束之后,将最小的元素放到数组的第一个位置上,然后从数组的第二个位置开始继续执行上述步骤。当进行到数组倒数第二个位置的时候,所有的数据就完成了排序。

选择排序同样会用到嵌套循环,外循环从数组第一个位置移到倒数第二个位置;内循环从第二个位置移动到数组最后一个位置,查找比当前外循环所指向的元素还要小的元素,每次内循环结束后,都会将最小的值放到合适的位置上。

//选择排序
function selectionSort( data ) {
    for( var i = 0; i< data.length ; i++){
        var min = data[i];
        var temp;
        var index = i;
        for( var j = i + 1; j< data.length; j++){
            if( data[j] < min ){
                min = data[j];
                index = j;
            }
        }

        temp = data[i];
        data[i] = min;
        data[index]= temp;
    }
    return data;
}

// 运行结果如下:
> var arr = [99,77,87,100, 6, 38, 69, 32, 2, 6, 9, 55, 69];
> selectionSort(arr)
> [2, 6, 6, 9, 32, 38, 55, 69, 69, 77, 87, 99, 100]

插入排序(insertionSort)

插入排序是一种简单直观的排序算法。它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
插入排序的实现过程:

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到下一位置中
  6. 重复步骤2~5
//插入排序

function insertionSort( data ) {
    var len = data.length;
    for (var i = 1; i < len; i++) {
        var key = data[i];
        var j = i - 1;
        while ( j >= 0 && data[j] > key) {
            data[j + 1] = data[j];
            j--;
        }
        data[j + 1] = key;
    }
    return data;
}

在运算速度上,冒泡排序是最慢的,插入排序是最快的,我们可以在运行的过程中通过 console.time('sortName') 和 console.timeEnd('sortName') 来看他们的效率如何

阅读《你不知道的JavaScript》笔记

理解JavaScript的环境

  • 引擎
    从头到尾负责整个JavaScript程序的编译及执行过程
  • 编译器
    引擎的好朋友之一,负责语法分析及代码生成等脏活累活
  • 作用域
    引擎的另一位好朋友,负责收集并维护由所有声明的变量组成的一系列查询,并实施一套非常严格的规则,确定当前执行的代码对这些标识符的访问权限。

css3之@keyframes

css3样式

div{
   width: 100px;
   height: 100px;
   background: red;
   position: relative;
   animation: mymove 5s infinite;
   -moz-animation: mymove 5s infinite; /* Firefox */
   -webkit-animation: mymove 5s infinite; /* Safari and Chrome */
   -o-animation: mymove 5s infinite; /* Opera */
}
@keyframes mymove
{
  from {top:0px;}
  to {top:200px;}
}

@-moz-keyframes mymove /* Firefox */
{
  from {top:0px;}
  to {top:200px;}
}

@-webkit-keyframes mymove /* Safari 和 Chrome */
{
  from {top:0px;}
  to {top:200px;}
}

@-o-keyframes mymove /* Opera */
{
  from {top:0px;}
  to {top:200px;}
}

语法

@keyframes animationname {keyframes-selector {css-styles;}}

  • animationname 动画名称
  • keyframes-selector 动画时长的百分比
    • 0—100%
    • from(与 0% 相同)
    • to(与 100% 相同)
  • css-styles 一个或者多个css样式属性

RN的TouchableOpacity的使用笔记

在RN中有时候需要为Image组件添加点击事件,但是Image本身又是不支持的,所以我们常用

TouchableWithoutFeedback
TouchableOpacity
TouchableHighlight

Image组件包括一下,将onPress事件加到上面。

  • TouchableOpacity

本组件用于封装视图,使其可以正确响应触摸操作。当按下的时候,封装的视图的不透明度会降低。

不透明度的变化是通过把子元素封装在一个Animated.View中来实现的,这个动画视图会被添加到视图层级中,少数情况下有可能会影响到布局。

此组件与TouchableHighlight的区别在于并没有额外的颜色变化,更适于一般场景。)

示例

renderButton: function() {
  return (
    <TouchableOpacity onPress={this._onPressButton}>
      <Image
        style={styles.button}
        source={require('./myButton.png')}
      />
    </TouchableOpacity>
  );
},
  • TouchableWithoutFeedback

除非你有一个很好的理由,否则不要用这个组件。所有能够响应触屏操作的元素在触屏后都应该有一个视觉上的反馈(然而本组件没有任何视觉反馈),这也是为什么一个"web"应用总是显得不够"原生"的主要原因之一。

注意TouchableWithoutFeedback只支持一个子节点(不能没有子节点也不能多于一个)。如果你希望包含多个子组件,可以用一个View来包装它们。

常见的使用场景比如想实现点击空白处触发某个操作,那么就可以把空白部分用TouchableWithoutFeedback包起来,或者绝对定位覆盖住。

示例

  • TouchableHighlight

本组件用于封装视图,使其可以正确响应触摸操作。当按下的时候,封装的视图的不透明度会降低,同时会有一个底层的颜色透过而被用户看到,使得视图变暗或变亮。

在底层实现上,实际会创建一个新的视图到视图层级中,如果使用的方法不正确,有时候会导致一些不希望出现的视觉效果。譬如没有给视图的backgroundColor显式声明一个不透明的颜色。

注意TouchableHighlight只支持一个子节点(不能没有子节点也不能多于一个)。如果你希望包含多个子组件,可以用一个View来包装它们。

示例

HTTPS初探

HTTP协议(HyperText Transfer Protocol,超文本传输协议):是客户端浏览器或者其他程序与web服务器之间的应用层通信协议

HTTPS协议(HyperText Transfer Protocol over Secure Socket Layer):可以理解为HTTP+SSL/TLS,即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要 SSL,用于安全的 HTTP 数据传输。

SSL(Secure Socket Layer,安全套接字层):1994年为 Netscape 所研发,SSL 协议位于 TCP/IP 协议与各种应用层协议之间,为数据通讯提供安全支持

TLS(Transport Layer Security,传输层安全):其前身是 SSL,它最初的几个版本(SSL 1.0、SSL 2.0、SSL 3.0)由网景公司开发,1999年从 3.1 开始被 IETF 标准化并改名,发展至今已经有 TLS 1.0、TLS 1.1、TLS 1.2 三个版本。SSL3.0和TLS1.0由于存在安全漏洞,已经很少被使用到。TLS 1.3 改动会比较大,目前还在草案阶段,目前使用最广泛的是TLS 1.1、TLS 1.2。

实际使用

SSL/TLS的工作过程

  • 通过CA体系交换public key
  • 通过非对称加密算法,交换用于对称加密的密钥
  • 通过对称加密算法,加密正常的网络通信

CA作为一个公证机构,能确保数字证书的真实性,CA认证一般是要收费的

  • 当客户端去访问一个带有CA认证的Web服务器的时候

  • 服务器返回经过CA认证的数字证书,证书里面包含了服务器的public key

    这里服务器发送了一个SSL证书给客户端,SSL 证书中包含的具体内容有:

    1. 证书的发布机构CA
    2. 证书的有效期
    3. 公钥
    4. 证书所有者
    5. 签名

    ...

  • 客户端拿到数字证书,用自己浏览器内置的CA证书解密得到服务器的public key

    客户端在接受到服务端发来的SSL证书时,会对证书的真伪进行校验

    1. 首先浏览器读取证书中的证书所有者、有效期等信息进行一一校验
    2. 浏览器开始查找操作系统中已内置的受信任的证书发布机构CA,与服务器发来的证书中的颁发者CA比对,用于校验证书是否为合法机构颁发
    3. 如果找不到,浏览器就会报错,说明服务器发来的证书是不可信任的
    4. 如果找到,那么浏览器就会从操作系统中取出 颁发者CA 的公钥,然后对服务器发来的证书里面的签名进行解密
    5. 浏览器使用相同的hash算法计算出服务器发来的证书的hash值,将这个计算的hash值与证书中签名做对比
    6. 对比结果一致,则证明服务器发来的证书合法,没有被冒充
    7. 此时浏览器就可以读取证书中的公钥,用于后续加密了
  • 客户端用服务器的public key加密一个用于接下来的对称加密算法的密钥,传给web服务器

    因为只有服务器有private key可以解密,所以不用担心中间人拦截这个加密的密钥

  • 服务器拿到这个加密的密钥,解密获取密钥,再使用对称加密算法,和用户完成接下来的网络通信

感谢 HTTPS系列干货(一):HTTPS 原理详解浅谈SSL/TLS工作原理

js触发子元素事件,而不触发父元素事件(阻止事件冒泡)

问题背景:
有时候我们写的代码中会出现元素嵌套,父元素绑定一个事件,子元素也有自己的事件,此时如果我们处理(阻止事件冒泡),就会出现点击子元素的时候同时会触发父元素的事件,往往我们是要规避这种情况的。

传送门-代码实战

自己总结三种方法:

  1. 在原生js使用 window.event.cancelBubble = true
document.getElementById('childT').addEventListener('click', (e) => {
        window.event.cancelBubble = true; // 在原生事件中可以使用
        const name = $(e.target).data('name')
        console.log('child', name)
      }, false)
  1. 在jQuery中使用e.stopPropagation()
$(document)
      .on('click', '.parent', (e) => {
        const name = $(e.target).data('name')
        console.log('parent', name)
      })
      .on('click', '.child', (e) => {
        e.stopPropagation();
        const name = $(e.target).data('name')
        console.log('child', name)
        // 触发子元素的事件中,事件处理完成后,加一个return false,即可阻止父元素事件的触发
        // return false;
      })

3.在jQuery中使用return false

$(document)
      .on('click', '.parent', (e) => {
        const name = $(e.target).data('name')
        console.log('parent', name)
      })
      .on('click', '.child', (e) => {
       //  e.stopPropagation();
        const name = $(e.target).data('name')
        console.log('child', name)
        // 触发子元素的事件中,事件处理完成后,加一个return false,即可阻止父元素事件的触发
        return false;
      })

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.