封装Axios
https://juejin.im/post/59a22e71518825242c422604
滚动条在IOS不流畅
// 在设置overflow的那个node节点上添加:
-webkit-overflow-scrolling: touch;
promise的用法
// 比如A、B都是异步。
// B要在A返回结果后再执行
A () {
return new Promise((resolve, reject) => {
this.$axios.get(`${prefix}/plan/getWeekCalendar`)
.then((res) => {
if (res.data.success) {
// A返回结果了
resolve()
}
})
.catch((err) => {
console.log(err)
})
})
},
A()
.then(B) // 注意,这里B没有括号
vue阻止事件冒泡
@click.stop
axios和session问题
http://www.jb51.net/article/118555.htm
两个inline-block不对齐问题:
// 一般会出现img 配 div 时,
// 原因是:基线问题
vertical-align: top;
微信内置浏览器点击事件会闪烁
-webkit-tap-highlight-color: transparent;
VUE里的data
// 子组件中(写法1):
template: '<div>{{ template }}</div>',
props: ['temp'],
data () {
return {
template: this.temp // 这里template得到的只是快照。所以这里的值,只会是父组件mounted()前的temp的值
}
}
// 子组件中(写法2):
template: '<div>{{ template }}</div>',
props: ['template'], // 因为props一直是最新的。可以和data一样使用实现响应式,只不过是只读的
// 子组件中(写法3):
template: '<div>{{ template }}</div>',
props: ['temp'],
computed: {
template () {
return this.temp // 通过计算属性,源源不断的给他计算出最新的temp值
}
}
// 子组件中(写法4):
template: '<div>{{ template }}</div>',
props: ['temp'],
data () {
return {
template: ''
}
},
watch: { // 监听props的值,然后动态更新我们子组件里面的template
temp () {
this.template = this.temp
}
},
created () {
this.template = this.temp
}
VUE里的set
Vue.set( ) 用来设置对象的属性,如果对象是响应式的,那么为了确保对象的属性在被新创建后也是响应式的,同时保证会触发试图更新。
所以这个方法主要用于避开Vue不能检测属性被添加的限制
https://www.w3cplus.com/vue/vue-reactivity-and-pitfalls.html
坑:
<div v-for="item in items">
<!--这里item的isSubscribed属性是拉取接口后,我手动新增的,因此不会被vue检测到-->
<div :class="{ isSubscribed: item.isSubscribed }"></div>
</div>
// 解决方案1:
this.$set(this.items, 'isSubscribed', true)
// 解决方案2:
this.items = Object.assign({}, this.items)
VUE里的slot
slot 是插槽的意思
一般我们在父组件里引用子组件,不会塞任何东西的,如:
<div class="IamParent">
<h1>我是父标题</h1>
<Child></Child>
</div>
有时候可以在
<Child></Child>
里面塞东西,就要用到<slot>
了
// 在父组件中:
<div class="IamParent">
<h1>我是父标题</h1>
<Child>
<p>这是给儿子的第一个礼物</p>
<p>这是给儿子的第二个礼物</p>
</Child>
</div>
// 在子组件中:
<div class="IamChild">
<h2>我是子标题</h2>
<slot>
我没有收到父亲的礼物(这段文字只有在,父组件没有给子组件分发任何内容时才会显示)
</slot>
</div>
// 最终渲染结果:
<div class="IamParent">
<h1>我是父标题</h1>
<div class="IamChild">
<h2>我是子标题</h2>
<p>这是给儿子的第一个礼物</p>
<p>这是给儿子的第二个礼物</p>
</div>
</div>
上面的是单个插槽,如果要特定插入到子组件的哪个插槽,那就要用到
<slot>
的 name 属性
// 在父组件中:
<div class="IamParent">
<h1>我是父标题</h1>
<Child>
<p slot="first">这是给儿子的第一个礼物</p>
<p slot="foot">这是给儿子的第二个礼物</p>
</Child>
</div>
// 在子组件中:
<div class="IamChild">
<h2>我是子标题</h2>
<slot name="first">父组件没有给我第一个礼物</slot>
<slot name="second">父组件没有给我第二个礼物</slot>
</div>
// 最终渲染:
<div class="IamParent">
<h1>我是父标题</h1>
<div class="IamChild">
<h2>我是子标题</h2>
<p slot="first">这是给儿子的第一个礼物</p>
父组件没有给我第二个礼物
</div>
</div>
VUE里的watcher
写法1:
watch: {
'fetchAgain': 'shouldFetch' // shouldFetch是函数名
}
写法2:
watch: {
fetchAgain: function (newVal, oldVal) { // 一个参数,则为newVal
this.shouldFetch() // 这里不能用箭头函数,否则this不是这个vue实例!而是全局,此时this包括整个生命周期/data等等,不单单是methods
}
}
position: sticky
- 因为fixed是相对于浏览器窗口的,那如果希望相对于父容器,怎么做?
1/给子元素设定position: sticky;
2/同时也设定top/right/bottom/left四值其中之一,这个叫阈(yu)值。(比如设定top: 20px)
【注意】
这些值是相对于“最近的块级父元素的顶部“(有时候是相对于浏览器窗口顶部?);
3/随着滚动,子元素会慢慢上升。(此时是相对定位position: relative)
【注意】
若top的值 < 子元素height,子元素才会慢慢上升;否则会保持不动!(刚好可以利用这一个特性,来达到将fixed的参照物设定为最近的块级父元素顶部)
4/当上升到 子元素和“最近的块级父元素“顶部的距离 < 20px时,不再上升(此时是固定定位position: fixed)
position: fixed失效
要使用position: fixed的子元素突然失效了?
- 原因:父元素带有transform: translate(…)
vscode常用插件
然后在setting.json(首选项 -- 设置),添加如下:
"workbench.colorTheme": "One Dark Pro",
"workbench.iconTheme": "material-icon-theme",
"material-icon-theme.folders.theme": "classic",
"material-icon-theme.folders.color": "#42a5f5",
"editor.detectIndentation": false,
"editor.tabSize": 4,
"stylelint.configOverrides": {
"ignoreFiles": "src/common/css/**"
},
"eslint.autoFixOnSave": true,
"eslint.validate": [
"javascript",
"javascriptreact",
{
"language": "html",
"autoFix": true
},
{
"language": "vue",
"autoFix": true
}
]
for…of 和for…in 和v-for=” …of/in”
v-for=”…of/in”都是一样的,只是…of的写法更贴近于js的of迭代器
var arr = [1, 9, 9, 6]
var obj = {
name: 'heshiyu',
age: 21
}
var items = [{
name: 'heshiyu',
age: 21
}, {
name: 'caozuoxiao',
age: 22
}]
Tables | for…of | for…in |
---|---|---|
arr | 1 9 9 6 | 0 1 2 3 |
obj | 报错! | name age |
items | {name: ‘heshiyu’, age: 21} {name: ‘caozuoxiao’, age: 21} | 0 1 |
Tables | v-for…of |
---|---|
arr | 1 9 9 6 |
obj | heshiyu 21 |
items | {name: ‘heshiyu’, age: 21} {name: ‘caozuoxiao’, age: 21} |
数组的includes( )
[1, 9, 9, 6].includes(9) // true
数组的find( )
[1, 9, -9, 6].find((n) => {
return n < 0
}) // -9
// 数组中的每个成员都一次执行这个方法,直到 第一个 返回true的就结束
// 类似的方法findIndex( )是一样的,只是返回第一个返回true的下标
Array.of()
可以将给的参数变成一个数组
rest参数 和 扩展运算符…
rest参数用于获取函数的多余参数
- 是将一个个参数转成一个真正的数组
- 是放在函数的参数部分的
- 和arguments的区别在于:arguments是一个类似数组的对象,而rest参数是真正的一个数组,它里面装着多余的参数
function add (arr, ...rest) {
rest.forEach((item) => {
arr.push(item)
})
}
扩展运算符…
- 和rest参数是逆过来的,是将一个数组转成一个个参数
// 用例0:深复制数组
var arr1 = [1, 2]
var arr2 = [...arr1]
// 用例1:
function add (x, y) {
// 这里只需要2个参数
return (x + y)
}
var nums = [1, 9]
add(...nums)
// 用例2:将一个数组直接添加到另一个数组的尾部
var arr1 = [0, 1, 2];
var arr2 = [3, 4, 5];
arr1.push(...arr2);
短路赋值
function log (x, y) {
y = y || 'World';
console.log(x, y);
}
log('Hello');// "Hello World"
log('Hello', false);// "Hello World"
log('Hello', '');// "Hello World"
短路赋值因为false或者'',而忽视了我们设定的y的默认值
ES5解决方法:
if (typeof y === 'undefined') {
y = 'World'
}
ES6解决方法:
function log (x, y = 'World') {
}
// 若参数里 y = 表达式求值,那每次都会重新计算一次!
Math中常用:
1/去除小数:
Math.trunc(1.23) // 1
2/进一
Math.ceil(0.35) // 1
3/判断正负零:
Math.sigh(1.23)
// 正:+1
// 负:-1
// 0:0
// -0:-0
// 其他值:NaN
RegExp
实例化正则对象:
var regex = new RegExp(/a/, ‘i’)
flags:
i 不区分大小写
g 全局匹配
正则对象的方法(使用圆括号进行组匹配)
var regex = new RegExp(/(\d{4})-(\d{2})-(\d{2})/, ‘ig’)
var str = ‘my name is Heshiyu’
exec(str)
regex.exec(str) // 返回一个数组arr
// arr[0] :str本身
// arr[1] :第一个组匹配
// arr[2] :第二个组匹配
// arr[3] :第三个组匹配
字符串对象 & 正则表达式
var str = ‘my name is Heshiyu’
match(pattern) 找很多人
str.match(regex) // 返回第一个(若flags有g,则匹配到所有)匹配到的字(没有下标),否则返回null
search(pattern) 找到一个就行
str.search(regex) // 返回一个(onlyOne)匹配到的下标,否则返回-1
replace(pattern) 替换
str.replace(regex) // 返回一个字符串,它是第一个(若flags有g,则匹配到所有)匹配到的字符被替换后,所形成的
模版字符串
用法:
let name = 'heshiyu'
`Hello! My name is ${name}`
注意:
- 反印号里的所有 空格 和 换行 都会被保留,要去除,就用trim()
- ${函数也行}
新增的3个检验字符串的方法:
ES5:
indexOf
var str = "Hello world!"
str.indexOf('world'); // 返回第一个字符匹配的所在位置
ES6:(都是返回true/false)
includes(数组也有这个方法)
var str = "Hello world!"
str.includes('world'); // 是否包含。。。字符串
startsWith
var str = "Hello world!"
str.startsWith('world'); // 是否以。。。开头
endsWith
var str = "Hello world!"
str.endsWith('world'); // 是否以。。。结尾
解构赋值的用途
1/交换变量的值(不引入第三个变量)
var x0 = 0, x1 = 1;
[x0, x1] = [x1, x0];
2/提取json值
var myJson = {
name: 'heshiyu',
age: 21
}
let {name, age} = myJson;
name // 'heshiyu'
age // 21
3/导入模块的指定方法
const { func1, func2 } = require(“source-map”);
(对象的)解构赋值中的默认值
var {x = 3} = {};
x // 3
var {x, y = 5} = {x: 1};
x // 1
y // 5
var {x: y = 3} = {};
y // 3
var {x: y = 3} = {x: 5};
y // 5
(对象的)解构赋值
// 这是“右对象的属性名“ 与 “左对象的变量名“同名时
let {foo, bar} = {foo: 'fo', bar: 'ba'};
// 这是“右对象的属性名“ 与 “左对象的变量名“不同名时
let {foo: hsy, bar} = {foo: 'fo', bar: 'ba'};
// 真正被赋值的是后者(hsy),而不是前者(foo)。
(数组的)解构赋值中的默认值
let [x = 1] = [];
x // 1
let [x = 1] = [undefined];
x // 1
let [x = 1] = [null];
x // null
// 只有当数组里的元素严格等于undefined(===),x的默认值才会生效
(数组的)解构赋值
解构不成功(如下面的middle),将会变成undefined
...tail 如果没有东西,会变成[]
// 代码
var [head, middle, ...tail] = [1]
head;// 1
middle;// undefined
tail;// []
在es5中,window顶层对象的属性 = 全局变量
var name = 'heshiyu';
window.name; // 'heshiyu'
将一个对象冻结:Object.freeze({…})
这样以后,这个对象就不能再添加新的属性了;
也不能更改属性的值
const保证的不是值不变,而是地址不变;
这个地址不变,如果是一个对象/数组,那对象/数组里装的东西可以变呀
暂时性死区
var tmp = 123;
if (true) {
console.log(tmp); // ReferenceError
let tmp = 3;
}
// 因为这里tmp在代码块里,用了let声明,所以不会有变量提升;
// 而且变量tmp会绑定这个块级作用域,从一开始就形成封闭作用域(暂时性死区),听不到外面的tmp变量
// 也不可以重复声明
打印全局i
var a = [];
for (var i=0; i<10; i++) {
a[i] = function () {
console.log(i);
}
}
a[1]();// 10
// a[i]只记住了要打印,但是到最后这个i是全局变量,导致是i=10
配Snippets
首选项 -- 用户代码片段 -- 可以选javascript.json或者css.json
注意!如果是用了sass,那就是scss.json
VS Code的setting.json
快捷键 command ,
获取url后缀(文件格式)
downloadRename (url) {
var postfix = /\.[^\.]+$/.exec(url)
return postfix;
},
改了host后,vue-cli出现 invalid host header
在webpack.dev.conf.js中的devServer字段,增加:
disableHostCheck: true
判断用户是否手机,重定向
if(navigator.userAgent.match(/(iPhone|iPod|Android|ios)/i)){
window.location.href = 'http://wap-sight.netease.com';
}
引入vux提示:压缩体积过大,请升级到vux-loader最新版本
解决办法:将vue-loader降至12.2.2
将axios加入到Vue实例的原型链中
① 在main.js中导入axios
import axios from ‘axios’
② 加入到Vue的原型中
Vue.prototype. axios=axios③用的时候直接this. a x i o s = a x i o s ③ 用 的 时 候 直 接 t h i s . axios即可(也可以取其他名字)
//get用法:
this.$axios.get(url)
.then(function(res){
})
.catch(function(error){
})
//post用法:
var querystring = require('querystring');//Json数据查询器
this.$axios.post(url, querystring({是一个json参数对象}))
.then(function(res){
})
.catch(function(error){
})
自己写个hover菜单显示子菜单
最终功能图:
① 在某一个li下面,再加多一层div
② 这层div的css样式(划线两个为主要):
③ 给他的父li增加这个hover样式,即可
在vue-cli项目中引入node-sass
① 先装一个淘宝镜像:
npm install -g cnpm --registry=https://registry.npm.taobao.org
② 通过淘宝镜像去安装node-sass
cnpm i sass-loader node-sass --save-dev
③ 在webpack.base.conf.js加入这个rule
{
test: /\.scss$/,
loaders: ["style", "css", "sass"]
},
④ 在.vue里的style这样写,即可
<style lang="scss" type="text/css" scoped>
vue-cli在ios调试失败
原因:Can’t find variable: SockJS
因为webpack(3.6.0)的热加载需要websocket来通知浏览器,而SockJS是一个必须的库。对于google它有很多种方式解决,而safari却没有。
解决办法:在webpack.config.js中devtool将“eval-source-map“改为“inline-source-map“即可
webpack
- webpack的热加载是通过websocket通知浏览器来实现的
path.resolve
//webpack.config.js
const path = require('path')
path: path.resolve(__dirname, 'dist')
//这样,后半部分就拼接成了一个字符串:'项目路径/dist'
//相当于:
//cd __dirname
//cd dist
// pwd