朱亮的博客

码农,程序猿,未来的昏析师


  • 首页

  • vue源码解析

  • 分类

  • 归档

  • 留言板

  • 关于

你不知道的js阅读小计

发表于 2018-11-29 | 更新于 2019-01-01 | 分类于 读后感 | 评论数: | 阅读次数:

作用域相关

 var a = 2;
浏览器的处理逻辑
1. 遇到var a,编译器会询问作用于是否有一个该名称的变量存在于同一个作用于集合中,若有,则忽略该条,继续编译,否则会要求当前作用域在在当前作用域集合中声明一个新变量,并命名a。
2.接下来编译器会为引擎生成运行时所需要的代码,用来处理a = 2操作。此时引擎会先询问作用域是否存在变量a,如果是,就使用这个变量,并将2赋值给a,否则继续向上查找,直到超出作用域,抛出一个异常。
总结: 编译器会首先声明一个变量(如果之前没有声明过),然后运行时引擎会查找该变量并对该变量进行赋值。

同时,在这个例子中,也存在LHS和RHS查询,L和R分别表示一个赋值操作的左侧和右侧。
RHS只是简单的找到这个变量的值,而LHS是找到这个变量的容器本身。

注: 不成功的LHS会抛出一个(ReferenceError)异常,而一个不成功RHS会创建一个全局变量(费严格模式下)

此法作用域

  • js本身会在编译阶段进行数项的性能优化。但是如果使用eval或者with的话,编译器无法明确的知道会接受到什么样的代码,所以这些优化都会无效,所以不建议使用eval或者with
  • 遮蔽效应
    指由于作用域查找会在找到第一个匹配的值时停止,所以在多层嵌套的作用域中,内部的标识符遮蔽了外部的标识符。
    注:词法作用域只会查找一级标识符,比如foo.bar.baz,此法作用域只会试图查找foo,当找到foo变量时,对象访问规则便会分别接管对bar和baz的访问权限。
    with关键字可能会导致变量的泄露,看如下代码
    function foo(obj) {
    with(obj) {
    a = 2;
    }
    }

    var o1 = {
    a = 3;
    }

    var o2 = {
    b = 2;
    }

    foo(o1);
    foo(o1);
    在这段代码中,当第二次执行foo函数时,因为o2并没有a属性,此时程序会自动创建一个a变量并绑定到全局作用域中。

函数作用域和块作用域

  • 函数作用域
    指属于这个函数的全部变量都可以在整个范围内使用及复用。
  • 最小授权原则
    指在软件设计中,应该最小限度的暴露必要的内容,将其他内容隐藏起来。
  • 规避冲突
    1. 全局命名空间
      通过命名空间,将各自的属性都声明再统一的对象下,,而不是将自己暴露在顶级词法作用域下。
    2. 模块管理
      模块模式
  • IIFE(立即执行函数)
    (function(){})()

  • 块作用域
    在一个代码块内,变量只能在内部使用,不会对外部的块作用域进行污染。
    with, trh/catch都会创建一个块作用域
    es6的let 和 const 也会创建一个快作用域
    注: 当声明一个覆盖整个函数作用域的闭包时,js极有可能不会回收该函数,造成内存不必要的浪费和泄露,但是在块作用域下就能够与避免这样的情况。

闭包

  • 函数中的函数,由于函数的作用域链,外部函数无法访问函数中定义的函数内容,从而形成闭包

隐式和显示作用域

  • let声明会创建一个显示作用域并与其进行绑定,再块外部是无法访问let声明的变量的

this词法

  • es6中新增了箭头函数() => {} 使用箭头函数会放弃普通的this绑定规则,取而代之的使用当前词法作用域覆盖了this本来的值

关于this

  • 为什么要用this
    答: this提供了一种更优雅的方式来隐式’传递’一个对象引用,由此可以将API设计的更加简洁并且易于复用。随着使用的模式越来越多
    显式传递上下文对象会让代码越来越混乱,使用this就不会这样。
function foo(num) {
console.log('foo' + num);

// 记录foo 被调用的次数
foo.count++;
}
foo.count = 0;
var i = 0;
for (i = 0; i < 10; i++ ) {
if (i > 5) {
foo(i);
}
}
console.log(foo.count); //0
因为词法作用域的原因,foo函数中的this绑定到全局变量,导致count永远是0;
// 解决方法

1. 创建一个带count的对象
2. 使用foo.count 替代 this.count
3. 使用call函数使this强制绑定到foo上(荐)
  • this调用栈和调用位置
function baz() {
// 当前调用栈是:baz;
// 因此,当前调用位置是全局作用域
console.log('baz');
bar(); // bar的调用位置
}

function bar() {
// 当前调用栈是baz --> bar
// 因此,当前调用位置再baz中
console.log('bar');
foo(); // <-- foo的调用位置
}

function foo() {
// 当前调用栈是baz --> bar --> foo
// 因此,当前调用位置是在bar中
console.log('foo')
}
baz(); // <-- baz的调用位置

this绑定规则

  1. 默认规则

    • 再无法应用其他规则时的规则
      function foo() {
      console.log(this.a);
      }
      foo();
      // 这里this默认绑定到了全局变量上,因为foo是直接使用不带任何修饰的函数引用进行调用的,所以应用了this的默认绑定,因此this指向全局对象
      // 但是在严格模式下则不会绑定到全局全局对象,会直接绑定到undefined
  2. 隐式绑定

    function foo() {
    console.log(this.a);
    }
    var obj = {
    a: 2,
    foo: foo,
    };

    obj.foo();
    // 因为此时foo调用的函数上下文是obj,所以此时this就绑定到了obj上。调用位置会使用obj上下文来引用函数,因此你可以说函数被调用时obj对象'拥有'或者'包含'它
  3. 显式绑定(call apply bind)

Function.prototype.bind = function(newThis) {
var args = Array.prototype.slice.call(arguments, 1);
var that = this;
return function() {
return that.apply(newThis, args.concat(Array.prototype.slice.call(arguments, 1));o
}
}

开发经验汇总和一些问题的解决方法

发表于 2018-09-17 | 更新于 2019-01-24 | 分类于 开发经验 | 评论数: | 阅读次数:

js深拷贝浅拷贝

  • Object.create()为对象层面的深拷贝

  • Object.assign()当对象只有一层时为深拷贝,当有嵌套对象时为深拷贝

对象多个属性赋值

Vue.options.components = {}
Vue.options.directives = {};
Vue.options.filters = {};

// 相当于,且更方便维护
const ASSET_TYPES = ['component','directive','filter'];
ASSET_TYPES.forEach(type => {Vue.options[type + 's'] = Object.create(null)});

使用js+css实现粘性布局

// 获取滚动的总高度
getScrollTop() {
let scrollTop = 0;
let bodyScrollTop = 0;
let documentScrollTop = 0;
if (document.body) {
bodyScrollTop = document.body.scrollTop;
}
if (document.documentElement) {
documentScrollTop = document.documentElement.scrollTop;
}
scrollTop = (bodyScrollTop - documentScrollTop > 0) ? bodyScrollTop : documentScrollTop;
return scrollTop;
},
// 文档的总高度
getScrollHeight() {
let scrollHeight = 0;
let bodyScrollHeight = 0;
let documentScrollHeight = 0;
if (document.body) {
bodyScrollHeight = document.body.scrollHeight;
}
if (document.documentElement) {
documentScrollHeight = document.documentElement.scrollHeight;
}
scrollHeight = (bodyScrollHeight - documentScrollHeight > 0) ? bodyScrollHeight : documentScrollHeight;
return scrollHeight;
},
// 获取可见页面的总高度
getWindowHeight() {
let windowHeight = 0;
if (document.compatMode === 'CSS1Compat') {
windowHeight = document.documentElement.clientHeight;
} else {
windowHeight = document.body.clientHeight;
}
return windowHeight;
},
window.onscroll = function(){
if(getScrollTop() + getWindowHeight() == getScrollHeight()){
alert("已经到最底部了!!");
}
};

flex自动充满的用处

display: flex;

// 子容器中
height: auto;

html 拖拽代码

let draging = false;
let isdrop = false;

function getDOMs(el) {
return document.querySelectorAll(el);
}

function setData(e, data) {
const setDate = JSON.stringify(data);
if (e.dataTransfer.setData) {
e.dataTransfer.setData('dropData', setDate)
}else {
sessionStorage.setItem('dropData', setDate);
}
}

function getData(e) {
if (e.dataTransfer.getData) {
return JSON.parse(e.dataTransfer.getData('dropData'));
}else {
return JSON.parse(sessionStorage.getItem('dropData'));
}
}

function bindDrag(dom,dragStart,dragEnd) {
let offsetX;
let offsetY;
dom.ondragstart=function(e){
if (draging) return;
draging = true;
dom.style.opacity = 0;
if (dragStart) {
dragStart();
}
setData(e, {
componentName: e.srcElement.dataset.componentname,
groupName: e.srcElement.dataset.group,
type: 'component',
})
}
dom.ondrag=function(e){
let x= e.pageX;
let y= e.pageY;
//drag事件最后一刻,无法读取鼠标的坐标,pageX和pageY都变为0
if(x === 0 && y === 0){
return; //不处理拖动最后一刻X和Y都为0的情形
}
x-=offsetX;
y-=offsetY;
}
dom.ondragend=function(e){
draging = false;
// if (isdrop) {
// isdrop =false;
// }else {
// dom.style.opacity = 1;
//};
dom.style.opacity = 1;
if (dragEnd) {
dragEnd();
};
}
}


function dragenter(e) {
e.stopPropagation();
e.preventDefault()
};
function dragover(e) {
e.stopPropagation();
e.preventDefault();
};
function drop(e, dropCB) {
e.stopPropagation();
e.preventDefault();
console.log(getData(e))
if (dropCB) {
// 调用增加组件方法
return dropCB(getData(e));
}
return false;
}

function getDOM(el) {
return document.querySelector(el);
}

const DragUtil = {
drag (el,dragStart,dragEnd) {
const doms = getDOMs(el);
doms.forEach( item => {
bindDrag(item,dragStart,dragEnd);
})

},
addDropListen(el,dropCB) {
let dom = getDOM(el);
dom.ondragenter = function(e){
dragenter(e);
};
dom.ondragover = function(e) {
dragover(e);
};
dom.ondrop = function(e) {
const returnFlag = drop(e,dropCB);
isdrop = true;
};
},
};

export default DragUtil;
// 因为业务的原因,也增加了一些多余的逻辑,当拖拽的元素使用opacity:0时,如果不加动画效果延迟,拿拖拽就为空,这里需要注意下

vue子组件修改props的问题

  • 再使用iview的抽屉时,因为将抽屉做成了一个组件,所以使用props去控制抽屉的打开与关闭,但是因为右上角自带的关闭按钮导致子组件
    会自动修改props中的值,触发报错。

  • 一开始想用computed去吧props的值做一个copy,但是由于vue的新版本导致computed的属性必须要set,所以做如下修改

computed: {
showDrawerTemp: {
get() {
return this.showDrawer;
},
set() {
},
},
},

关于github提交没有提交记录的问题

  • 经常发现是用另外一个电脑去提交代码的时候,git没有算到我的提交记录里面,经过查证发现,是因为邮箱地址的错误,导致提交时不算是我的
    将邮箱地址修改即可

  • Git总结

1

2

3

git上ssh的问题

  • 部署vuepress文档的时候,出现无法访问的问题,是git的sshkey除了错误,解决方法https://blog.csdn.net/qq_34291777/article/details/55052201?locationNum=1&fps=1
  • mac上打开.ssh文件的方法 open ~/.ssh

git修改最近一次的commit信息

git commit --amend

better-scroll 滚动

vuepress中重复提交导致docs目录覆盖dist目录的问题

重复提交之前,需要使用git init来将仓库清空,重新去上传dist文件夹

使用vue-meta-info和预渲染解决单页面应用seo问题

  • https://zhuanlan.zhihu.com/p/29148760?group_id=890298677627879424

  • 预渲染的使用 https://blog.csdn.net/yftk765768540/article/details/81047145

vue路由重定向

if (to.path !== '/login' && !Util.getDataFormSessionStorage('USERINFO', true, '') && !Util.getDataFromLocalStorage('USERINFO', true)) {
router.push({ path: '/login' });
next({
path: '/login',
// query: {redirect: to.fullPath} // 将跳转的路由path作为参数,登录成功后跳转到该路由
});
} else {
next();
}

flex无限放大的问题

  • 主要是因为当前dom宽度超过界面宽度,所以当界面拖动的时候,display:webkit-box和display:flex会导致元素无限变成,解决方法就是将元素的宽度限制死,不要超过界面宽度

移动端开发的常见问题和解决方案

  • https://blog.csdn.net/diqi77/article/details/54692920

  • 使用vm vh进行页面的兼容性处理

//640px作为设计稿基准
$vm_base: 640;
@function vm($px) {
@return ($px / 640) * 100vw;
}

//通过代码,假如设计稿中元素的宽度是 40px ,那么就可以在样式中写
.test{
width:vm(40)
}

less中使用calc函数

.echarts {
height: calc(~"100vh - 222px");;
}

纯css的波浪条纹实现

.ivu-progress-bg {
background: repeating-linear-gradient(-60deg,#166aee 10px,#72a8f5 0%,#72a8f5 20px,#166aee 0%,#166aee 30px, #72a8f5 0%);
background-size: 100% 13px;
}
注意其中background-size的把控

css修改浏览器输入框提示字的样式

  /* WebKit browsers */
input::-webkit-input-placeholder {
color: red;
} 
/* Mozilla Firefox 4 to 18 */
input:-moz-placeholder {
color: #666;
}
/* Mozilla Firefox 19+ */
input::-moz-placeholder {
color: #666;
} 
/* Internet Explorer 10+ */
input:-ms-input-placeholder {
color: #666;
}


### icon-font symbol引用无法修改颜色的问题

* http://www.cnblogs.com/jopny/p/9454785.html

### vue获取当前路由下的组件

```javascript
this.$route.matched[2].components
  • 对当前路由视图直接使用ref,则可以直接指向当前活动的component

关于async await的一些问题

  • await关键字必须在async关键字下使用。。。否则后果很严重

移动端的vw适配方案

  • 设计搞切成375版本,直接使用vw作为单位

  • 字体显示多少pt就用多少px,不需要转换

  • 除了特殊情况,一般都是用vw作为显示单位,如果要支持pad横屏显示,就要用vmin(因为宽度总是小于高度)

vue图片动态加载解决方案

img: require('../../assets/guessLike.png'),

vue预渲染示例

https://github.com/chrisvfritz/prerender-spa-plugin/tree/e2c49428e0efab5a672f421a3a33da45fc345710/examples/vue2-webpack-router

css transform同时实现多个属性

transform: rotate(360deg) scale(2,2) skew(10deg,5deg); //效果中间用空格隔开即可

vue 路由history模式,tomcat配置

tomcat 目录下免得conf文件夹里面的web.xml文件加上下面的配置

<display-name>webapp</display-name>
<description>
webapp
</description>
<error-page>
<error-code>404</error-code>
<location>/</location>
</error-page>

js判断对象中是否存在属性

对于一般的对象属性需要用字符串指定属性的名称   如:
let mycar = {make: "Honda", model: "Accord", year: 1998};
"make" in mycar // returns true
"model" in mycar // returns true

git patch

git format-patch相对于git diff更便于操作,是更新的打包方式,应该采取这种打包方式。git diff打包的patch只能使用git apply处理。而git format-patch的补丁,可以应当使用git am命令。

基本用法

git format-patch xxxx.patch

https://www.cnblogs.com/zzb-Dream-90Time/p/7693860.html

display: flex justify-content实现间隔布局

  • http://www.ruanyifeng.com/blog/2015/07/flex-grammar.html
justify-content: space-between; 实现元素间隔布局

右上角三角形

.select-dup-com-icon {
position: absolute;
right: 2px;
top: 0px;
.select-icon {
height: 12px;
width: 12px;
z-index: 1;
position: relative;
color: white!important;
display: none;
}
&:after {
content: ' ';
position: absolute;
top: -18px;
right: -20px;
border-left: 18px solid transparent;
border-top: 18px solid transparent;
border-right: 18px solid transparent;
border-bottom: 18px solid transparent;
transform: rotate(-45deg);
}
}

webpack项目依赖再多个文件中的引入方式

// 错误方式

a.Vue
import xxx from '../../../xx';

b.Vue
import xxx from '../../../xx';

//正确方式
webpack.config.js
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}

a.Vue
import xxx from '@/xx';

b.Vue
import xxx from '@/xx';

使用别名,减少代码耦合,这样多出修改的时候,就不用那么麻烦了

wx小程序RPX解析

rpx(responsive pixel): 可以根据屏幕宽度进行自适应。规定屏幕宽为750rpx。如在 iPhone6 上,屏幕宽度为375px,共有750个物理像素,则750rpx = 375px = 750物理像素,1rpx = 0.5px = 1物理像素。 
rpx 为小程序中使用的相对单位,用法和rem类似, 1rpx = 屏幕宽度/750 px, 所以在屏幕宽度为750的设计稿中,1rpx = 1px。

mpvue 采坑记录

https://www.cnblogs.com/zhouyangla/p/9000879.html
https://github.com/Meituan-Dianping/mpvue/issues/21 // mpvue项目征集
https://www.cnblogs.com/xuyan1/p/9549490.html // mpvue使用iview
http://www.php.cn/xiaochengxu-407509.html // mpvue使用iview

css 渐变 linear-gradient

background: linear-gradient(to bottom,#1986ef 0%, #1986ef 60%, #1fb3e8);

表示从上到下0% —— 70% 是#1986ef ,剩下的用#1fb3e8渐变

Vue与Angular特性对比

发表于 2018-07-29 | 更新于 2018-08-21 | 分类于 经验总结 | 评论数: | 阅读次数:

学习曲线

vue.js的学习和理解相对简单,而Angular则需要时间去习惯和适应,这两个框架本身都很棒。相对Angular,Vue对扩展的支持更加简单,而Angular则保持规范的开发流程,为项目后期的维护考虑。

语法方面,Vue和Angular的语法很类似,比如API和设计,因为Vue是实际上是从早期Angular的开发阶段中获得启发。

开发语言

Vue: es6+
Angular: TypeScript

相对于JS,TS增加了静态类型、类、模块、接口和类型注解,适合于大型项目的开发,并且在多人协作中,可以有效的保证类型安全,为团队创建一个高效的编码和调试过程。
而且对于具有一定js基础的开发人员上手相对容易。

灵活性

Vue相对Angular会灵活一些,适合在中小型项目进行快速迭代开发,但是在大型项目中,尤其是多人合作时,这种灵活会导致多种代码风格,对后期的维护造成很大的阻碍和困难。

性能

从Vue官方文档上关于两个框架性能的对比报告图
,对比Angular在去年8月分布的rc版本和同期的Vue beta版本的不同操作性能,可以看出两个框架都很快,Angular
和Vue正在大多操作上性能指标都处于同一个数量级,但是Vue在部分指标上略胜一筹。

开发团队

Angualr是由谷歌团队进行开发和维护,Vue则是尤雨溪的个人开源项目。并且Angular拥有相对更加繁荣的社区,在这一点上
,Angualr要略强于Vue。

数据绑定方面

Angular2支持绑定到任何普通的JavaScript兑现对象,并且不会对对象造成任何改变,通过zone.js实现任意位置的异步操作
后的数据自动同步。而Vue对于一些复杂对象的复杂操作,需要手动调用setter来通知Vue进行更新,操作上更为复杂

angular学习

发表于 2018-07-12 | 更新于 2018-08-06 | 分类于 angular | 评论数: | 阅读次数:

根据官方命名规则 angualr 指 angular4.0 an gularJS 指 angular1

程序架构

  • 组件
  • 是 Angular 应用的基本构建块,你可以吧一个组件理解为一段带有业务逻辑和数据的 Html
  • 模块
  • 模块是用来将应用中不同的部分组织成一个 Angular 框架可以理解的单元
  • 指令
  • 允许你向 Html 元素添加自定义行为
  • 服务
    阅读全文 »

TypeScript介绍

发表于 2018-07-12 | 更新于 2018-08-08 | 分类于 typescript | 评论数: | 阅读次数:
  • 为什么要学习TS
    • 支持ES6规范
    • 强大的IDE支持(语法提示,强制类型要求)
    • 是NG框架的开发语言

      是js的超级,有谷歌和微软支持,后台强大。可能成为js后续发展的一个方向

需要compoiler将TS转为JS语法,防止浏览器的不兼容

TS的新特性

阅读全文 »

代码编写规范小结

发表于 2018-06-12 | 分类于 经验 | 评论数: | 阅读次数:

1.尽量减少代码的复杂程度,方便别人阅读和维护,如果无法避免的话请打上注释。
2.代码逻辑上加上注释,方便别人阅读。
3.声明类属性的时候只有public的属性不需要声明前缀,其余类型的都需要声明前缀。
4.碰见重复的代码需要封装起来,重复代码和增加代码的冗余。
5.常量和一些全局变量请提取出来声明在最前面或者使用字典目录。
6.变量声明和函数声明,类型、返回值等都需要,规范、统一
7,无用的变量需需要及时删除。

深入浅出node.js

发表于 2018-05-26 | 更新于 2018-05-30 | 分类于 读后感 | 评论数: | 阅读次数:

封面

第一章(简介)

node.js特点

阅读全文 »

js异步编程

发表于 2018-05-24 | 更新于 2018-06-25 | 分类于 node.js | 评论数: | 阅读次数:

js异步编程

使用 js 编程,回调再常见不过。因为单线程,所以要异步,因为异步,所以要有回调。随着逻辑的越来越复杂,回调也越来越多,
尤其是在 node.js 中,经常会发生回调层层去嵌套的情况。

阅读全文 »

问诊代码阅读小记

发表于 2018-05-23 | 更新于 2018-05-28 | 分类于 开发经验 | 评论数: | 阅读次数:

问诊代码阅读小记

写在前面
阅读全文 »

nodejs设计模式学习小笔记小记

发表于 2018-05-18 | 更新于 2018-05-27 | 分类于 nodejs | 评论数: | 阅读次数:

封面

一些总结

第一章: 欢迎来到node.js平台(对nodejs的一些简单的介绍)

阅读全文 »
12…5
  • ajax知识点整理1
  • angular学习记录1
  • css和js部分的优化相关1
  • css相关1
  • html相关强化1
  • js设计模式小计1
  • nodejs1
  • nuxt学习笔记1
  • service worker实战1
  • typescript相关学习1
  • vuepress学习小计2
  • 一本需要反复阅读的js书籍1
  • 代码编写规范总结1
  • 代码编写过程中的沉淀1
  • 前端知识点沉淀1
  • 图片相关1
  • 总的来说,这本书有点脱节了,内容有些老旧1
  • 服务端性能优化1
  • 浏览器中各种距离的计算1
  • 浏览器存储和缓存1
  • 深入浅出node.js一书读后感1
  • 看vue.js一书所得1
  • 缓存相关1
  • 重绘与回流相关1
  • 面试记录1
  • 高性能javascript一书阅读笔记1

朱亮

Leon Zhu’s blog | 爱前端 | 爱生活

43 日志
17 分类
26 标签
GitHub E-Mail 掘金
© 2019 朱亮
用户总数 | 访问总数