笔记
V-ON绑定事件 V-BIND绑定属性
Network中可以查看当前发起的请求
XHR这个标签出现在Chrome浏览器的开发者工具Network选项卡中
XHR类型即通过XMLHttpRequest方法发送的请求即AJAX请求
外部JS引入当前Vue实例 函数中传this指向就好了
forEach没有返回值要有返回值的话用map
git checkout -b dev origin/dev 建立分支并且从远程拉取
APP的组件生命周期与小程序有出入
scroll view 有滑动时间并把scrollTop返回给scroll view 滑动会有抖动
页面滑动最好用
Console.log() 一个对象 浏览器显示出来的是最后结果 如果其中属性是有异步函数返回的,你将读不到那个属性
CCS3 中的Calc()函数
await等的是Promise对象
通过data-xx 绑定一个值 可以通过event获取
z-index只有在设置了position为relative,absolute,fixed时才会有效。
z-index的“从父原则”。设置了z-index的元素要在相同的根元素下菜有效
微信小程序的Console.log()可以字符串加数据也会显示对象
如果需要在页面进入时设置标题,可以在onReady
内执行,以避免被框架内的修改所覆盖。如果必须在onShow
内执行需要延迟一小段时间
小程序 组件CSS优先 APP 页面CSS优先
transition 触发条件是当属性变化的时候触发
闭包是指有权访问另外一个函数作用域中的变量的函数。可以理解为(能够读取另一个函数作 用域的变量的函数)
src用于替代这个元素,而href用于建立这个标签与外部资源之间的关系。
hasOwnProperty(property)
判断对象是否有某个特定的属性。必须用字符串指定该属性。(例如,o.hasOwnProperty(“name”))
IsPrototypeOf(object)
判断该对象是否为另一个对象的原型。
//重写setData使uniapp支持setData写法
import Mixin from “./common/mixins.js”;
Vue.mixin(Mixin);
Nodejs用require 和 export.moudle 其他用Import 和export
require 是赋值过程并且是运行时才执行,
import 是解构过程并且是编译时执行。
require可以理解为一个全局方法,就意味着可以在任何地方执行。
而import必须写在文件的顶部。
require的性能相对于import稍低,因为require是在运行时才引入模块并且还赋值给某个变量,
而import只需要依据import中的接口在编译时引入指定模块所以性能稍高
子传父通过自定义事件,emit 触发自定义事件传值,再通过自定义事件绑定一个函数进行取值
parseInt(‘01’);
var obj = {};
function searchResult(){
clearTimeOut(obj.g);
obj.g = setTimeout(function(){
//这里发送请求
},1000)
}
var pre = new Date();
function trol(fn,delay){
return function () {
var now = new Date();
if(now-pre >= delay){
fn();
pre = new Date();
}
}
在连续的操作中,无论进行了多长时间,只有某一次的操作后在指定的时间内没有再操作,这一次才被判定有效
规定时间内,只触发一次,可以通过设置immediate
来决定触发的时机在这个时间的开始,还是结束的时候执行。
filters: {
ellipsis (value) {
if (!value) return ''
if (value.length > 32) {
return value.slice(0,32) + '...'
}
return value
}
}
//enum 枚举
enum Gender {
Male = 0,
Female = 1,
}
let i: { name: string, gender: Gender }
i = {
name: '孙悟空', gender: Gender.Male//0
}
设备 | rpx换算px (屏幕宽度/750) | px换算rpx (750/屏幕宽度) |
---|---|---|
iPhone5 | 1rpx = 0.42px | 1px = 2.34rpx |
iPhone6 | 1rpx = 0.5px | 1px = 2rpx |
iPhone6 Plus | 1rpx = 0.552px | 1px = 1.81rpx |
1 rpx = 屏幕宽度/750 px
给元素设置catchtouchmove=“notmove” notmove为空的返回函数就可以阻止滚动,只有真机测试的时候才有反应,鼠标滚动仍可以滚动,uniapp没有catchtouchmove,可用@touchmove.stop.prevent代替
当tap或者click时,点击后事件默认是冒泡,当你添加.stop的时候当事件触发对应的stop后不再传播
position:fixed会在ScollView失效,Canvas也不能用position:fixed
相当于Vuex里的computed属性
getters: {
// Getter 接受 state 作为其第一个参数
weekDate: state => {
return moment(state.date).format('dddd');
}
}
不但如此,Getter 还会将 store.getters 对象暴露出去,你可以以属性的形式访问这些值:
console.log(store.getters.weekDate)
我们可以很容易地在任何组件中使用它:
computed: {
weekDate () {
return this.$store.getters.weekDate
}
}
因为Data是函数的话他可以有return然后返回一个对象,而每个对象都是独立的作用域的,相同类型的组件的data就可以区分开来
components:{
List:()=> import(’./List’)
}
import Vue from ‘vue’
import VueRouter from ‘vue-router’
Vue.use(VueRouter)
const router = new VueRouter({
routes: [
{ path: ‘/login’, component: () => import(’@/views/login/index.vue’) },
{ path: ‘/home’, component: () => import(’@/views/home/home.vue’) }
]
export default router
1、props 和 e m i t 。 父 组 件 向 子 组 件 传 递 数 据 是 通 过 p r o p s 传 递 的 , 子 组 件 传 递 给 父 组 件 是 通 过 emit。父组件向子组件传递数据是通过props传递的,子组件传递给父组件是通过 emit。父组件向子组件传递数据是通过props传递的,子组件传递给父组件是通过emit触发事件来做到的。
2、$parent 和 $children 获取单签组件的父组件和当前组件的子组件。
3、$attrs 和 l i s t e n e r s A − > B − > C 。 V u e 2.4 开 始 提 供 了 listeners A -> B -> C。Vue2.4开始提供了 listenersA−>B−>C。Vue2.4开始提供了attrs和$listeners来解决这个问题。
4、父组件中通过 provide 来提供变量,然后在子组件中通过 inject 来注入变量。(官方不推荐在实际业务中适用,但是写组件库时很常用。)
5、$refs 获取组件实例。
6、envetBus 兄弟组件数据传递,这种情况下可以使用事件总线的方式。
7、vuex 状态管理。
三者公共点都是隐藏。不同点:
Vue中methods声明方式与函数的声明方式
methods:{
*// 在此时定义方法,方法之间使用逗号分隔*
方法名:function(){}
});
函数声明方式
声明 : function first(){};
调用:first()
函数表达式声明方式
声明: var second=function(){};
调用:second()
好像不需要事先设置生命周期
onPageScroll(e) {
this.scrollTop = e.scrollTop;
},
回到顶部函数
uni.pageScrollTo({
scrollTop: 0, duration: 300
});
组件引用的JS是相对于组件的位置
通常单独使用left、right、top、bottom均无效,需要在使用绝对定位CSS position样式才能生效。
一般left和right在一个样式是只能使用其一,不能left和right都设置,要么使用left就不使用right,要么使用right就不使用left,如果left和right均使用将会出现兼容问题,一个对象设置了靠左left多少距离,自然右边距离自然就有了所以无需设置左边。
相同道理,top和bottom对一个对象只能使用其一,不然会出现逻辑兼容问题。譬如一个人让你往左走,一个人让你往右走,同时发出往左往右走这个时候你也不好判断往那边走。
在这里我先介绍component标签: 它是Vue内置的标签,它的用途是可以动态绑定我们的组件,根据数据不同更换不同的组件.
比如:这个效果效果:
<body>
<div id="app">
<component :is="who"></component>
<button @click="changeComponent">changeComponent</button>
</div>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script>
let componentA={
template:`I am componentA`
}
let componentB={
template:`I am componentB`
}
let componentC={
template:`I am componentC`
}
let app = new Vue({
el: '#app',
data:{
who:'componentB'
},
components:{
"componentA":componentA,
"componentB":componentB,
"componentC":componentC
},
methods: {
changeComponent(){
if(this.who=="componentA"){
this.who="componentB"
}
else if(this.who=="componentB"){
this.who="componentC"
}else{
this.who="componentA"
}
}
},
})
</script>
</body>
1、vm.$on( event, callback )
监听当前实例上的自定义事件。事件可以由vm.$emit触发。回调函数会接收所有传入事件触发函数的额外参数。
2、vm.$emit( event, […args] )
触发当前实例上的事件。附加参数都会传给监听器回调,如果没有参数,形式为vm.$emit(event)
3、vm.$off( [event, callback] )
移除自定义事件监听器。
如果没有提供参数,则移除所有的事件监听器;
如果只提供了事件,则移除该事件所有的监听器;
如果同时提供了事件与回调,则只移除这个回调的监听器。
c组件需要用,在c引用
https://segmentfault.com/a/1190000017155151
中的方法虽然引入的时候方便了,但是computed中定义的代码还是很多,而这时候vuex又给我们提供了更简便的方法mapState方法
import {mapState} from 'vuex'
export default {
name: 'home',
computed: mapState(['nickname','age','gender'])
}
mapState(['nickname','age','gender']) //映射哪些字段就填入哪些字段
这一句代码就相当于下面这些
nickname(){return this.$store.state.nickname}
age(){return this.$store.state.age}
gender(){return this.$store.state.gender}
跟mapState、mapGetters一样
methods:{
...mapMutations(['addAge'])
}
mapMutations([‘addAge’])这一句就相当于下面的代码
addAge(payLoad){
this.$store.commit('addAge',payLoad)
}
2.1 getters相当于vue中的计算属性,通过getters进一步处理,得到我们想要的值,而且允许传参,第一个参数就是state
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
state: { //存放状态
nickname:'Simba',
firstname:'张',
lastname:'三丰',
age:20,
gender:'男',
money:1000
},
getters:{
realname(state){
return state.firstname+state.lastname
},
money_us(state){
return (state.money/7).toFixed(2)
}
},
mutations: {},
actions: {},
modules: {}
})
vue部分
computed: { //computed是不能传参数的
valued(){
return this.value/7
},
...mapGetters(['realname','money_us'])
不过我还有个问题就是,官方文档都是把属性state,放入computed里面去,我想vuex本身就是响应式的,能追踪到变化的,我完全可以在需要用的到地方去使用,也就是this.$store.state.count,为什么还要放在computed下呢,纯粹是因为这样可以缩减代码量吗?还是有别的原因,望指教
你如果只是想单独使用 this.$store.state.count 的话,那直接用或者mapState一下就好了。computed 一般是需要收集多个依赖,或者做一些额外的计算时使用。
谢回答,可是mapSate不也放入在computed下了嘛,我对vuex属性放在computed下的初步认识就是缩写代码量,_!
嗯,如果仅单独使用的话 是的
*1*|***0***join()
join,就是把数组转换成字符串,然后给他规定个连接字符,默认的是逗号( ,)
书写格式:join(" "),括号里面写字符串 (“要加引号”),
var arr = [1,2,3];
console.log(arr.join()); // 1,2,3
console.log(arr.join("-"));
var arr = [1,2,3];
console.log(arr.join()); // 1,2,3
console.log(arr.join("-")); // 1-2-3
console.log(arr); // [1, 2, 3](原数组不变)
*2*|***0***push()和pop()
push(): 把里面的内容添加到数组末尾,并返回修改后的长度。
pop():移除数组最后一项,返回移除的那个值,减少数组的length。
书写格式:arr.push(" "),括号里面写内容 (“字符串要加引号”),
书写格式:arr.pop( )
var arr = ["Lily","lucy","Tom"];
var count = arr.push("Jack","Sean");
console.log(count); // 5
console.log(arr); // ["Lily", "lucy", "Tom", "Jack", "Sean"]
var item = arr.pop();
console.log(item); // Sean
console.log(arr); // ["Lily", "lucy", "Tom", "Jack"]
*3*|***0***shift() 和 unshift() (和上面的push,pop相反,针对第一项内容)
**shift():删除原数组第一项,并返回删除元素的值;如果数组为空则返回undefined 。
**
unshift:将参数添加到原数组开头,并返回数组的长度 。
书写格式:arr.shift(" "),括号里面写内容 (“字符串要加引号”),
var arr = ["Lily","lucy","Tom"];
var count = arr.unshift("Jack","Sean");
console.log(count); // 5
console.log(arr); //["Jack", "Sean", "Lily", "lucy", "Tom"]
var item = arr.shift();
console.log(item); // Jack
console.log(arr); // ["Sean", "Lily", "lucy", "Tom"]
*4*|***0***sort()
sort():将数组里的项从小到大排序
书写格式:arr.sort( )
var arr1 = ["a", "d", "c", "b"];
console.log(arr1.sort()); // ["a", "b", "c", "d"]
sort()方法比较的是字符串,没有按照数值的大小对数字进行排序,要实现这一点,就必须使用一个排序函数
function sortNumber(a,b)
{
return a - b
}
arr = [13, 24, 51, 3]; console.log(arr.sort()); // [13, 24, 3, 51]
console.log(arr.sort(sortNumber)); // [3, 13, 24, 51](数组被改变)
*5*|***0***reverse()
reverse():反转数组项的顺序。
书写格式:arr.reverse( )
var arr = [13, 24, 51, 3];
console.log(arr.reverse()); //[3, 51, 24, 13]
console.log(arr); //[3, 51, 24, 13](原数组改变)
*6*|***0***concat()
concat() :将参数添加到原数组中。这个方法会先创建当前数组一个副本,然后将接收到的参数添加到这个副本的末尾,最后返回新构建的数组。在没有给 concat()方法传递参数的情况下,它只是复制当前数组并返回副本。
书写格式:arr.concat(),括号里面写内容 (“字符串要加引号”),
var arr = [1,3,5,7];
var arrCopy = arr.concat(9,[11,13]);
console.log(arrCopy); //[1, 3, 5, 7, 9, 11, 13]
console.log(arr); // [1, 3, 5, 7](原数组未被修改)
*7*|***0***slice()
slice():返回从原数组中指定开始下标到结束下标之间的项组成的新数组。slice()方法可以接受一或两个参数,即要返回项的起始和结束位置。在只有一个参数的情况下, slice()方法返回从该参数指定位置开始到当前数组末尾的所有项。如果有两个参数,该方法返回起始和结束位置之间的项——但不包括结束位置的项。
书写格式:arr.slice( 1 , 3 )
var arr = [1,3,5,7,9,11];
var arrCopy = arr.slice(1);
var arrCopy2 = arr.slice(1,4);
var arrCopy3 = arr.slice(1,-2);
var arrCopy4 = arr.slice(-4,-1);
console.log(arr); //[1, 3, 5, 7, 9, 11](原数组没变)
console.log(arrCopy); //[3, 5, 7, 9, 11]
console.log(arrCopy2); //[3, 5, 7]
console.log(arrCopy3); //[3, 5, 7]
console.log(arrCopy4); //[5, 7, 9]
arrCopy只设置了一个参数,也就是起始下标为1,所以返回的数组为下标1(包括下标1)开始到数组最后。
arrCopy2设置了两个参数,返回起始下标(包括1)开始到终止下标(不包括4)的子数组。
arrCopy3设置了两个参数,终止下标为负数,当出现负数时,将负数加上数组长度的值(6)来替换该位置的数,因此就是从1开始到4(不包括)的子数组。
arrCopy4中两个参数都是负数,所以都加上数组长度6转换成正数,因此相当于slice(2,5)。
*8*|***0***splice()
splice():删除、插入和替换。
删除:指定 2 个参数:要删除的第一项的位置和要删除的项数。
书写格式:arr.splice( 1 , 3 )
插入:可以向指定位置插入任意数量的项,只需提供 3 个参数:起始位置、 0(要删除的项数)和要插入的项。
书写格式:arr.splice( 2,0,4,6 )
替换:可以向指定位置插入任意数量的项,且同时删除任意数量的项,只需指定 3 个参数:起始位置、要删除的项数和要插入的任意数量的项。插入的项数不必与删除的项数相等。
书写格式:arr.splice( 2,0,4,6 )
var arr = [1,3,5,7,9,11];
var arrRemoved = arr.splice(0,2);
console.log(arr); //[5, 7, 9, 11]
console.log(arrRemoved); //[1, 3]
var arrRemoved2 = arr.splice(2,0,4,6);
console.log(arr); // [5, 7, 4, 6, 9, 11]
console.log(arrRemoved2); // []
var arrRemoved3 = arr.splice(1,1,2,4);
console.log(arr); // [5, 2, 4, 4, 6, 9, 11]
console.log(arrRemoved3); //[7]
*9*|***0***indexOf()和 lastIndexOf()
indexOf():接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的开头(位置 0)开始向后查找。
书写格式:arr.indexof( 5 )
*lastIndexOf:接收两个参数:要查找的项和(可选的)表示查找起点位置的索引。其中, 从数组的末尾开始向前查找。*
书写格式:arr.lastIndexOf( 5,4 )
var arr = [1,3,5,7,7,5,3,1];
console.log(arr.indexOf(5)); //2
console.log(arr.lastIndexOf(5)); //5
console.log(arr.indexOf(5,2)); //2
console.log(arr.lastIndexOf(5,4)); //2
console.log(arr.indexOf("5")); //-1
*10*|***0***forEach()
forEach():对数组进行遍历循环,对数组中的每一项运行给定函数。这个方法没有返回值。参数都是function类型,默认有传参,参数分别为:遍历的数组内容;第对应的数组索引,数组本身。
书写格式:arr.forEach()
var arr = [1, 2, 3, 4, 5];
arr.forEach(function(x, index, a){
console.log(x + '|' + index + '|' + (a === arr));
});
// 输出为:
// 1|0|true
// 2|1|true
// 3|2|true
// 4|3|true
// 5|4|true
*11*|***0***map()
map():指“映射”,对数组中的每一项运行给定函数,返回每次函数调用的结果组成的数组。
书写格式:arr.map()
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.map(function(item){
return item*item;
});
console.log(arr2); //[1, 4, 9, 16, 25]
*12*|***0***filter()
filter():“过滤”功能,数组中的每一项运行给定函数,返回满足过滤条件组成的数组。
书写格式:arr.filter()
var arr = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
var arr2 = arr.filter(function(x, index) {
return index % 3 === 0 || x >= 8;
});
console.log(arr2); //[1, 4, 7, 8, 9, 10]
*13*|***0***every()
every():判断数组中每一项都是否满足条件,只有所有项都满足条件,才会返回true。
书写格式:arr.every()
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.every(function(x) {
return x < 10;
});
console.log(arr2); //true
var arr3 = arr.every(function(x) {
return x < 3;
});
console.log(arr3); // false
*14*|***0***some()
some():判断数组中是否存在满足条件的项,只要有一项满足条件,就会返回true。
书写格式:arr.some()
var arr = [1, 2, 3, 4, 5];
var arr2 = arr.some(function(x) {
return x < 3;
});
console.log(arr2); //true
var arr3 = arr.some(function(x) {
return x < 1;
});
console.log(arr3); // false
handleChooseImg
用按钮图片来增加一个可替换图片
https://www.jianshu.com/p/84b727a4b58a
在事件处理程序中调用 event.preventDefault()
或 event.stopPropagation()
是非常常见的需求。尽管我们可以在方法中轻松实现这点,但更好的方式是:方法只有纯粹的数据逻辑,而不是去处理 DOM 事件细节。
为了解决这个问题,Vue.js 为 v-on
提供了事件修饰符。之前提过,修饰符是由点开头的指令后缀来表示的。
.stop
.prevent
.capture
.self
.once
.passive
...
...
https://zhuanlan.zhihu.com/p/72777951
PS:没用到的组件没加载到的时候要注意销毁事件 例子: this.Bus.$off(‘makeCover’, this.handleMakeCover);
所谓的后背内容,其实就是slot的默认值,有时我没有在父组件内添加内容,那么 slot就会显示默认值,如:
//子组件 : (假设名为:ebutton)
<template>
<div class= 'button'>
<button> </button>
<slot> 这就是默认值 </slot>
</div>
</template>
有时候,也许子组件内的slot不止一个,那么我们如何在父组件中,精确的在想要的位置,插入对应的内容呢? 给插槽命一个名即可,即添加name属性。
//子组件 : (假设名为:ebutton)
<template>
<div class= 'button'>
<button> </button>
<slot name= 'one'> 这就是默认值1</slot>
<slot name='two'> 这就是默认值2 </slot>
<slot name='three'> 这就是默认值3 </slot>
</div>
</template>
父组件通过v-slot : name 的方式添加内容:
//父组件:(引用子组件 ebutton)
<template>
<div class= 'app'>
<ebutton>
<template v-slot:one> 这是插入到one插槽的内容 </template>
<template v-slot:two> 这是插入到two插槽的内容 </template>
<template v-slot:three> 这是插入到three插槽的内容 </template>
</ebutton>
</div>
</template>
当然 vue 为了方便,书写 v-slot:one 的形式时,可以简写为 #one
通过slot 我们可以在父组件为子组件添加内容,通过给slot命名的方式,我们可以添加不止一个位置的内容。但是我们添加的数据都是父组件内的。上面我们说过不能直接使用子组件内的数据,但是我们是否有其他的方法,让我们能够使用子组件的数据呢? 其实我们也可以使用v-slot的方式:
//子组件 : (假设名为:ebutton)
<template>
<div class= 'button'>
<button> </button>
<slot name= 'one' :value1='child1'> 这就是默认值1</slot> //绑定child1的数据
<slot :value2='child2'> 这就是默认值2 </slot> //绑定child2的数据,这里我没有命名slot
</div>
</template>
new Vue({
el:'.button',
data:{
child1:'数据1',
child2:'数据2'
}
})
//父组件:(引用子组件 ebutton)
<template>
<div class= 'app'>
<ebutton>
<template v-slot:one = 'slotone'>
{{ slotone.value1 }} // 通过v-slot的语法 将子组件的value1值赋值给slotone
</template>
<template v-slot:default = 'slottwo'>
{{ slottwo.value2 }} // 同上,由于子组件没有给slot命名,默认值就为default
</template>
</ebutton>
</div>
</template>
任务队列 事件循环
js主代码 setImmediate(Node) requestAnimationFrame(浏览器)
Process.nextTick放队列前 setImmediate 放队列后
此时需要注意,只有前一个队列完全清空后,才会执行下一个队列
http://www.ruanyifeng.com/blog/2012/06/sass.html
import Child from './Child'
import { toggle } from './mixins/toggle'
export default {
name: 'modal',
mixins: [toggle],
components: {
appChild: Child
}
}
//mixin
const hi = {
methods: {
sayHello: function() {
console.log('hello from mixin!')
}
},
mounted() {
this.sayHello()
}
}
//vue instance or component
new Vue({
el: '#app',
mixins: [hi],
methods: {
sayHello: function() {
console.log('hello from Vue instance!')
}
},
mounted() {
this.sayHello()
}
})
// Output in console
> hello from Vue instance!
> hello from Vue instance!
var obj = {a:1, b:2, c:3};
for (var prop in obj) {
console.log("obj." + prop + " = " + obj[prop]);
}
// Output:
// "obj.a = 1"
// "obj.b = 2"
// "obj.c = 3"
不难看出,for in循环遍历的是数组的键值(索引),而for of循环遍历的是数组的值。
for of不能遍历对象,除非使用迭代器或者使用Object.key处理这个对象
1.首先使用touch事件第一步肯定是要绑定touch事件
在html元素里绑定@touchstart=“….自己起名字…”
@touchmove=“….自起名字….”
@touchend=“…自己起名字…..”
touchstart会在你第一次触碰到它时候触发
touchmove就是你一直点着不松手的时候触发
touchend就是你的手刚刚移开的时候触发
这几个touch事件可以根据自己的需求进行绑定,绑定自己起的名字
然后在methods里面写自己绑定的名字的事件你要让他如何处理
而touch事件里面更包含了下面几个跟踪触摸的属性方便我们为了对应的效果进行使用
touches:表示当前跟踪的触摸操作的touch对象的数组。
targetTouches:特定于事件目标的Touch对象的数组。
changeTouches:表示自上次触摸以来发生了什么改变的Touch对象的数组。
每个Touch对象包含的属性如下。
clientX:触摸目标在视口中的x坐标。
clientY:触摸目标在视口中的y坐标。
identifier:标识触摸的唯一ID。
pageX:触摸目标在页面中的x坐标。
pageY:触摸目标在页面中的y坐标。
screenX:触摸目标在屏幕中的x坐标。
screenY:触摸目标在屏幕中的y坐标。
target:触目的DOM节点目标。
注意 mounted 不会承诺所有的子组件也都一起被挂载。如果你希望等到整个视图都渲染完毕,可以用 vm.$nextTick 替换掉 mounted
mounted: function () {
this.$nextTick(function () {
// Code that will run only after the
// entire view has been rendered
})
}
值更新了但DOM里面的节点的值还没更新完,如果你获取更新完后的DOM值的话要用nextTick
Vue2.0对于响应式数据的实现有一些不足:
vm.items[indexOfItem] = newValue
vm.items.length = newLength
性能问题,性能的代价和用户体验收益不成正比。
当你在使用一个引用值的时候,当你改变原来的值,还要实时响应引用中的data的话,如果你不用$set是不能实现实时响应的,可以用
that.$set(that.list,that.INDEX,res.msg[i]);
https://zhuanlan.zhihu.com/p/30078937
if(e.xundefined || e.yundefined)
{
this.pointStart = {
x: e.changedTouches[0].pageX,
y: e.changedTouches[0].pageY,
};
我们先来简单了解一下setTimeout延时器的运行机制。setTimeout会先将回调函数放到等待队列中,等待区域内其他主程序执行完毕后,按时间顺序先进先出执行回调函数。本质上是作用域的问题。
因此若是这样将不会得到想要的结果输出1.2.3.4.5,而会连续输出5个6。
for (var i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
解决方案1:闭包
使用闭包是很经典的一种做法:
for (var i=1; i<=5; i++) {
(function(j) {
setTimeout( function timer() {
console.log( j );
}, j*1000 );
})(i);
}
解决方案3:let
这里再来说一说使用es6的let来解决此问题:
for (let i=1; i<=5; i++) {
setTimeout( function timer() {
console.log( i );
}, i*1000 );
}
这个例子与第一个相比,只是把var更改成了let,可是控制台的结果却是依次输出1到5。
因为for循环头部的let不仅将i绑定到for循环中,事实上它将其重新绑定到循环体的每一次迭代中,确保上一次迭代结束的值重新被赋值。setTimeout里面的function()属于一个新的域,通过var定义的变量是无法传入到这个函数执行域中的,通过使用let来声明块变量能作用于这个块,所以function就能使用i这个变量了;这个匿名函数的参数作用域和for参数的作用域不一样,是利用了这一点来完成的。这个匿名函数的作用域有点类似类的属性,是可以被内层方法使用的。
获取系统信息同步接口。
同步返回参数说明
参数 | 说明 | 平台差异说明 |
---|---|---|
brand | 设备品牌 | App、微信小程序、百度小程序、字节跳动小程序、飞书小程序、QQ小程序 |
model | 设备型号 | 全平台支持。H5(3.1.10+)新增PC |
pixelRatio | 设备像素比 | |
screenWidth | 屏幕宽度 | |
screenHeight | 屏幕高度 | |
windowWidth | 可使用窗口宽度 | |
windowHeight | 可使用窗口高度 | |
windowTop | 可使用窗口的顶部位置 | App、H5 |
windowBottom | 可使用窗口的底部位置 | App、H5 |
statusBarHeight | 状态栏的高度 | 字节跳动小程序不支持 |
navigationBarHeight | 导航栏的高度 | 百度小程序 |
titleBarHeight | 标题栏高度 | 支付宝小程序 |
language | 应用设置的语言 | 字节跳动小程序不支持 |
version | 引擎版本号 | H5不支持 |
storage | 设备磁盘容量 | 支付宝小程序 |
currentBattery | 当前电量百分比 | 支付宝小程序 |
appName | 宿主APP名称 | 字节跳动小程序、飞书小程序 |
AppPlatform | App平台 | QQ小程序 |
host | 宿主平台 | 百度小程序 |
app | 当前运行的客户端 | 支付宝小程序 |
cacheLocation | 上一次缓存的位置信息 | 百度小程序 |
system | 操作系统版本 | |
platform | 客户端平台,值域为:ios 、android 、mac(3.1.10+) 、windows(3.1.10+) 、linux(3.1.10+) |
|
fontSizeSetting | 用户字体大小设置。以“我-设置-通用-字体大小”中的设置为准,单位:px | 微信小程序、支付宝小程序、百度小程序、QQ小程序 |
SDKVersion | 客户端基础库版本 | 支付宝小程序和H5不支持 |
swanNativeVersion | 宿主平台版本号 | 百度小程序 |
albumAuthorized | 允许微信使用相册的开关(仅 iOS 有效) | 微信小程序 |
cameraAuthorized | 允许微信使用摄像头的开关 | 微信小程序 |
locationAuthorized | 允许微信使用定位的开关 | 微信小程序 |
microphoneAuthorized | 允许微信使用麦克风的开关 | 微信小程序 |
notificationAuthorized | 允许微信通知的开关 | 微信小程序 |
notificationAlertAuthorized | 允许微信通知带有提醒的开关(仅 iOS 有效) | 微信小程序 |
notificationBadgeAuthorized | 允许微信通知带有标记的开关(仅 iOS 有效) | 微信小程序 |
notificationSoundAuthorized | 允许微信通知带有声音的开关(仅 iOS 有效) | 微信小程序 |
bluetoothEnabled | 蓝牙的系统开关 | 微信小程序 |
locationEnabled | 地理位置的系统开关 | 微信小程序 |
wifiEnabled | Wi-Fi 的系统开关 | 微信小程序 |
safeArea | 在竖屏正方向下的安全区域 | App、H5、微信小程序 |
safeAreaInsets | 在竖屏正方向下的安全区域插入位置(2.5.3+) | App、H5、微信小程序 |
deviceId | 设备 id | 非 App 端由 uni-app 框架生成并存储,清空 Storage 会导致改变 |
Tips
safeArea 的结构
参数 | 类型 | 说明 |
---|---|---|
left | Number | 安全区域左上角横坐标 |
right | Number | 安全区域右下角横坐标 |
top | Number | 安全区域左上角纵坐标 |
bottom | Number | 安全区域右下角纵坐标 |
width | Number | 安全区域的宽度,单位逻辑像素 |
height | Number | 安全区域的高度,单位逻辑像素 |
safeAreaInsets 的结构
参数 | 类型 | 说明 |
---|---|---|
left | Number | 安全区域左侧插入位置 |
right | Number | 安全区域右侧插入位置 |
top | Number | 安全区顶部插入位置 |
bottom | Number | 安全区域底部插入位置 |
Vue 实例属性 | 描述 | H5 | App端 | 微信小程序 | 说明 |
---|---|---|---|---|---|
vm.$data | Vue 实例观察的数据对象 详情 | √ | √ | √ | |
vm.$props | 当前组件接收到的 props 对象 详情 | √ | √ | √ | |
vm.$el | Vue 实例使用的根 DOM 元素 详情 | √ | x | x | |
vm.$options | 用于当前 Vue 实例的初始化选项 详情 | √ | √ | √ | |
vm.$parent | 父实例,如果当前实例有的话 详情 | √ | √ | √ | H5端 view 、text 等内置标签是以 Vue 组件方式实现,$parent 会获取这些到内置组件,导致的问题是 this.$parent 与其他平台不一致,解决方式是使用 this.$parent.$parent 获取或自定义组件根节点由 view 改为 div |
vm.$root | 当前组件树的根 Vue 实例 详情 | √ | √ | √ | |
vm.$children | 当前实例的直接子组件 详情 | √ | √ | √ | H5端 view 、text 等内置标签是以 Vue 组件方式实现,$children 会获取到这些内置组件,导致的问题是 this.$children 与其他平台不一致,解决方式是使用 this.$children.$children 获取或自定义组件根节点由 view 改为 div |
vm.$slots | 用来访问被插槽分发的内容 详情 | √ | x | √ | |
vm.$scopedSlots | 用来访问作用域插槽 详情 | √ | √ | √ | |
vm.$refs | 一个对象,持有注册过 ref attribute 的所有 DOM 元素和组件实例详情 | √ | √ | √ | 非H5端只能用于获取自定义组件,不能用于获取内置组件实例(如:view、text) |
vm.$isServer | 当前 Vue 实例是否运行于服务器 详情 | √ | √ | x | App端总是返回false |
vm.$attrs | 包含了父作用域中不作为 prop 被识别 (且获取) 的 attribute 绑定 详情 | √ | √ | x | 把父组件的所有data通过$attrs传到子组件中 |
vm.$listeners | 包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器 详情 | √ | √ | x | - |
实例方法 | 描述 | H5 | App端 | 微信小程序 | 说明 |
---|---|---|---|---|---|
vm.$watch() | 观察 Vue 实例上的一个表达式或者一个函数计算结果的变化 详情 | √ | √ | √ | |
vm.$set() | 这是全局 Vue.set 的别名 详情 | √ | √ | √ | |
vm.$delete() | 这是全局 Vue.delete 的别名 详情 | √ | √ | √ | |
vm.$on() | 监听当前实例上的自定义事件 详情 | √ | √ | √ | |
vm.$once() | 监听一个自定义事件,但是只触发一次 详情 | √ | √ | √ | |
vm.$off() | 移除自定义事件监听器 详情 | √ | √ | √ | |
vm.$emit() | 触发当前实例上的事件 详情 | √ | √ | √ | |
vm.$mount() | 手动地挂载一个未挂载的实例 详情 | √ | x | x | |
vm.$forceUpdate() | 迫使 Vue 实例重新渲染 详情 | √ | √ | √ | |
vm.$nextTick() | 将回调延迟到下次 DOM 更新循环之后执行 详情 | √ | √ | √ | |
vm.$destroy() | 完全销毁一个实例 详情 | √ | √ | √ | - |
Vue 指令 | 描述 | H5 | App端 | 微信小程序 | 说明 |
---|---|---|---|---|---|
v-text | 更新元素的 textContent 详情 | √ | √ | √ | |
v-html | 更新元素的 innerHTML 详情 | √ | √ | x | 微信小程序会被转成 rich-text |
v-show | 根据表达式之真假值,切换元素的 display CSS属性 详情 | √ | √ | √ | |
v-if | 根据表达式的值的 truthiness 来有条件地渲染元素 详情 | √ | √ | √ | |
v-else | 为 v-if 或者 v-else-if 添加“else 块” 详情 | √ | √ | √ | |
v-else-if | 表示 v-if 的“else if 块”。可以链式调用 详情 | √ | √ | √ | |
v-for | 基于源数据多次渲染元素或模板块 详情 | √ | √ | √ | |
v-on | 绑定事件监听器 详情 | √ | √ | √ | |
v-bind | 动态地绑定一个或多个 attribute,或一个组件 prop 到表达式 详情 | √ | √ | √ | |
v-model | 在表单控件或者组件上创建双向绑定 详情 | √ | √ | √ | |
v-pre | 跳过这个元素和它的子元素的编译过程 详情 | √ | √ | x | |
v-cloak | 这个指令保持在元素上直到关联实例结束编译 详情 | √ | x | x | |
v-once | 只渲染元素和组件一次 详情 | √ | √ | x | - |
特殊属性 | 描述 | H5 | App端 | 微信小程序 | 说明 |
---|---|---|---|---|---|
key | 主要用在 Vue 的虚拟 DOM 算法,在新旧 nodes 对比时辨识 VNodes 详情 | √ | √ | √ | |
ref | ref 被用来给元素或子组件注册引用信息 详情 | √ | √ | √ | 非 H5 平台只能获取 vue 组件实例不能获取到内置组件实例 |
is | 用于动态组件且基于 DOM 内模板的限制来工作 详情 | √ | √ | x | - |
内置组件 | 描述 | H5 | App端 | 微信小程序 | 说明 |
---|---|---|---|---|---|
component | 渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染 详情 | √ | √ | x | |
transition | 作为单个元素/组件的过渡效果 详情 | √ | x | x | |
transition-group | 作为多个元素/组件的过渡效果 详情 | √ | x | x | |
keep-alive | 包裹动态组件时,会缓存不活动的组件实例,而不是销毁它们 详情 | √ | x | x | |
slot | 作为组件模板之中的内容分发插槽 详情 | √ | √ | √ | - |
template | 并不是一个组件,它仅仅是一个包装元素,不会在页面中做任何渲染,只接受控制属性 详情 | √ | √ | √ | - |
onInit | 监听页面初始化,其参数同 onLoad 参数,为上个页面传递的数据,参数类型为 Object(用于页面传参),触发时机早于 onLoad | 百度小程序 | 3.1.0+ |
onLoad | 监听页面加载,其参数为上个页面传递的数据,参数类型为 Object(用于页面传参),参考示例 | ||
onShow | 监听页面显示。页面每次出现在屏幕上都触发,包括从下级页面点返回露出当前页面 | ||
onReady | 监听页面初次渲染完成。注意如果渲染速度快,会在页面进入动画完成前触发 | ||
onHide | 监听页面隐藏 | ||
onUnload | 监听页面卸载 | ||
onResize | 监听窗口尺寸变化 | App、微信小程序 |
https://www.jianshu.com/p/0c05faee0975
[PurgeCSS 中文文档]压缩CSS
promise有三种状态:pending/reslove/reject 。pending就是未决,resolve可以理解为成功,reject可以理解为拒绝。
async return出去的是一个Promise对象
await 等待的也必须是一个Promise对象
let n = await
let n = async function test(){
return 1
}
相当于
return new Promise((resolve)=>{
resolve(‘1’)
})
async function test(){
await this.preManhua();
this.cardRightIn=false;
this.cardLeftIn=true;
}
test();
let promiseDemo = new Promise((resolve, reject) => {
// code
resolve('success')
// code
reject('failed')
})
promiseDemo.then((result) => {
console.log(result)
}, (result) => {
console.log(result)
})
cookie#
Cookie 是一些数据,由服务器生成,发送给浏览器,一旦用户从该网站或服务器退出,Cookie 就存储在用户本地的硬盘上,下一次请求同一网站时会把该cookie发送给服务器。Cookie的作用就是用于解决“如何记录客户端的用户信息”。
可以使用 document.cookie 属性来创建 、读取、及删除 cookie。
创建 cookie :
document.cookie="username=Irelia;
为 cookie 添加一个过期时间(以 UTC 或 GMT 时间)。默认情况下,cookie 在浏览器关闭时删除:
document.cookie=“username=Irelia; expires=Thu, 19 Dec 2025 12:00:00 GMT”;
path 参数告诉浏览器 cookie 的路径。默认情况下,cookie 属于当前页面。
document.cookie=“username=Irelia; expires=Thu, 19 Dec 2025 12:00:00 GMT; path=/”;
Cookie的缺陷
MDN链接:https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/cookies
sessionStorage#
这个数据本质是存储在当前页面的内存中,为页面会话期间可用的每个给定源维护一个单独的存储区域(只要浏览器处于打开状态,包括页面重新加载和恢复)
方法:
loclaStorage#
1.存储的内容一般为5MB
2.不同浏览器不能共享数据。但是在同一个浏览器的不同窗口中可以共享数据
3.永久生效,他的数据是存储在硬盘上,并不会随着页面或者浏览器的关闭而清除,如果想清除,必须手 动清除
方法:
Cookie
cookie 是一个非常具体的东西,指的就是浏览器里面能永久存储的一种数据,仅仅是浏览器实现的一种数据存储功能。
cookie由服务器生成,发送给浏览器,浏览器把cookie以kv形式保存到某个目录下的文本文件内,下一次请求同一网站时会把该cookie发送给服务器。由于cookie是存在客户端上的,所以浏览器加入了一些限制确保cookie不会被恶意使用,同时不会占据太多磁盘空间,所以每个域的cookie数量是有限的。
Session
session 从字面上讲,就是会话。这个就类似于你和一个人交谈,你怎么知道当前和你交谈的是张三而不是李四呢?对方肯定有某种特征(长相等)表明他就是张三。
session 也是类似的道理,服务器要知道当前发请求给自己的是谁。为了做这种区分,服务器就要给每个客户端分配不同的“身份标识”,然后客户端每次向服务器发请求的时候,都带上这个“身份标识”,服务器就知道这个请求来自于谁了。至于客户端怎么保存这个“身份标识”,可以有很多种方式,对于浏览器客户端,大家都默认采用 cookie 的方式。
服务器使用session把用户的信息临时保存在了服务器上,用户离开网站后session会被销毁。这种用户信息存储方式相对cookie来说更安全,可是session有一个缺陷:如果web服务器做了负载均衡,那么下一个操作请求到了另一台服务器的时候session会丢失。
XSS(跨站脚本攻击)是指攻击者在返回的HTML中嵌入javascript脚本,为了减轻这些攻击,需要在HTTP头部配上,set-cookie:
httponly-这个属性可以防止XSS,它会禁止javascript脚本来访问cookie。
secure - 这个属性告诉浏览器仅在请求为https的时候发送cookie
1.变量提升只会提升变量名的声明,而不会提升变量的赋值初始化。
2.函数提升的优先级大于变量提升的优先级,即函数提升在变量提升之上。
记住这两句话,就可以从容不迫的撸代码了!
console.log(a); ``var` `a=1;``console.log(a); ``function` `a(){console.log(2);}``console.log(a); ``var` `a=3;``console.log(a); ``function` `a(){console.log(3);}``a();``console.log(a);
你知道执行结果吗?
其实,实际的执行顺序为:
function` `a(){alert(3);} `
`//第一步预解析:将 var a提升 但因为变量名与函数名相同,故function a()提升时将覆盖var a,又因为存在两个相同名称 的function函数,后写的将覆盖先写的,所以最后提升的只有function a(){alert(3);}` `console.log(a); ``//因为函数提升,所以打印的a为函数整体``a=1; ``//将1赋值给函数a,此时的a为一个变量,不再是函数``console.log(a); ``//故打印的为a赋的值``console.log(a);``a=3; ``//将a重新赋值3``console.log(a); ``//故打印结果为3``a(); ``//此时的a为一个变量,不再是一个函数,所以报错,js中一旦出现报错,后面的语句将不再运行,所以最后一个console.log不进行打印。``console.log(a);
结束!搞清楚这题,变量提升与函数提升你就搞懂啦!
1.额外标签法(在最后一个浮动标签后,新加一个标签,给其设置clear:both;)(不推荐)
优点:通俗易懂,方便
缺点:添加无意义标签,语义化差
2.父级添加overflow属性(父元素添加overflow:hidden)(不推荐)
优点:代码简洁
缺点:内容增多的时候容易造成不会自动换行导致内容被隐藏掉,无法显示要溢出的元素
3.使用after伪元素添加clear both清除浮动(推荐使用)
优点:符合闭合浮动思想,结构语义化正确
缺点:ie6-7不支持伪元素:after,使用zoom:1触发hasLayout.
4.使用before和after双伪元素清除浮动
优点:代码更简洁
缺点:用zoom:1触发hasLayout.
选择一个中心轴取出,设定两个下标 left 和right
如果left或者right的随便一个值 比如说 rifht 如果比中心轴大则不换下标 right往左移动 继续检测 如果比中心轴小则换到left位置 left向右移动 类似做法 到重合的时
候空的就把中心轴放进去 左右序列循环操作
########### 每个指令必须有分号结束。#################
#user administrator administrators; #配置用户或者组,默认为nobody nobody。
#worker_processes 2; #允许生成的进程数,默认为1
#pid /nginx/pid/nginx.pid; #指定nginx进程运行文件存放地址
error_log log/error.log debug; #制定日志路径,级别。这个设置可以放入全局块,http块,server块,级别以此为:debug|info|notice|warn|error|crit|alert|emerg
events {
accept_mutex on; #设置网路连接序列化,防止惊群现象发生,默认为on
multi_accept on; #设置一个进程是否同时接受多个网络连接,默认为off
#use epoll; #事件驱动模型,select|poll|kqueue|epoll|resig|/dev/poll|eventport
worker_connections 1024; #最大连接数,默认为512
}
http {
include mime.types; #文件扩展名与文件类型映射表
default_type application/octet-stream; #默认文件类型,默认为text/plain
#access_log off; #取消服务日志
log_format myFormat ‘ r e m o t e a d d r – remote_addr– remoteaddr–remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent $http_x_forwarded_for’; #自定义格式
access_log log/access.log myFormat; #combined为日志格式的默认值
sendfile on; #允许sendfile方式传输文件,默认为off,可以在http块,server块,location块。
sendfile_max_chunk 100k; #每个进程每次调用传输数量不能大于设定的值,默认为0,即不设上限。
keepalive_timeout 65; #连接超时时间,默认为75s,可以在http,server,location块。
upstream mysvr {
server 127.0.0.1:7878;
server 192.168.10.121:3333 backup; #热备
}
error_page 404 https://www.baidu.com; #错误页
server {
keepalive_requests 120; #单连接请求上限次数。
listen 4545; #监听端口
server_name 127.0.0.1; #监听地址
location ~*^.+$ { #请求的url过滤,正则匹配,~为区分大小写,~*为不区分大小写。
#root path; #根目录
#index vv.txt; #设置默认页
proxy_pass http://mysvr; #请求转向mysvr 定义的服务器列表
deny 127.0.0.1; #拒绝的ip
allow 172.18.5.54; #允许的ip
}
}
value=value.replace(/
/,'')
//构造函数
function TreeCode() {
//构造函数
let BiTree = function (ele) {
this.data = ele;
this.lChild = null;
this.rChild = null;
}
//方法
this.createTree = function () {
let biTree = new BiTree('A');
biTree.lChild = new BiTree('B');
biTree.rChild = new BiTree('C');
biTree.lChild.lChild = new BiTree('D');
biTree.lChild.lChild.lChild = new BiTree('G');
biTree.lChild.lChild.rChild = new BiTree('H');
biTree.rChild.lChild = new BiTree('E');
biTree.rChild.rChild = new BiTree('F');
biTree.rChild.lChild.rChild = new BiTree('I');
return biTree;
}
}
//前序遍历
function ProOrderTraverse(biTree) {
if (biTree == null) return;
console.log(biTree.data);
ProOrderTraverse(biTree.lChild);
ProOrderTraverse(biTree.rChild);
}
//中序遍历
function InOrderTraverse(biTree) {
if (biTree == null) return;
InOrderTraverse(biTree.lChild);
console.log(biTree.data);
InOrderTraverse(biTree.rChild);
}
//后续遍历
function PostOrderTraverse(biTree) {
if (biTree == null) return;
PostOrderTraverse(biTree.lChild);
PostOrderTraverse(biTree.rChild);
console.log(biTree.data);
}
let myTree = new TreeCode();
console.log(myTree.createTree());
console.log('前序遍历')
ProOrderTraverse(myTree.createTree());
console.log('中序遍历')
InOrderTraverse(myTree.createTree());
console.log('后续遍历')
PostOrderTraverse(myTree.createTree());
function Person(name, age) {
this.name = name;
this.age = age;
}
Person.prototype.sayHi = function() {
console.log("你好,我叫" + this.name);
};
let person = new Person("frank", 18);
let person2 = new Person("jack", 19);
http://code-ken.github.io/2016/07/13/jsonp-json-ajax/
核心配置
1、你要 http://e.dxy.net/api/test 你可以在本地调 localhost:8080/api/test,如axios.get('/api/test')
localhost:8080/api/test -> http://e.dxy.net/api/test
localhost:8080/bcma/api/test -> http://e.dxy.net/bcma/api/test
//vue-cli3.0 里面的 vue.config.js做配置
devServer: {
proxy: {
'/api': {
target: 'http://e.dxy.net', // 后台接口域名
ws: true, //如果要代理 websockets,配置这个参数
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, //是否跨域
}
}
}
2、当你调接口后端的命名没有统一给接口前加 /api 这类的标识,那么你可以自己加,也就是你可以在本地调 localhost:8080/api/test,如axios.get('/api/test'),而你要的目标接口是 http://e.dxy.net/test,你就可以用 pathRewrite,遇到 /api 就去找代理 http://e.dxy.net 并且把 /api 重写为 /
localhost:8080/api/test -> http://e.dxy.net/test
//vue-cli3.0 里面的 vue.config.js做配置
devServer: {
proxy: {
'/api': {
target: 'http://e.dxy.net', // 后台接口域名
ws: true, //如果要代理 websockets,配置这个参数
secure: false, // 如果是https接口,需要配置这个参数
changeOrigin: true, //是否跨域
pathRewrite:{
'^/api': '/'
}
}
}
}
https://zhuanlan.zhihu.com/p/139590941
vertical-align
优点:
缺点:
这个方法使用绝对定位的 div,把它的 top 设置为 50%,
优点:
缺点:
只需要简单地把 line-height 设置为那个对象的 height 值
优点:
缺点:
在
DOCTYPE html>
<html>
<head>
<script src="test1.js" defer="defer">script>
<script src="test2.js" defer="defer">script>
head>
<body>
body>
html>
说明:虽然<script> 元素放在了<head>元素中,但包含的脚本将延迟浏览器遇到html>标签后再执行。
HTML5规范要求脚本按照它们出现的先后顺序执行。在现实当中,延迟脚本并不一定会按照顺序执行。
defer属性只适用于外部脚本文件。支持 HTML5 的实现会忽略嵌入脚本设置的 defer属性。
异步脚本一定会在页面 load 事件前执行。
不能保证脚本会按顺序执行。
<html>
<head>
<script src="test1.js" async>script>
<script src="test2.js" async>script>
head>
<body>
body>
html>
async和defer一样,都不会阻塞其他资源下载,所以不会影响页面的加载。
缺点:不能控制加载的顺序
3.动态创建DOM方式
//这些代码应被放置在标签前(接近HTML文件底部)
<script type="text/javascript">
function downloadJSAtOnload() {
varelement = document.createElement("script");
element.src = "defer.js";
document.body.appendChild(element);
}
if (window.addEventListener)
window.addEventListener("load",downloadJSAtOnload, false);
else if (window.attachEvent)
window.attachEvent("onload",downloadJSAtOnload);
else
window.onload =downloadJSAtOnload;
</script>
4.使用jQuery的getScript()方法
$.getScript("outer.js",function(){//回调函数,成功获取文件后执行的函数
console.log("脚本加载完成")
});
5.使用setTimeout延迟方法
6.让JS最后加载
:class="{
'dp-object-wrapper-selected': currentLayer && item.id === currentLayer.id && !(this.editor.isPoster),
'dp-object-wrapper-editing': editor.editTextId === item.id,
}"
JavaScript 在需要用到布尔类型值的上下文中使用强制类型转换(Type Conversion )将值转换为布尔值,比如:在条件语句或者循环语句中
一,truthy
在javascript中,Truthy (真值)指的是在Boolean上下文中转换后的值为真的值。所有值都是真值,除非它们被定义为falsy(即除了 false
,0
,""
,null
,undefined
和 NaN
外)。
JavaScript中truthy值的例子 (通过 if 代码段将truthy值转换为true)
if (true)
if ({})
if ([])
if (42)
if ("foo")
if (new Date())
if (-42)
if (3.14)
if (-3.14)
if (Infinity)
if (-Infinity)
二,falsy
falsy(虚值)是在 Boolean上下文中已认定可转换为‘假‘的值.
JavaScript中falsy值的例子 (通过 if 代码段将falsy值转换为false):
1 if (false)
2 if (null)
3 if (undefined)
4 if (0)
5 if (NaN)
6 if ('')
7 if ("")
8 if (document.all)
异步组件
路由懒加载
图片懒加载
图片采用CDN分发
回流之后的重排重绘
减少DOM操作
减少请求次数
HTTP缓存
Keep-alive
可能是父级元素绑定着click事件,当点击上传时冒泡到父级元素,导致无反应。解决办法:
在 input file 外包一层元素,在该元素上阻止事件冒泡
也就是说事件往上冒泡触发了父元素覆盖了子元素的click
FileReader的使用方式非常简单,可以按照如下步骤创建FileReader对象并调用其方法:
1.检测浏览器对FileReader的支持
if(window.FileReader) {
var fr = new FileReader();
// add your code here
}
else {
alert(“Not supported by your browser!”);
}
FileReader 的实例拥有 4 个方法,其中 3 个用以读取文件,另一个用来中断读取。下面的表格列出了这些方法以及他们的参数和功能,需要注意的是 ,无论读取成功或失败,方法并不会返回读取结果,这一结果存储在 result属性中。
方法名 参数 描述
abort none 中断读取
readAsBinaryString file 将文件读取为二进制码
readAsDataURL file 将文件读取为 DataURL
readAsText file, [encoding] 将文件读取为文本
readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为 UTF-8。这个方法非常容易理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。
readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。
readAsDataURL:这是例子程序中用到的方法,该方法将文件读取为一段以 data: 开头的字符串,这段字符串的实质就是 Data URL,Data URL是一种将小文件直接嵌入文档的方案。这里的小文件通常是指图像与 html 等格式的文件。
FileReader 包含了一套完整的事件模型,用于捕获读取文件时的状态,下面这个表格归纳了这些事件。
事件 描述
onabort 中断时触发
onerror 出错时触发
onload 文件读取成功完成时触发
onloadend 读取完成触发,无论成功或失败
onloadstart 读取开始时触发
onprogress 读取中
代码复现
const isJPG = file.type === "image/jpeg";
const isLt2M = file.size / 1024 / 1024 < 2;
if (!isLt2M) {
this.$message.error("上传头像图片大小不能超过 2MB!");
}
let reader = new FileReader();
reader.readAsDataURL(file); // 这里是最关键的一步,转换就在这里
reader.onload = function () {
this.realImg = reader.result;
};
https://blog.csdn.net/xinruliushui/article/details/79085485
我们可以是使用字符串形式监听。
watch: {
'obj.a': {
handler(newName, oldName) {
console.log('obj.a changed');
},
immediate: true,
// deep: true
}
}
这样Vue.js才会一层一层解析下去,直到遇到属性a
,然后才给a
设置监听函数。
如果你希望 scoped 样式中的一个选择器能够作用得“更深”,例如影响子组件,你可以使用 >>> 操作符:
// 上述代码将会编译成:
.a[data-v-f3f3eg9] .b { /* … */ }
有些像 Sass 之类的预处理器无法正确解析 >>>。这种情况下你可以使用 /deep/ 或 ::v-deep 操作符取而代之——两者都是 >>> 的别名,同样可以正常工作。
有时我需要检测一个点击是发生在一个特定元素 el 的内部还是外部。这就是我通常使用的方法。
window.addEventListener('mousedown', e => {
// 获取被点击的元素
const clickedEl = e.target;
if (el.contains(clickedEl)) {
//在 "el "里面点击了
} else {
//在 "el "外点击了
}
});
排查CORS跨域规则是否设置正确,具体操作如下:
登录OSS管理控制台。
单击****Bucket列表****,单击目标Bucket,进入Bucket概览页面。
在左侧导航栏中选择权限管理>跨域设置,然后单击设置。
单击规则右侧的
编辑
,
进行
以下配置,配置规则及注意事项请参见
更多信息
。
*
,确认该配置项无误。如果设置成*
后可以成功上传,说明是之前的来源配置错误,请根据规则认真检查。*
,确认该配置无误。如果设置后可以正常调用,说明之前的允许 Headers配置错误,请根据规则认真检查。如果问题还是无法解决,请参见设置跨域规则后调用OSS时仍然报“No ‘Access-Control-Allow-Origin’”的错误。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-B6aOuqzA-1636443365383)(C:\Users\Lenovo\Desktop\image-20211109152003201.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-hDHv71a0-1636443365384)(C:\Users\Lenovo\Desktop\image-20211109152025509.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-kcrGwJUg-1636443365384)(C:\Users\Lenovo\Desktop\image-20211109152045103.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-nQVRwTYH-1636443365385)(C:\Users\Lenovo\Desktop\image-20211109152101247.png)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-9xl6MULV-1636443365385)(C:\Users\Lenovo\Desktop\image-20211109152129019.png)]