学习心得
从今天开始,把每天的学习的一些知识小结一下~
2022-8-3
rem 和 vw 的优势与劣势,以及发展历史。
rem 优势:可以应用于移动端页面在 pc 端展示,定义 pc 端的 font-size,不会使得页面内容过大。1px 不需要额外的实现。 vw:rem 的升级版,使用更简单方便,不需要关心 viewport。1px 可以使用 transform 来实现。
如果老项目使用 rem 想迁移到 vw 到话,可以只修改 html 的 font-size,根据 media query,将 px 转换成对应的 vw 即可。
2022-7-12
flex vs grid: 一维和二维的区别,flex 专注于每一行或者每一列内容的排列顺序,但是 grid 可以创建二维布局,并且可以精确的精确的放到单元格内。 列子:首字母和内容的两列布局,每个首字母都有可能存在 2 个及以上的内容,那么在第 2 个内容开始,左边就没有首字母填充,这个时候使用 grid 就方便很多。 内容至上 vs 布局至上,flex 的内容会自动伸缩,grid 的内容不会。
何时使用 grid:
- 有一个比较复杂的设计,并且可维护性高
- 在块状元素上添加间隙
何时使用 flex:
- 设计比较简单,并且行列数量不多
- 需要对其元素
- 需要内容自适应
在使用 git 多用户的时候,要注意切换本地的 git config 用户信息和 hostname 的 user。 本地的 git config 会在每次 commit 中的用户信息里展示,hostname 则是表示本次 commit 是 github 中哪个账号提交的。
2022-6-17
vue3 虽然用 proxy 监听数组了,但是还是劫持了部分数组的方法。
因为 proxy 监听数组的时候,也会追踪数组的 length 属性,然后在某些例子中会导致无限循环。
例子:
const arr = reactive([]);
watchEffect(() => {
arr.push(1);
});
watchEffect(() => {
arr.push(2);
});
源码:
function createArrayInstrumentations() {
const instrumentations: Record<string, Function> = {}
// instrument identity-sensitive Array methods to account for possible reactive
// values
;(['includes', 'indexOf', 'lastIndexOf'] as const).forEach(key => {
instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
const arr = toRaw(this) as any
for (let i = 0, l = this.length; i < l; i++) {
track(arr, TrackOpTypes.GET, i + '')
}
// we run the method using the original args first (which may be reactive)
const res = arr[key](...args)
if (res === -1 || res === false) {
// if that didn't work, run it again using raw values.
return arr[key](...args.map(toRaw))
} else {
return res
}
}
})
// instrument length-altering mutation methods to avoid length being tracked
// which leads to infinite loops in some cases (#2137)
;(['push', 'pop', 'shift', 'unshift', 'splice'] as const).forEach(key => {
instrumentations[key] = function (this: unknown[], ...args: unknown[]) {
pauseTracking()
const res = (toRaw(this) as any)[key].apply(this, args)
resetTracking()
return res
}
})
return instrumentations
}
function createGetter(isReadonly = false, shallow = false) {
return function get(target: Target, key: string | symbol, receiver: object) {
...
const targetIsArray = isArray(target)
if (!isReadonly && targetIsArray && hasOwn(arrayInstrumentations, key)) {
return Reflect.get(arrayInstrumentations, key, receiver)
}
...
return res
}
}
在 vue3-tsx 中,就算 computed 后计算出来的值没有变,但是只要依赖变了,就会触发 component 的 render。
如果 computed 后计算的值没有在 render 中被使用,那么就算依赖变了导致计算出来的值也变了,computed 函数也不会执行了,只执行 2 次。
vue-router 中,router.push 内部会先调用 router.replace(),再调用 router.push()
不能在 setup 中的 defineProps 中使用 import 的 type 和 interface。
ts 中,??和?.只要验证的是 null 和 undefined 值,而&&和||验证的是 falsy 值(‘‘、”“、0、NaN、null、undefined、false)。 非空断言!在部分业务场景中还是很适用的。var!可以直接排除 null 和 undefined 的情况
访问对象值的时候尽量使用解构赋值,好处有以下几点:
- 可以自定义新的变量名
- 提高可读性,便于维护
- 可以设置默认值
- 减少了访问数据属性所采取的步骤数
- 有助于减少应用程序中使用的代码量。
- 节省了多次迭代对象数组的时间。
位运算:
- 判断奇偶的时候使用 i & 1 === 0 来代替 i % 2=== 0
vue3 中编译模版的时候,会遍历所有的 node 节点,并打上静态提升标记 push 到 transformContext.hoists 里,在生成代码字符串的时候,会遍历 hoists,并在 code 里拼接上const _hoisted_${i + 1} =...
2022-5-26
If you use CSS Flexbox Layout to implement a page component with horizontal scrolling, be aware that browsers ignore the end-side padding (in this case, padding-right) of the flex container.
You can emulate the missing padding by spacing the flex items via margin-right and adding a very narrow ::after flex item to the container.
.container {
display: flex;
overflow-x: scroll;
padding: 1em; /* browsers ignore the padding-right component */
}
.container::after {
content: '';
padding-right: 0.02px; /* smallest size that is cross browser */
}
使用 ionicon 来引入自定义 svg 的时候,注意引入的地址,如果是本地地址,customElement 默认是不会编译地址的。
2020-6-19
- react-router-dom 中的 redirect 不会自动把 query 带上,如果自己不添加到 search 里,则会丢失 query。
- react 中设置 stoppropagation 失效是因为 react 会把所有的事件绑定到 document 上,并且返回一个合成事件,每次你在合成事件中 stoppropagation 只能阻止外层合成事件的触发,但是不会阻止 document 上的原生事件。在 react17 中会把所有的事件绑定到 root 上,这样使得在不同的 react 版本的项目中,不会因为版本不同的存在而使得项目事件混乱。
2020-4-20
.q {
display: flex;
--px: 0;
}
.q > div {
width: 300px;
height: 100px;
// --px: 0; 如果在这里设定默认的--px,那么修改q上的style Attribute会被默认的覆盖。
}
.a {
background: pink;
}
.b {
background: blue;
}
.c {
background: red;
transform: translateY(calc(130px * var(--px)));
}
$('.q').style.setProperty('--px', '100px');
同时可以通过 style.setProperty 来修改 css 变量,不过父元素 style Attribute 会被子节点默认的 css 变量覆盖。
2019-9-4
清空 git 当前分支的历史缓存
尝试 运行 git checkout --orphan latest_branch
添加所有文件git add -A
提交更改git commit -am "commit message"
删除分支git branch -D master
将当前分支重命名git branch -m master
最后,强制更新存储库。git push -f origin master
如果git push -f 被拒绝了,则需要修改服务器端的receive.denyNonFastForwards字段为false。
2019-4-1
console.log(1)(function () {})();
为什么上面这段代码会报错呢?因为 js 会把(function…)当作是函数 console.log(1)的参数来执行,所以就会报错。
foo()
bar()
var foo = function bar () {}
注意上述代码中的bar函数不会提升,而且全局变量中也不能获取到bar函数。
实际上编译成下面:
var foo;
foo() // TypeError,foo不是函数
bar() // ReferenceError,声明不存在
foo = function () {
var bar = self
...
}
function foo() {
console.log(a); //2
}
function bar() {
var a = 3;
console.log(a); //3
foo();
}
var a = 2;
bar();
因为 js 中的作用域是词性作用域,词法作用域是在写代码或者说定义时确定的,词法作用域关注函数在何处声明。但是 this 机制类似动态作用域,动态作用域是在运行时确定的,动态作用域关注函数从何处调用。
2019-2-14
禁止浏览器回退:
window.addEventListener(
'popstate',
function (e) {
pushHistory();
},
false
);
function pushHistory() {
var state = {
title: '',
url: window.location.pathname, // 填入当前的url path
};
window.history.pushState(state, state.title, state.url);
}
// 这两行代码也是需要的,如果打开页面后并没有pushState过,则还是可以点击返回按钮的,因为此时没有往history中pushState过,所以监听不到popstate。
pushHistory();
window.history.go(-1);
用 Vue 发开微信公众号网页中,调用微信的 jssdk 的时候,每次跳转页面就发现安卓的签名过期,查找了一下发现原因是这样的:安卓和 ios 的微信对于 H5 新增的的路由跳转方式解析不同。
在微信的文档中有一句话:同一个 url 仅需调用一次,对于变化 url 的 SPA 的 web app 可在每次 url 变化时进行调用,目前 Android 微信客户端不支持 pushState 的 H5 新特性,所以使用 pushState 来实现 web app 的页面会导致签名失败,此问题会在 Android6.2 中修复。
之前我只在初始化的时候获取签名,这个时候安卓就发现签名过期。然后看到文档这句话后我就每次路由跳转都重新获取签名,这个时候就是 IOS 发现签名过期了。
原因就是在 IOS 的微信上,无论页面如果跳转,他认准的签名 URL 是你第一次进入这个网页时的 URL,所以在 IOS 上你跳转页面的时候就不应该重新获取签名。
既然知道了原因,那解决方式也很简单,只要先判断是安卓还是 IOS,是安卓就自动获取签名,是 IOS 就判断是否已经有了签名,有则不重新获取,没有则获取。
import { getsignature } from './Api/api.js';
let exist = false;
export const getSignature = {
created: function () {
const u = navigator.userAgent;
const isiOS = !!u.match(/\(i[^;]+;( U;)? CPU.+Mac OS X/);
if (isiOS && exist) return;
getsignature(encodeURIComponent(location.href.split('#')[0]))
.then((res) => {
// eslint-disable-next-line no-undef
wx.config({
debug: false,
appId: res.data.appid,
timestamp: res.data.timestamp,
nonceStr: res.data.noncestr,
signature: res.data.signature,
jsApiList: [
'updateAppMessageShareData',
'updateTimelineShareData',
'onMenuShareAppMessage',
'onMenuShareTimeline',
'chooseWXPay',
'editAddress',
],
});
// eslint-disable-next-line no-undef
wx.error(function (res) {
alert(res.errMsg);
});
if (isiOS && !exist) exist = true;
})
.catch((err) => {
alert(err);
});
},
};
// 在你需要使用jssdk的页面导入即可
import { getSignature } from '../utils';
export default {
mixins: [getSignature],
};
在目前最新的 jssdk 版本 1.4.0 中,updateAppMessageShareData 和 updateTimelineShareData 暂时无法使用,报错 fail,原因未知。
2019-1-3
新年新气象,在使用 react-native 的使用要用到 echarts,然后发现 react-native-echarts 已经好久没有更新迭代了,而且有很多的 issue 的问题也没有修复,看了他的源码,发现它也就是引入 echarts,然后包在 webview 中展示,那么其实我们完全可以自己来做引入,还能使用 v4 的 echarts。
在稳固 echarts 的 api 的时候,不知道为什么就想看下它的源码。可能是最近经常看源码,导致看啥轮子都想看看源码的实现。
2018-12-20
在什么时候要使用height: 100%
呢?
要解决这个问题关键是理解 height 这个属性。
如果我们不设置 height 的话,它就会遍历子元素,然后获取子元素的高度设置成自己的 height。也就是说填充自己。
如果你设置了 height 为 100%,他就会继承父元素的高度。但是这个时候如果父元素的高度没有设置的话,它遍会寻找父元素的父元素的高度,直至找到位置。html 默认为 100%。body 元素比较特殊,如果 html 的 height 为 80%,那么不设置 body 的高度的话,它的 height 还是 100%。如果 html 的高度大于 100%,body 的高度则和 html 相同。但是 div 未设置 height 的高度则始终和父元素的高度相同。
2018-12-11
以前写过 bind 的原生实现,但是时间久了还是有些细节遗忘了,今天还是记录一下。
es6: if (typeof Function.prototype.bind1 !== 'function') {
Function.prototype.bind1 = function (context, ...rest) {
if (typeof this !== 'function') {
throw new TypeError(
'Function.prototype.bind - what is trying to be bound is not callable'
);
}
var self = this;
return function F(...args) {
if (this instanceof F) {
return new self(...rest, ...args);
}
return self.apply(context, rest.concat(args));
};
};
}
es5: Function.prototype.bind2 = function (context) {
if (typeof this !== 'function') {
throw new Error(
'Function.prototype.bind - what is trying to be bound is not callable'
);
}
var self = this;
var args = Array.prototype.slice.call(arguments, 1);
var fNOP = function () {};
var fBound = function () {
var bindArgs = Array.prototype.slice.call(arguments);
// 使new出来的函数的this指向实例,而不是bind后的context
return self.apply(
this instanceof fNOP ? this : context,
args.concat(bindArgs)
);
};
// 避免修改fBound原型的时候也同时修改了原函数的原型对象
fNOP.prototype = self.prototype;
fBound.prototype = new fNOP();
return fBound;
};
高颜值的 curry 实现方式:
var curry = (fn) =>
(judge = (...args) =>
args.length === fn.length ? fn(...args) : (arg) => judge(...args, arg));
2018-10-31
mac 下好用的工具:
- brew install wget 下载、扒站神器
- brew install ack 搜索代码神器
- brew install autojump 终端下多目录跳转神器
正则的部分理解:
- (?:exp)的作用是什么?
^([1-9][0-9]*|0)$
和^[1-9][0-9]*|0$
的区别
2018-8-30
Object.create(null) 和 {} 的区别是:Object.create(null)创造出来的对象是没有继承任何原型的,他没有 toString,hasOwnProperty 等等方法。
理解,递归的应用
(fn =>
(f => f(f))(f => fn(n => f(f)(n)))
)(g =>
n => [1, 2].indexOf(n)> -1 ? 1 : g(n - 1) + g(n - 2)
)(10);
2018-7-30
- 在 mac 中使用 nvm 的时候,如果直接
yarn global add <package>
,我发现它不会帮我们安装到 nvm 所对应的 version 下,而是安装在了.config 下的 yarn 中。但是 npm 安装全局包是可以的。
写一个方法过滤数组中的空字符串:
const filterEmptyString = function (arr, result) {
arr.forEach((e) => {
if (Object.prototype.toString.call(e) === '[object Array]') {
result.push([]);
filterEmptyString(e, result[result.length - 1]);
if (!result[result.length - 1].length) result.splice(r.length - 1, 1);
} else {
if (e !== '') result.push(e);
}
});
return result;
};
2018-7-25
- 在 vscode 中使用 nvm 会出现一点问题,就算你通过
nvm alias default <version>
设置了默认都 node 版本,但是每次在 vscode 中打开终端发现 node 版本还是等于 system,但是通过系统内置终端或者 iterm2 都是正常的。查找了网上都资料发现别人也有这个问题,如果要解决可以在 bash_profile 都结尾处添加nvm use <versioin>
。 - 发现 vue/cli 3.0 构建的项目在热更新中有点问题。pc 端是没有问题的,但是在移动端打开项目后,每次修改触发热更新后,界面是会变化,但是如果你刷新页面后,页面又回到了起始项目运行的界面,即界面收到 HMR 的 hash 是最初的 hash,并不是最新的 hash,不知道具体是什么问题,我构建的 vue-cli 2.0 是没有该问题的。(发现在 safari 下才有问题,chrome 中是没有问题的。)
- 吐槽最近的 github 总是抽筋!!!
- 在使用 HMR 的时候,我在 webpack 引入 babel 后,发现 module.hot.accept 只能接收到一次数据。
- 搭建简易的 vue 感觉还是蛮简单的,原理也不是很难。比较困难的感觉是后面生态的建设,组件等等,因为这些会导致原来的思考方式在目前看来是行不通的。以及部分代码的实现等等,最近要好好想想怎么更好的制作一个简易的 Vue。
- 在使用 vue 的 keep-alive 的时候,如果使用在字符串中分隔逗号的话,要注意逗号后面的空格,它会将这个空格也算到 name 中。所以在写的时候要删除逗号之后的空格。
- 在异步导入组件的时候,是不能在 import 中使用变量以及模版字符串的,可能是为了安全因素考虑。
2018-7-9
新公司 emm 蛮不错的,最近写了一些小插件,感觉写插件真好玩!!
- IE 浏览器中 css3 动画(height)不流畅卡顿,原因是动画所选中的元素设置了 position 为 relative,导致动画卡顿。在 chrome 下无卡顿。
- requireJs 中 shim 主要是针对对非 AMD 规范的导入方式的优化,如果不使用 shim,则那些文件在 define 引用后无法使用,但是使用了 shim,则 require 会自动帮我们返回全局变量中的模块信息。
- requireJs 的学习可以直接看文档,写的还是比较详细的。
- vue-cli 3.0 的学习,看了一下项目构建,发现和 react 的 create-react-app 好像,基本都把配置内置了,如果要修改可以自己写一个 vue.config.js 文件,会覆盖默认配置。
- 看了一下 vue-cli-service 的源码,还有部分没理解透,等理解透了再写篇文章整理一下。
2018-5-24
最近学习了微信小程序,阅读深入理解计算机系统这本书,不得不说,我看的真的快睡着了。即将离开第一家公司,心里也很不是滋味。最近这段时间都感觉迷茫了。加油加油吧!
2018-5-7
使用 toString()可以将函数转化成 string 打印出来,但是如果你重新 bind 了函数的指向,再打印,会出现function () { [native code] }
关于移动端输入框挡住 input 的解决方法:
window.addEventListener('resize', function () {
if (
document.activeElement.tagName === 'INPUT' ||
document.activeElement.tagName === 'TEXTAREA'
) {
window.setTimeout(function () {
if ('scrollIntoView' in document.activeElement) {
document.activeElement.scrollIntoView();
} else {
document.activeElement.scrollIntoViewIfNeeded();
}
}, 0);
}
});
AE(Adobe After Effects)中有个插件(Bodymovin),他可以将在 AE 中的动画导出成 json 文件,然后在网页中引入bodymovin.js
就可以播放这段动画。
2018-4-24
对于行内不可替换元素,设置上下外边距无效,左右有效,同理内边距。
这是因为对于行内不可替换元素来说,上下边距不会改变 line-height,而边距又是透明的,所以没有任何视觉效果,但是查看盒子模型还是可以看到上下边距存在。
对于行内可替换元素来说,上下边距和左右边距都有效。
instanceof 的原理:能否在实例的原型链中找到该该实例的构造函数的原型对象(即 prototype 指向),能找到就返回 true。
如何优雅的将'20180408000000'字符串转成'2018-04-08 00:00:00'
let formatStr = function (str, type) {
let i = 0,
_type = type || "xxxx-xx-xx xx:xx:xx"
return _type.replace(/x/g, () => str[i++])
}
手写原生 ajax 请求
function createXHR() {
if (window.XMLHttpRequest) {
return window.XMLHttpRequest()
} else {
return new ActiveXObject('Microsoft.XMLHttp')
}
}
var xhr = createXHR()
xhr.onReadyStateChange = function () {
if (xhr.readyState === 4) {
if ((xhr.state >= 200 && xhr.state <= 300) || xhr.state === 304) {
console.log(xhr.responseText)
} else {
.....
}
}
}
2018-4-16
- 关于队列任务的执行顺序:process.Trick() > Promise 的回调 > setTimeout > setImmediate
- 前端模块化解决的问题:命名冲突,繁琐的文件依赖,复用性差,可维护性差。
关于 AMD/CMD/CommonJs 的区别:
- AMD/CMD/CommonJs 是 JS 模块化开发的标准,目前对应的实现是 RequireJs/SeaJs/nodeJs。
- CommonJs 主要针对服务端(因为客户端没有 export,require,global 等字段),AMD/CMD 主要针对浏览器端。
- AMD/CMD 区别,虽然都是并行加载 js 文件,但还是有所区别,AMD 是预加载,在并行加载 js 文件同时,还会解析执行该模块(因为还需要执行,所以在加载某个模块前,这个模块的依赖模块需要先加载完成);而 CMD 是懒加载,虽然会一开始就并行加载 js 文件,但是不会执行,而是在需要的时候才执行。
- AMD 优点:加载快速,尤其遇到多个大文件,因为并行解析,所以同一时间可以解析多个文件。
- AMD 缺点:并行加载,异步处理,加载顺序不一定,可能会造成一些困扰,甚至为程序埋下大坑。
- CMD 优点:因为只有在使用的时候才会解析执行 js 文件,因此,每个 JS 文件的执行顺序在代码中是有体现的,是可控的。
- CMD 缺点:执行等待时间会叠加。因为每个文件执行时是同步执行(串行执行),因此时间是所有文件解析执行时间之和,尤其在文件较多较大时,这种缺点尤为明显。
2018-3-27
可以使用caret-color
来修改 input 中光标的颜色。
腾讯面试问题:
- http 的状态码,什么情况下会返回 304?cache-control 和 etag,last-modified 的区别?
- 描述一下 css 盒模型
- 实现垂直水平居中有哪些方法
- 跨域有什么处理方法?JSONP 的原理是什么?JSONP 可以用 post 请求吗?为什么?
- cookie 和 localstorage 有什么区别?
- vue 数据双向绑定的原理
- react 的生命周期有哪些?什么时候会用到 componentwillreceiveprops?
初始化 constructor static getDerivedStateFromProps() UNSAFE_componentWillMount() render componentDidMount 更新过程 UNSAFE_componentWillReceiveProps() static getDerivedStateFromProps() shouldComponentUpdate() UNSAFE_componentWillUpdate() render getSnapshotBeforeUpdate() componentDidUpdate 卸载过程 componentWillUnmount
- let 和 var 的区别
- 使用过构建工具吗?webpack 的 loader 是干什么的?
2018-3-19
前几天看到 js 位运算,发现有好多可以巧用这个技巧。
-
按位非 ~-1 === 0
-
异或来交换数字
let a = 1,
b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
a; // 2
b; // 1
关于for..in
,Object.keys()
,Object.hasOwnPropertyNames(obj)
,obj.hasOwnProperty(prop)
的区别:
- for…in 会遍历所有可枚举属性,对象从其构造函数原型中继承的属性。
- Object.keys()会遍历所有可枚举属性,但是不访问其构造函数原型中继承的属性。
- Object.hasOwnPropertyNames(obj)方法返回一个由指定对象的所有自身属性的属性名(包括不可枚举属性但不包括 Symbol 值作为名称的属性)组成的数组,但是不会返回其构造函数原型中继承的属性。
- obj.hasOwnProperty(prop)可以用来检测一个对象是否含有特定的自身属性;和 in 运算符不同,该方法会忽略掉那些从原型链上继承到的属性。
- for…in 和 obj.hasOwnProperty(prop)搭配筛选后的结果和 Object.keys()相同。
- Object.hasOwnPropertyNames(obj)返回的只比 Object.keys()多指定对象的不可枚举属性。
x = (1, 2, 3)
表达式为 Comma operator。
Comma operator:他表示依次执行括号中的每个表达式,然后返回最后那个结果(返回的是结果,是指,不是 reference)。
如果返回的那个结果是 console.log(this),那么这个 this 不是执行那个方法,而是 undefined。
例子如下:
'use strict'
const fn = function () {
default () {
console.log(this)
}
}
(fn[default])() // fn
(0, fn[default])() // this
只有在fn.a()、fn[a]()这样才会被认为是在执行fn的a方法,this才会指向fn,而(0, fn[a])只是返回fn[a]的结果即console.log(this),而此时this为undefined。在非严格模式下,应该是返回window(全局对象)。
2018-2-24
在 rgb 中,red 是暖色,green 是中性色,blue 是冷色,如果 r>b,则为暖色,否则为冷色。
在 hsv 中,hsv.h >= 60 && hsv.h <= 240
为冷色调,减淡变亮,色相顺时针旋转更暖。hsv.h <= 60 && hsv.h >= 240
为暖色调,减淡变亮,色相逆时针旋转更暖。
实现深拷贝
function deepClone(data) {
let r = null;
if (typeof data !== 'object') {
r = {};
for (let key in data) {
if (data.hasOwnProperty(key)) {
r[key] = deepClone(data[key]);
}
}
} else if (Array.isArray(data)) {
r = [];
for (let i = 0; i < data.length; i++) {
r.push(deepClone(data[i]));
}
} else {
return data;
}
}
2018-2-6
今天在使用 vue 的时候发现一个问题,beforeCreate 居然在 create 之后执行,百思不得其解,后来才发现原来在 create 中的 ajax 设置了 async 为 false,因为是同步,所以会导致 beforeCreate 中的 loading 组件延迟执行。
vue 中 provide,inject 使用。配合 vee-validate 可以在父组件中对所有使用验证的子组件进行验证。
为什么 flex 的子元素在设置 display 为 flex 后,它的子元素无法撑开它自己。
svg 中使用简便的时候,使用 d3.area()才渲染下面的面积,如果使用 d3.line()会使上扬的线条的上部分渲染。
2018-1-16
webpack-dev-server 使用,vue 模拟数据的配置。
nginx 中重写路径:
location /static {
if ($http_referer ~* "test\/"){
rewrite ^(/static\/.*) /test/$1 break;
}
rewrite ^(/static\/.*) $1 break;
}
2018-1-3
今天在给 ie 调试 ajax 的时候发现 ajax 不会发送,jquery1.5+ ajax 跨域请求在 IE 下没反应
The root route must render a single element 这个异常,这是因为 module.exports(CommonJS) 和 ES6 里的 export default 有区别。
如果你是使用 es6 的写法,并且就是你的组件都是通过 module.exports 导出的,那么在 getComponent 方法里面需要加入 .default。
如果你是使用 CommonJS 的写法,也就是通过 module.exports 导出的,那就无须加 .default 了。
在 vue 中使用 async。
2017-12-25
如果是自己手动配置 webpack,当你要打包的时候,打包的方式是 runtime-only build 模式(运行时构建),这个时候new Vue
挂载的时候不支持 template,只能只能 render,如果使用 template,就会报错You are using the runtime-only build of Vue where the template compiler is not available. Either pre-compile the templates into render functions, or use the compiler-included build
。
相关链接
因为要给公司开发自用的 chrome 插件,所以最近肯定要学习不少的内容。就在这几天使用 jq 的时候,发现很多以前的知识都遗忘了。
比如要获取 radio 的 checked 的属性时,不应该使用 attr,应该使用后 prop。
对于 HTML 元素本身就带有的固有属性,在处理时,使用 prop 方法。
对于 HTML 元素我们自己自定义的 DOM 属性,在处理时,使用 attr 方法。
给某个 name 的 radio 设置 checked 的 value,$('input[name="radioName"][value="checkedValue"]').prop('checked', true)
2017-12-20
移动端调试工具:debuggap,ChromeDevTools,weinre
2017-12-14
浏览器中, js 引擎线程会循环从 任务队列 中读取事件并且执行, 这种运行机制称作 Event Loop (事件循环)。
不仅如此, event loop 至少拥有如下两种队列:
1.task queue, 也叫 macrotask queue, 指的是宏任务队列, 包括 rendering, script(页面脚本), 鼠标, 键盘, 网络请求等事件触发, setTimeout, setInterval, setImmediate(node)等等。
2.microtask queue, 指的是微任务队列, 用于在浏览器重新渲染前执行, 包含 Promise, process.nextTick(node), Object.observe, MutationObserver 回调等。
以下是原文:
An event loop has one or more task queues. A task queue is an ordered list of tasks, which are algorithms that are responsible for such work as: events, parsing, callbacks, using a resource, reacting to DOM manipulation… Each event loop has a microtask queue. A microtask is a task that is originally to be queued on the microtask queue rather than a task queue.
浏览器(或宿主环境) 遵循队列先进先出原则, 依次遍历 macrotask queue 中的每一个 task, 不过每执行一个 macrotask, 并不是立即就执行下一个, 而是执行一遍 microtask queue 中的任务, 然后切换 GUI 线程重新渲染或垃圾回收等.
2017-12-13
cmd 中arp -a
、ipconfig/all
、nslookup
window.requestAnimationFrame 方式的应用。
nginx X-real-ip、X-Forwarded-For 字段理解:
proxy_set_header X-real-ip $remote_addr
是设置客户端的 ip,如果不设置,经过代理服务器 nginx 后,web 服务器接收到的 ip 是 nginx 的 ip,并非是客户端的真是 ip(如果只隔了 1 台 nginx)。
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for
意思是增加一个$proxy_add_x_forwarded_for 到 X-Forwarded-For 里去,注意是增加,而不是覆盖,只不过由于默认的 X-Forwarded-For 值是空的,所以我们觉得是赋值,在中间使用多台代理的时候就会展现不同。$proxy_add_x_forwarded_for 变量包含客户端请求头中的”X-Forwarded-For”,与$remote_addr 两部分。每次在 X-Forwarded-For 中增加一个 X-Forwarded-For $proxy_add_x_forwarded_for,就可以看成是将接收到的 X-Forwarded-For 加上自上一台代理或者客户端的 ip,逐一传递下来后 web 服务端就可以接收到从客户端以及各个代理的 ip。
2017-12-12
parallax.js 滚动插件的使用,注意不是 parallax 这个轻量级的可视化引擎。
srcset 的应用场景分析:同一张图片针对不同响应式展现不同精度的格式。
js 三种递归方式以及区别:
1.直接调用自身
function a(n) {
if (n <= 0) {
return 1;
} else {
return n + a(n - 1);
}
}
a(5); //15
let b = a;
b(5); //15
a = null;
b(5); //error:a is not a function
这里就可以看出,b 其实是 a 的一个引用,当 a 设置为 null 的时候,b 自己也就无法使用了。
2.通过 arguments 调用自身
let a = function () {}和匿名函数结论相同
function a(n) {
if (n <= 0) {
return 1
} else {
return n + arguments.callee(n - 1)
}
}
a(5) //15
let b = a
b(5) //15
a = null
b(5) //15
虽然 arguments.callee 可以调用自身,但是在严格模式下,是禁止使用 arguments.callee 的。
3.通过函数命名表达式
let a = function f(n) {
if (n <= 0) {
return 1;
} else {
return n + f(n - 1);
}
};
a(5); //15
let b = a;
b(5); //15
a = null;
b(5); //15
这个方法使用了函数命名表达式来定义函数 a。然后在函数内部通过函数名 f 来调用自身,这样就 b 和 a 也就没有任何关系了。他们的指针都指向 f 函数,在 a 设置为 null 后,也只是将修改了 a 的指针,并没有修改 f 函数。
2017-12-8
之前就研究过 exports 和 module.exports,最近好好梳理下。
module.exports = {}
这个时候因为 module.exports 绑定了一个新对象,所以会和原本的 exports 失去联系,exports 不再是 module.exports 的引用,所以 export.xx = xx 不会被导出。
解决办法是exports = module.exports = {}
,然后 exports.xx = xx 还是会被导出。
这是比较关键的一点。另一个是exports = {}
这个时候,exports 不再是原来的 module.exports 的引用,所以还是会失去关联。
若 exports 和 module.exports 都以 aa.xx = bb 的形式赋值,则相互不影响。若有相同的 key 时,value 取后赋值的,不是 module.exports 赋值的。
2017-12-6
js 下载文件方法汇总
1.a 标签 get 方式下载
window.open(url? + params)
2.form 表单 post 方式下载
$('body').append(form);
form.attr('style', 'display:none');
form.attr('target', '_blank');
form.attr('method', 'post');
form.attr('action', url);
for (let i in data) {
let input = $('<input>');
input.attr('name', i);
input.attr('value', data[i]);
form.append(input);
}
form.submit();
form.remove();
3.blog 方式下载
配合downloadjs一起使用;
axios({
method: 'post',
url: url,
data: data,
responseType: 'blob',
headers: {
Accept:
'application/vnd.openxmlformats-officedocument' + '.spreadsheetml.sheet',
},
}).then((res) => {
download(res.data, 'test1.xls');
});
2017-12-5
for (const prop in obj) {
if (obj.hasOwnProperty(prop)) {
console.log(`obj.${prop} = ${obj[prop]}`);
}
}
// for in 会循环继承的属性,而hasOwnProperty则会忽略继承的属性
2017-11-20
怎么在 vue 中修改 echarts 的 tooltip 框的大小宽度,因为 tooltip 框是一个 echarts 自动生成的 div,而他的样式都是行内样式,所以直接通过改变 tooltip 的样式是比较麻烦的,比较轻松的一种方式是通过formatter
来实现。
因为 formatter 可以返回一个 div,所以我们可以通过 params 得到图表的 name 等别的参数,然后显示在 div,通过给 div 一个 class,然后设置 css 来实现 tooltip 的换行已经宽度控制,当然如果在 vue 中使用的时候要格快注意取消 css 的 scope 属性。
2017-10-27
在 vue 遇到Do not use 'new' for side effects
,可以在这函数头顶上加一句/* eslint-disable */
。
删除 html 中的标签,删除空格,删除换行的正则匹配:
text.replace(/<.*?>/ig, '').replace(/(^\s*)|(\s*$)/g, '').replace(/(\n)/g, '')
2017-10-18
当 vue 使用 history 的 router 模式后,如果你想打包完看打包之后的项目,需要配置相关服务器配置,这是因为 vue 是单页面应用,而 history 在跳转的时候会直接跳转到另外一个网页,而不是当前的单页面,所以会出现 index 可以打开,但是跳转别的页面的时候会出现 not found,这是因为 route 在这里无法被识别。所以需要配置相关的服务器。
在官网中有好几种方式,我试了下 node 的,发现并不好用,因为他每次返回的 content-type 都是 text,这就导致获取到的 js 文件也是 text 类型,然后就会出现unexpected token >
这个错误。
然后我尝试使用 expredd 搭配connect-history-api-fallback
中间件这个方法,一开始也是有点摸不到头脑,连主页都是 not found,后来在issus#35中找到了答案,原来在使用这个中间件的时候,还要配置默认的静态文件和 index 跳转路径。
具体代码:
var history = require('connect-history-api-fallback');
var express = require('express');
var app = express();
// 这里指向你的index.html文件目录,第一次使用的时候是为了让中间件获取主要的静态文件请求
app.use(express.static('./'));
app.use(history({}));
// 第二次使用时为了让中间件重写请求,如果这里不添加的话只会显示主页,跳转别的页面的时候就会出现not found
app.use(express.static('./'));
const port = 5000;
app.listen(port, () => {
console.log(`Example app listening on port ${port}!`);
});
2017-10-13
在使用 swiper 的时候遇到了很多问题,首先是如果遇到页面进去不自动播放的话,先设置 observer 和 observeParents 为 true,还不行的话就看看 this.swiper.autoplayPaused 是否为 true,如果为 true 则设置为 false,然后在this.swiper.init()
一下就会自动播放了。至于点击之后不自动播放那就需要设置 autoplayDisableOnInteraction 为 false。
centeredSlides
可以让图片居中显示。
由于移动端和 pc 端还是有蛮大的差别,首先移动端不常用 px,很多是以 rem 为单位。
2017-9-22
UMM!~~好久没写了~还是照旧总结下最近新获取的到的一些内容~
- 在 bootstrap 的弹出框中看到可以点击弹出框外的部分实现弹出框关闭,vue 中就是在 created 中给 document.addEventListener 中绑定一个函数,让弹出框的 disable 为 true,然后给弹出框的 div 绑定一个 click,
event.stopPropagation()
即可。 - 最近的新项目比较大,然后数据接口全由前端来设计,虽然这对前端是好事,但是事情也多了不少了,接口对接文档写的头疼,特别是需求改了之后部分接口数据接口都变了,不过我发现写这个还是蛮有趣的,挺锻炼人的~
- 在关于 vue 中组件化的区分,如果父组件和子组件之间联系很大的话,比如子组件的渲染很大程度的依靠父组件各个数据,那么组件化的过程中可以主要的把 css 等样式组件化出去,js 等方法还是写在父组件中,但是如果是子组件自己的方法的话还是应该写在子组件中的 script 中。
- 虽然每天写代码,但是我发现其实自己的基础还是掌握的不好,很多基础的 api 还是需要去翻文档,不翻就写不出来,所以现在每天都会把基础的知识写在小本子上,平时的时候多翻翻。
- transition 不能应用在 display 的变化上。
- 如果不想使用 table,但是又想使用 table 的那些布局,那么可以给 div 设置 display 为 table-row 和 table-cell 来实现行和列的效果。
- 如果在 table 想让 table 的 tbody 出现滚动条,而 thead 保持不动,我发现实在是没什么好办法,虽然很多人说给 tbody 的 tr 和 thead 添加 display 为 table,但是当 tbody 的 display 设置成 block 之后 tbody 和 thead 就已经不联动了,如果你的 table 的 th 和 td 都是固定的,那还是可以显示那个效果,但是如果你的 th 和 td 都是联动的,th 的宽度和会根据 td 的宽度而改变的时候这时候这个方法就不适用了。所以这个时候只能通过 js 获得每个 td 的宽度,然后分别给对应的 th 设置宽度。
VeeValidate 的使用,在 main.js 中引入 VeeValidate,然后设置 config,再Vue.use(VeeValidate, config)
即可,你可以将需要验证的表单内容写在 main.js 中,也可以写在各自的组件中,只要在 created 中定义好表单信息,然后updateDictionary
一下,比如:
const dict = {
zh: {
custom: {
user: {
required: '用户名不能为空',
},
password: {
required: '密码不能为空',
},
},
},
};
this.$validator.updateDictionary(dict);
使用 vue 自带的 dev-server.js 写接口,比如:
// api.js文件的内容
let path = require('path');
let api = {
'api/url': path.resolve(__dirname, 'data/data.json'),
};
module.exports = api;
// 在der-server.js中引入接口api的文档
let api = require('../mocking/api');
//遍历api中每个对象
Object.keys(api).forEach(function (url) {
app.get(url, (req, res) => {
fs.readFile(api[url], 'utf8', (err, data) => {
if (err) return console.log(err);
let json = JSON.parse(data);
res.json(json);
});
});
});
你将需要的数据写在 json 文档中,这样当你写好接口文档的时候,就不需要等到后端接口写好才去测试,自己可以边开发边测试接口数据。post 的类似,不过需要一些 node.js 知识来判断传过来的数据。
2017-8-11
在学习 node 的时候把 node 更新到了 8.3.0,结果之前的几个用了 sass 的项目打不开了,原因貌似是因为依赖的 node 版本改变,我 npm rebuild node-sass 后发现还是不行,就下了一个 nvm 解决了。使用 node.js 的时候用 8.3.0,不然就切换会 6.10.1。
2017-8-4
使用 scss 的时候记得安装相应的包:
npm install sass-loader node-sass vue-style-loader --D
然后再 style 中加入lang="scss"
只有设置了 prototype 的对象可以查看 prototype,不然不可查看。
构造函数 new 出来的对象的 constructor 会随着原型的改变而改变。如果原型没有改变,constructor 就指向构造函数,如果原型改变,则 constructor 则指向修改后的原型的 constructor。
理解 js 中的 replace 函数用法:
当第二个参数是函数的时候,他会给函数传递几个参数,matchStr,groups,index,sourceStr,其中 groups 根据正则中分组的情况增加,有两个分组就会传递 matchStr,group1,group2,index,sourceStr。
matchStr: 每次正则匹配到的字符串,这是固定的;
groups: 代表的是 group1,group2,group3……等等参数。参数个数根据捕获组的个数来定。
index: 匹配项在字符串中的开始下标;
sourStr: 原字符串。
2017-8-2
今天看了十年踪迹在清华大学演讲的 ppt,看到他用了很多的高阶函数,使用它的目的是 write less, do more!所以在今天也学习了很多简单高阶函数的用法!
第一次看到高阶函数的时候,比较感觉困惑的是参数的定义,当最外层函数传入一个参数的时候,内层函数再传参数那参数到底是怎么层层调用的呢,然后输出函数又是怎么再内层函数中调用,以及一系列的问题。现在来总结一下:
比如这个例子:
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li>
<li>7</li>
<li>8</li>
<li>9</li>
</ul>
function batch(fn) {
return function (target, ...args) {
if (target.length >= 0) {
console.log('11');
return Array.from(target).map((item) => fn.apply(this, [item, ...args]));
} else {
return fn.apply(this, [target, ...args]);
}
};
}
function queriable(fn) {
return function (selector, ...args) {
if (typeof selector === 'string') {
selector = document.querySelectorAll(selector);
}
console.log(...args);
return fn.apply(this, [selector, ...args]);
};
}
function pack(map) {
return function (el, obj) {
for (let key in obj) {
map[key].call(this, el, obj[key]);
console.log(obj[key]);
}
};
}
function setColor(el, color) {
el.style.color = color;
}
function setFontSize(el, fontSize) {
el.style.fontSize = fontSize;
}
let css = pack({ color: setColor, fontSize: setFontSize });
css = queriable(batch(css));
css('ul > li:nth-child(2n + 1)', { color: 'red' });
css('ul > li:nth-child(3n + 1)', { color: 'green', fontSize: '22px' });
刚开始看到这个的时候我是比较困惑的,到底是先执行 css,再 batch,还是先 queriable 再 batch,所以我在每个函数中打 log,打每个的 args 等参数,了解到函数都是从外到内运行,即 queriable 到 batch 再到 css,然后参数都是通过函数内置的 arguments 来传递。
其中那个 pack 函数我整整理解了很久才领略到高阶函数的魅力,他的确能够用更少的代码做更多的事,虽然难度比较大,也不好理解。
以及这个应用了 ramda.js 的例子:
最开始我并不是很理解函数柯里化,但是当我理解了这个例子中 changeColorTo 函数后,我不禁感叹函数柯里化的强大,而对于 ramda.js 这个库,阮一峰老师的这篇博文也说的很棒这里。
<div id="students"></div>
<button id="printBtn">print</button>
class Component {
constructor(id, opts = { data: [] }) {
this.container = document.getElementById(id);
this.options = opts;
this.container.innerHTML = this.render(opts.data);
}
}
class StudentViewModule {
constructor(view) {
this.view = view;
this.nameEl = view.querySelector('.student-name');
this.ageEl = view.querySelector('.student-age');
this.ageEl.onchange = function (evt) {
this.age = evt.target.value;
};
}
}
// 这里使用defindProperty是因为要双向绑定,不然可以直接在class StudentViewModule中设置name和age
Object.defineProperty(StudentViewModule.prototype, 'name', {
set(val) {
this.nameEl.innerHTML = val;
},
get() {
return this.nameEl.innerHTML;
},
});
Object.defineProperty(StudentViewModule.prototype, 'age', {
set(val) {
this.ageEl.value = val;
},
get() {
return this.ageEl.value;
},
});
class Students extends Component {
constructor(id, opts = { data: [] }) {
// super()是新建父类的this对象,但是this还是指向子类,所以这里调用父类的constructor的方法,其中的this指向子类,
// 所以父类的constructor方法中的this.render不会报错,因为this指向子类。
super(id, opts);
this.bind();
}
render(data) {
let content = data.map(
(student) => `
<li class="student-info">
<span class="student-name">${student.name}:</span>
<input type="text" value="${student.age}" class="student-age"/>
</li>
`
);
return `<ul>${content.join('')}</ul>`;
}
bind() {
let students = this.container.querySelectorAll('li.student-info');
let data = this.options.data;
let info = [];
students.forEach((student, i) => {
info[i] = new StudentViewModule(student);
});
this.studentInfo = info;
}
}
let data = [
{
name: '张三',
age: '27',
},
{
name: '李四',
age: '21',
},
{
name: '王五',
age: '22',
},
{
name: '赵六',
age: '23',
},
];
var studentList = new Students('students', { data });
printBtn.onclick = function () {
// 这里studnetList中调用了new Students,他在bind()中设置了studentInfo,这里的student是studentList.studentInfo的每个对象
console.log(
studentList.studentInfo.map((student) => {
return [student.name, student.age];
})
);
};
这是一个双向绑定的例子。
不得不说,今天的收获满满,虽然没做什么,但是感觉对 js 的理解更深了一步。
2017-8-1
alert(1 && 2)
会输出 2,知道这是为什么吗?
在使用 object.defineProperty 的时候要注意 descriptor 的定义。
//调用Object.defineProperty()方法时,如果不指定
var someOne = {};
someOne.name = 'coverguo';
console.log(Object.getOwnPropertyDescriptor(someOne, 'name'));
//输出 Object {value: "coverguo", writable: true, enumerable: true, configurable: true}
//直接在对象上定义的属性,这个特性默认值为为 true
var otherOne = {};
Object.defineProperty(otherOne, 'name', {
value: 'coverguo',
});
console.log(Object.getOwnPropertyDescriptor(otherOne, 'name'));
//输出 Object {value: "coverguo", writable: false, enumerable: false, configurable: false}
2017-7-27
如果是对整个子组件应用 vue 过渡效果的时候,由于没有设置 position,它在进入和消失的时候会闪屏,因为他消失好像是从上往下,我应用的时候由于顶部有个 black 的 bar,所以看起来特别明显。但是设置了 position 后就没有这个闪屏的效果了。
2017-7-26
在 vue 中使用 addEventListener 的时候,不要直接绑定在 body 上,这样多次绑定同一个函数的话不会被覆盖,应该覆盖在相应的组件上,可以用$.el
来获取当前的组件。
使用 v-html 插入 html 的时候,如果当前组件的 css 是 scoped 的,那么插入的 html 不会被 css 渲染,解决方法就是不要设置 scoped 属性。
vue 不会监测到一个对象新属性的增加与删除,解决方法是使用vm.$set(target, key, value)
和vm.$delete(target, key)
。
mixins 选项可以接受一个混合对象的数组。这些混合实例对象可以像正常的实例对象一样包含选项,他们将在Vue.extend()
里最终选择使用相同的选项合并逻辑合并。Mixin 钩子按照传入顺序依次调用,并在调用组件自身相同的钩子之前被调用。比如 mixins 里的 created()钩子在实例的 created()前调用,但是 mixins 的 mounted()钩子在实例的 created()钩子之后调用。
使用 directives 指令的时候,由于传入的参数只能是可读,当你要修改传入的参数的时候,使用 dataset 来修改。dataset 可以绑定 data 中的变量,但是在 directives 中修改 dataset 值的时候发现,他只能修改所绑定 el 的 dataset 的值,但是不会同时修改 data 中 dataset 所绑定的变量的值。比如:
<div v-a :data-name="bb">2222</div>
data () {
return {
bb: '22'
}
}
directives: {
a: {
bind (el) {
console.log(el.dataset.name) // '22'
console.log(el) // <div v-a data-name="22">2222</div>
el.dataset.name = 'bbb'
}
}
}
// <div v-a data-name="bb">2222</div>
执行完函数后发现div中的data-name等于bbb,但是data中的bb还是等于22。
2017-7-24
因为要短时间重写 jsp 老项目,只能暂时用 iframe 来代替 jsp 的 include,在使用 iframe 的时候发现获取不到页面滚动条的数值,最后自己再看 window.parent 的时候发现可以在window.parent.document.scrollingElement
中获取 scrollTop。
function totop() {
var scroll_top = window.parent.document.scrollingElement;
$(scroll_top).animate(
{
scrollTop: '0px',
},
400
);
}
2017-7-19
除了使用 chrome 的 web server 扩展可以开本地服务,也可以使用 npm 的 serve 来开启服务,他的端口自动设为 5000,如果占用了就往上加。
2017-7-13
windows 下全局安装 mocha 的时候发现无法安装,主要是没有管理员权限,解决方法是以管理员权限运行 cmd,再进行全局安装。
设置 node.js 的全局安装路径:打开 git,输入npm config ls
,修改 prefix 的值,npm config set prefix "xxxxxxxx"
就 ok 了。
关于 istanbul 这个代码覆盖率工具,如果是在 window 上和 mocha 一起使用的时候,要注意不能直接打istanbul cover _mocha
这个代码,因为 window 的路径问题,要使用istanbul cover node_modules/mocha/bin/_mocha
,这个在官方说明上 usage on windows 也有提到。
学习了一些 makefile 文件的配置,不过因为在 window 系统上,所以刚开始使用的时候还是很懵比,怎么也用不了 make。后来在http://sourceforge.net/projects/mingw/files/latest/download?source=files
上下载了 GNU 编译器,然后在后面的界面中选择基础配置和 C++编译器,将 MinGW 安装目录下的 bin 中的 mingw32-make.exe 重命名为 make.exe。接着就可以使用 make 指令了,网上有说要配置系统变量,不过我没配置好像也可以运行。之后我在 git 上尝试使用 make,但是始终告诉我 make commend not found,配置了用户变量也是提醒这个错误,我也不知道这个是什么原因 0.0。
2017-7-5
今天又遇到给后台传参要传数组的问题,发现还是不好传,所以以后还是直接传 json 对象比较好。今天还遇到表单提交的时候需要另外提交字段,如果后台用了 spring,解决方法是接受的时候增加一个参数来解析文字。
今天在使用 vuex 的时候发现,如果跳转的使用的是window.location.href
,那么 vuex 中 store 保存的信息都会清空,这是因为window.location.href
会刷新页面。所以在 vue 中需要跳转的时候最好是用this.$router.push()
来进行跳转。
2017-7-4
一看发现好久没写心得了,最近也比较忙(其实都是借口,就是懒),今天电话面试了一家公司,感觉自己还不错,虽然有些问题没答上来,以及在厕所不敢大声说话。这次面试也学到了蛮多东西,主要是一些 js 基本的应用概念,太久没写原生 js 了,发现自己有点忘了,还是要常常温故,之前拉下的 js 高级教程的笔记也要开始补起来了。今天被问到一些 ie8 兼容性,MVVM,MVP,MVC 框架的区别等等,以前都记过但是忘了,今天重新记下笔记:
- ie8 关于 json 的兼容性,因为 ie8 不兼容 JSON.parse()的解析方法,所以可以使用 eval()方式,不过比较危险,因为 eval()在解析的时候会执行字符串中的代码。关于转成字符串,一个比较有趣的方式是将 JSON.js 改名为 JSON2.js,然后调用 JSON2.stringify()。
- MVC 框架是最早提出的,用户操作->View(负责接收用户的输入操作)->Controller(业务逻辑处理)->Model(数据持久化)->View(将结果反馈给 View)。MVP 是把 MVC 中的 Controller 换成了 Presenter(呈现),目的就是为了完全切断 View 跟 Model 之间的联系,由 Presenter 充当桥梁,做到 View-Model 之间通信的完全隔离。如果说 MVP 是对 MVC 的进一步改进,那么 MVVM 则是思想的完全变革。它是将“数据模型数据双向绑定”的思想作为核心,因此在 View 和 Model 之间没有联系,通过 ViewModel 进行交互,而且 Model 和 ViewModel 之间的交互是双向的,因此视图的数据的变化会同时修改数据源,而数据源数据的变化也会立即反应到 View 上。
通过这一段话可以看出 MVVM 框架比较重要的进步是关于数据的控制,双重绑定保证了数据的一致性,而且在获取数据上也比通过 dom 操作简单很多。 - 关于 vue 的数据渲染逻辑:自定义 Render 函数,template 写法,el 写法。不过基本都是用 template。
- Vue 中 v-bind 和 v-on 的区别,v-bind 绑定的是变量,v-on 绑定的是方法,虽然知道怎么用但是一时间却说不上来这个。
现在总结一下这半个月学到的一些东西:
- 深层次的了解了 js 中的运算机制,比如
++[[]][+[]]+[+[]] = 10
,(1+{})[4]= j
等等(详见 justjavac 博客) - 公司新项目的开发,其中用到了一个集合 input 和 select 功能的 div,就是能用够像 select 一样进行下拉列表展示,也可以在 select 框中手动输入数据,并自动 filter,主要的思路就是使用一个 div,下面包裹一个 ul 列表用来展示下拉列表。
- 学习了 es6 的编码规范
- 在使用 JQuery 的时候,注意使用变量的时候使用单引号将字符串隔开
昨天在听了部分 justjavac 的知乎 live 中的前端工程师的入门与进阶,我总结几个要点:
- 前端工程师也还是程序员,所以必须要写出比较好的代码,好的代码包括,代码的很强壮,比较容易维护,逻辑条理清晰
- 在学习新的框架的时候也不能忘了 js,css 等基本的东西,很多人都是学习了 3 个月的知识,然后重复使用了好多年,即使有多年经验,但是知识还是那么多
等有空我单独写一篇心得 0.0
2017-6-20
毕业典礼请假了半个多月,感慨很多,今天回来上班,那就好好工作学习。那么今天呢,主要学习了关于前端反向代理跨域来调用后端的接口,从而获得数据。
一开始我使用的是 ngnix,在配置 ngnix 的时候我也遇到了一些问题:
- 当修改了配置文件的时候,ngnix -reload 不管用,需要先 ngnix -quit,在 start ngnix。
- ngnix 监听的端口不能与项目的端口一样,会产生冲突。我一开始使用的是 vue 的的 8080 端口,而 ngnix 的端口是 80,所以一直显示 404。
- ngnix 的 location 有两种写法,一种是 rewrite,一种是直接在标记的代码结构前添加请求的网址。相比较后一种直接添加的比较方便。
因为使用了 vue,如果在项目外重新开 ngnix 的话,ngnix 就监听不了 vue 的项目了,后来发现 vue-cli 本来就有反向代理这个功能,就是在 config 中的 index.js,proxyTable 这个字段,适用方法如下:
proxyTable: {
'api': {
target: 'your url',
changeOrigin: true
}
}
当你在页面中调用 api/aa 的时候,返回的数据就是 your url/api/aa 接口的数据。
当然 proxyTable 也有 rewrite 的功能。
proxyTable: {
'api': {
target: 'your url',
changeOrigin: true,
pathRewrite: {
'^/api': 'bb'
}
}
}
这样你在页面中调用 api/aa 的时候,返回的数据就是 your url/bb/aa 接口的数据。
2017-5-25
在知乎上看到一个话题,有个公司面试了一个 5 年经验的前端,结果那个面试者答不上原型链的基础知识,张口闭口就是 vue,react 等框架的实现原理等等,看着评论,大家的反应都不太一样,很多人说面试官要会发现面试者的优点,但是也有很多一批人说连 js 基础的知识了解的都一知半解,说句实话,感觉如今人们被工具支配的太恐怖了,以至于有了工具却不去了解基础知识了。我在平时的学习中一定要打好基础,努力加油。下面是哪个面试官出的一道题目:
输入 m,n,生成一个长度为 m 的每个数都为 n 的数组,如果不能用循环,可以使用递归:
function t3(m, n) {
var arr = arguments[2] || []
if (m > 0) {
arr.push(n)
t3(--m, n, arr)
}
return arr
}
或者使用new Array(m+1).join('n')
,不过递归的方法没有循环来的性能高。
arguments 对象存储的是实际传递给函数的参数,而不局限于函数声明所定义的参数列表,而且不能显式创建 arguments 对象。
2017-5-11
今天在用 vue 获取 ajax 请求的数据的时候发现一个问题,当我在 created 发出 ajax 请求来获取数据,在 template 中调用的时候,会报错,原因是因为当我调用的时候,数据还没有请求到,所以会出现 undefined 的现象,解决方法是在请假数据的外面包一个 div,v-if="数据"
,这样当数据不存在的时候便不会执行下面的代码,当数据请求到了,会自动更新。
2017-5-10
如果要给后台传 json 字符串的话,比如 ajax 中的请求是data: Data
,Data 是 json 字符串,那么需要在 ajax 中添加这句话,contentType: 'application/json; charset=utf-8'
,告诉服务器,我给你的 json 字符串,不然可能会出错。但是如果 json 字符串是写在 data 的对象里的话,则不需要写那句话,如:data: {jsonString: Data}
。
2017-4-26
try-catch 语句中如果后面跟着 finally 子句,那么无论 try 还是 catch 语句中的 return 语句都被毁忽略。finally 语句一定会被执行。
2017-4-21
因为 vue 中的 {{}} 是文本插值,所以 data 中的’\n’是不会再 html 中换行的,不过可以在换行的地方使用<br>
进行换行,用 jq 的 html()显示
2017-4-19
当使用 bootstrap 的时候,如果子元素设置了 margin-top,父元素没有 clearfix 的话,可能会出现子元素的 margin-top 应用在了父元素上,即父元素有了 margin-top,而子元素还是和父元素紧紧的依靠在一起,解决方法是给父元素 clearfix,出现这个的原因是 bootstrap 中有自带的默认 float 属性。
2017-4-17
在 vue 中使用 datetimepicker 插件的时候,因为这个插件是依赖 jq 的,所以在使用这个插件的时候在先引入 Jq,第一种方法在 index.html 中引入 jquery.js,在 webpack 中加入全局变量$
externals: {
jquery: 'window.$';
}
,然后再 index.html 中引入插件的 js 文件,在 vue 组件中 require jq,var $ = require('jquery')
,就可以使用了。
第二种方法是在 index.html 中引入 jq 文件,然后再 vue 组件中 import 插件的 js,再 require jq,var $ = require('jquery')
,就 ok 了
2017-4-10
当使用 CSS3 的 nth-child()的时候,千万要记住 body 是 html 的第二个子元素,所以 nth-child(2)会应用在 body 上。
CSS 的样式优先级:内联样式 > 内部样式 > 外部样式。
- JQ 的 addClass 是在外部文件或者内部样式中定义好的。
- JQ 的.css()是直接通过元素的 style 属性附加到元素上,属于内联样式。
所以.css()的优先级会高于 addClass,当你使用 JQ 实现点击、hover 样式转变的时候,最好使用 addClass 不容易出错。
2017-4-6
word-wrap 和 word-break 的区别:word-wrap 是用来决定单词内要不要断句,word-break 是用来决定怎么样断句。共同点就是当一个单词过长超过包裹的父级元素的宽度的时候,会另起一行,将单词断开。但是不同点是,word-wrap 会先另起一行,即将那个很长的单词另起一行显示,当那个单词太长一行都放不下的时候,再断开。但是 word-break 不会另起一行显示那个单词,而是接着前面的单词,当那行剩余的部分包裹不了的时候再换行。所以 word-break 比较节省空间。
2017-3-25
页面使用 border 创建一条线,怎么让它在 div 中竖直方向居中,除了用了 position,,可以使用 margin
2017-3-23
这几天学习了 vue.js
在 methods 中调用 ajax 的时候,一开始的 this 指向 vue 实例,但是 success 中的 this 指向 success 这个方法,如果要在 success 方法中调用 vue 实例中的数据,可以在 ajax 开头var self = this
,那这个 self 就是 vue 实例。
2017-3-17
position:fixed 始终以 body 为父级元素,所以当 height 为 100%的时候就会覆盖整个页面,用来整页修改 css 很有用。
2017-3-15
今天遇到了一个问题,在写项目的时候发现动态生成的 48 个表单中,有一个表单的样式不对,然后今天自己就好好使用断点来查找问题,最后发现是传回来的数据的末尾是/,然后和>形成了闭合,所以产生了两个 tr。所以以后再使用 js 动态添加节点的时候,最好值和>之间空一个空格,就可以避免这个问题,然后,虽然这个问题很小,但是我比较算正式的使用了断点这个功能,感受了他的魅力!
2017-3-13
今天遇到一个错误,显示 Uncaught SyntaxError: Unexpected token o in JSON at position 1
查了一下资料,原因是接收到的 json 已经是对象了,所以不能再使用 JSON.parse()将之转换成对象。
2017-3-10
项目基本写完了,这几天都在看 JavaScript 高级程序设计,看了 BOM,DOM,客户端检测,感觉看的晕乎乎的,没有前面几章看到有兴趣,也许是因为这几张比较侧重实例,不过自己还是要好好啃完它,啃完就要准备开始学习 vue 了。
2017-3-8
昨天和今天主要在为原来的项目增加可爬的数据类型,其中有好几种很复杂的数据,数列对象各种包,这里写几个遇到的一些麻烦。
- input end 不规范基本是因为{}没有断好。
- 不要使用 if,if,else。应该使用 if,else if,else。
- 注意 input 和 textarea。
- 如果对象的属性是变量的时候,需要使用 obj[]来获取属性,必要的时候自己来构建一个 str。比如:str=”[parma”+1+”]”,obj[str]。这里的 str=[parma1]。
- 在写 ajax 的时候,如果 data 是一个 json 对象,可以在赋值的时候直接添加到 data 里,也可以全部赋值完后统一定义 data。
- 使用 JQ 通过变量来获取某个节点的值的时候,不能直接$(name div),应该使用 find,parent 等方法来获取。
- 注意使用 return false 的后果。如果在循环中使用 return false 会直接种植循环。其次,return 语句只能在函数中使用,起的地方使用会报 Illegal return statement 错误。
- 使用 Object.getOwnPropertyNames(a).length 可以获取对象,数组的长度。
2017-3-6
写完项目的所有接口,用了很多数组的方法,也在 js 写了很多动态创建 html 的代码,从刚开始的不会使用++到现在的比较熟练,感觉还是学到了很多。
2017-3-4
今天写了分页,动态的获取数据库里的信息,发现一开始自己写的太复杂,其实写起来很简单,也学到了怎么通过 this 获取 this 里面的 span 的内容。
$('>span', this).text();
2017-3-2
今天遇见输入 input 时只要点击空格键就会自动提交并刷新表单,解决方法是:
$('input').keydown(function (event) {
if (event.keyCode == 13) return false;
});
这里的 keyCode==13 是代表回车键。
使用了 confirm(),在 confirm()中二次使用 ajax。
优化了项目中获取数据的表达式,感觉以后自己再写代码的时候要多注意代码的质量,考虑到可维护性,以及算法的优化。
2017-3-1
split(),join()用来数组和字符串的转换
学习了 BOM,window 对象,了解了 window.location 对象,并使用了其中的 href 和 search 的用在了自己的项目里。
使用了 window.open(),window.location.href 等等。
2017-2-28
JQ: focus()方法相当于 Javascript 中的 onfoucs()方法,作用是处理获得焦点的事件。
blue()方法相当于 Javascript 中的 onblur()方法,作用是处理失去焦点的事件。
offset()方法是获取元素在当前视窗的相对偏移。
scrollTop()和 scrollLeft()方法是获取元素的滚动条距顶端的距离和距左侧的距离。这两个方法也可以指定一个参数,控制元素的滚动条滚到到指定位置。
2017-2-27
JQ 的选择器,了解了选择和筛选的区别,children()是筛选子元素的,不会考虑其他后代元素,空格是选择后代的,< 是选择子元素的。
next()用于取得匹配元素后面紧邻的同辈元素。
prev()用于取得匹配元素前面紧邻的同辈元素。
siblings()用于取得匹配元素前后的所有同辈元素。(ps:这个函数很有用,可以用来点击按钮的时候改变 class)
closest()方法用于取得最近的匹配元素。
$('#CrawlerTable').delegate('.c-start', 'click', function () {
var startId = $(this).parents('tr').attr('id');
$.ajax({
type: 'POST',
xhrFields: {
withCredentials: true,
},
crossDomain: true,
url: dataUrl + '/SpyderPlatform/spyderInfo/start',
dataType: 'json',
data: {
id: startId,
},
success: function (data) {
if (data.result == true) {
alert('启动成功');
window.location.reload;
} else {
alert('启动失败或者已经启动');
}
},
});
});
这里的 xhrFields 的是用来设置本地 XHR 对象的”名-值”映射,可以在需要时设置”withCredentials”为 true 二人执行跨域名请求。
而 crossDomain 为 true 为跨域请求,false 为同域请求。
2017-2-23
ajxx 的基本格式:
$('#mysave').click(function(){
$.ajax({
type:"POST",
url:{},
datatype:'json';
async: false,
error: function(request) {
alert("Connection error");
},
success: function(data) {
$("#").parent().html(data);
}
})
})
这里的 data 是发送到服务器的数据,如果不是字符串,将自动转换为字符串格式。可以想要防止这种自动转换,可以使用 processData 选项。
dataType 是预期服务器返回的数据类型,如果不指定,JQuery 将自动根据 HTTP 包 MIME 信息返回 responseXML 或 responseText,并作为回调函数参数传递。可用的类型有:xml,html,json,script,jsonp,text。
jQuery 中 bind(),live(),delegate(),on()区别,点击这里.
今天在写项目的时候由于需要动态的创建文本,而文本里面有一些按钮来控制动态效果,如果只用 click,bind 事件来绑定这几个按钮的话,会发现浏览器没有报错也没有执行,查了资料请教了主管后才之后这个时候需要使用 deligate()方法,deligate()方法可以绑定未来的元素,比如脚本新创建的一些元素,而 live()和 deligate()的原理相同,只是 live()是绑定到元素上,而 deligate()可以通关过父级元素绑定到子元素。live()方法已经在 JQ1.7 版本被弃用,所以最后不要再使用,而以上的方法都是通过 on()方法来实现,所以 on()是万能的。
2017-2-22
margin-top,margin-left,margin-right,margin-bottom 是 body 中的属性
th,td 是表格的元素,与之对应的是
padding-top,padding-left,padding-right,padding-bottom,以及 vspace,hspace,cellspacing,cellPadding=0
等元素
今天学习了 input 框的一些属性:placeholder,required 等,还有一个 label 的 for,配合 input 的 id 使用。
JQ 的 clone(),index(),attr(),find(),after().
clone()可以解决一些需要动态创建相同格式的 html 元素。
index()这个函数也很有用,比如当我们点击一个按钮的时候,如果这类按钮有很多个,但是我们需要知道这个按钮的 index,比如点一个按钮,然后会使包裹他的父级 div 消失,因为都是同时出现的,只有合理的设置好 class,这个时候我们就可以通过按钮的 index 来得到 div 的 index,从而操控,但是如果我们要自己写,思路就是点击这个按钮的时候,最关键的就是得到这个按钮的 index,但是如果我们用普通的 js 来写就会有点麻烦,因为要得到按钮的 index,你首先需要遍历所有的这类按钮,然后给每个按钮一个 index,比如 btn.index = i ; 然后再次循环给每个按钮一个 click 事件,但是如果第二次循环给按钮一个 click 事件,那当我们点击这个按钮的时候就不会触发这个 click 函数,所以这时候我们就需要 index()这个函数来写。
就可以通过 index()解决。
$(document).ready(function(){
$(".Element").click(function(){ //添加按钮元素
alert($(.Element).index($(this)[0]));
})
})
2017-2-18
这几天学了一点 vue.js,推荐一个比较轻松愉快的入门博客,点这里.
2017-2-15
轻松愉快的一天!一天都在面试,所以晚上放松一天,明天继续努力学习!(晚上找了一些之前几个问题的答案,已附上)
oh my god~!
刚才遇到了被占用端口的问题,通过这个才了解
原来也是我的福昕阅读器占用了我的端口~
2017-2-14
今天是情人节哟,不知道小伙伴们都有没有人陪,我今天又在图书馆呆了一天,今天学习了原型的继承,函数表达式,因为明天的面试,略微的看了 xml,json 和 ajax 技术,没有足够的时间让我准备心里还是有点难过的,晚上具体的看了些 ajax 的代码,希望明天面试顺利,加油!
2017-2-13
今天在图书馆泡了一天,收获的不是一般的多,看了很多 js 的书,大概写了以下一些问题。
- 正则表达式的概念
- 创建数组时用 new 和不用的区别
- new 操作符在 js 中的意义
- 如何提升 js 的性能
- 函数声明,函数表达式的区别,以及一些扩展(声明提前,变量提前)
- URL 和 URI 的区别
好了,现在来一个个的解决。
正则表达式的含义我用一张图来解释。
关于创建数组时用不用 new 需要知道两个概念,就是栈对象和堆对象,在 JS 高程里面的第 119 页详细的介绍了,如果用 new 来创建一个新数组的,那这个数组就是属于堆对象,他不会自动销毁,需要手动释放否则可能会出现内存泄露。如果不用 new 的话,那这就是一个栈对象,这个只存在一行代码的执行瞬间,然后立即被销毁。
new 操作符在 js 中的意思,当用 new 操作符创建一个空对象时,this 指向该空对象,而且这个对象会继承原函数的原型,属性和方法也会加入到 this 引用的对象中。新创建的对象由 this 引用,并且最后隐式的返回 this。
如何提升 js 问题,我发现一个比较不错的博客,推荐给大家,点这里。
函数声明,函数表达式的区别其实很简单,就是函数声明的话函数名和函数体会提前,他属于那种随叫随到的,只要你需要了,我就到了。而函数表达式不会提前,他是属于那种只有你到我这里了,你才能见到我,不然休想。再翻其他资料的时候,也看了很多关于变量提前,以及关于这三者混合出现的一些情况。
这里简单的说下当变量声明和函数声明同时提升的时候(变量名和函数变量名相同),函数声明会覆盖变量声明,即最终那个变量显示的结果以函数为准,这个是变量声明而不是变量赋值。其中这个有一道比较好的题目,如果理解了这个应该对这几个名词的区别也了解的差不多了。点这里。
URI 是统一资源标识符,而 URL 是统一资源定位符。因此,笼统地说,每个 URL 都是 URI,但不一定每个 URI 都是 URL。这是因为 URI 还包括一个子类,即统一资源名称 (URN),它命名资源但不指定如何定位资源。上面的 mailto、news 和 isbn URI 都是 URN 的示例。
二者的区别在于,URI 表示请求服务器的路径,定义这么一个资源。而 URL 同时说明要如何访问这个资源(http://)。
今天 so tired!这里非常欢迎有大神以及小白来找我讨论,如果我哪里有写错的话也非常愿意听你来给我指导,表示一直缺一个小伙伴一起进步呢,我的微信是 Yhspehy。快来找我玩哈!