一、选择除第一个元素外的所有元素
<div class="father">
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
<div class="child"></div>
</div>
.father .child:not(:first-child) {
}
二、flex:1的原理
flex
是 flex-grow
、flex-shrink
、flex-basis
的缩写
flex-grow 属性用于设置或检索弹性盒子的扩展比率
flex-basis 属性用于设置或检索弹性盒伸缩基准值
flex-shrink的默认值为1,如果没有显示定义该属性,将会自动按照默认值1在所有因子相加之后计算比率来进行空间收缩。
<div class="parent">
<div class="item-1"></div>
<div class="item-2"></div>
<div class="item-3"></div>
</div>
<style type="text/css">
.parent { display: flex; width: 600px; }
.parent > div { height: 100px; }
.item-1 { width: 140px; flex: 2 1 0%; background: blue; }
.item-2 { width: 100px; flex: 2 1 auto; background: darkblue; }
.item-3 { flex: 1 1 200px; background: lightblue; }
</style>
-
主轴上父容器总尺寸为 600px
-
子元素的总基准值是:0% + auto + 200px = 300px,其中
0% 即 0 宽度
auto 对应取主尺寸即 100px
-
故剩余空间为 600px - 300px = 300px
-
伸缩放大系数之和为: 2 + 2 + 1 = 5
-
剩余空间分配如下:
item-1 和 item-2 各分配 2/5,各得 120px
item-3 分配 1/5,得 60px
-
各项目最终宽度为:
- item-1 = 0% + 120px = 120px
- item-2 = auto + 120px = 220px
- item-3 = 200px + 60px = 260px
-
当 item-1 基准值取 0% 的时候,是把该项目视为零尺寸的,故即便声明其尺寸为 140px,也并没有什么用,形同虚设
-
而 item-2 基准值取
auto
的时候,根据规则基准值使用值是主尺寸值即 100px,故这 100px 不会纳入剩余空间
三、vue中,vue.set、vue.use和.sync修饰符的作用
vue.set:给对象新增属性
解决“当vue的data里边声明或者已经赋值过的对象或者数组(数组里边的值是对象)时,向对象中添加新的属性,如果更新此属性的值,不会更新视图”的问题
vue.use: 使用插件(前提:插件有暴露install方法)
// 调用 `MyPlugin.install(Vue)`
Vue.use(MyPlugin)
new Vue({
// ...组件选项
})
.sync:对一个 prop 进行“双向绑定”。
父组件:
<text-document v-bind:title.sync="doc.title"></text-document>
子组件:
this.$emit('update:title', newTitle)
四、写出执行结果
var a = 3
function fn(a) {
console.log(a) // ƒ a() {)
var a = 2
function a() {
}
console.log(a) // 2
}
fn(1)
五、微信小程序的理解
1.运行环境
根据微信官方的说明,wa的运行环境有3个平台,IOS的webkit(苹果开源的浏览器内核),Android的X5(QQ浏览器内核),开发时用的nw.js(C++实现的web转桌面应用);
2.本质
本质就是富单页面web应用。首先,一个微信小程序应用程序就是一个单页面应用,所有的页面渲染和事件处理,都在一个页面内进行,但与传统的webapp不同的是,它也可以做得很丰富,就像native app一样,可以调用原生的各种接口,像网络状态、罗盘,重力,拨打电话
3.页面的脚本逻辑是在JsCore中运行,JsCore是一个没有窗口对象的环境
六、多维数组转一维数组
let arr = [1, 2, {
a: 2
}, true, 3, 4, 5, [6, 7, 8, [9, 10, 11, 12, [13, 14, 15, 16]]]]
let newArr = [] // 存放转化后的一维数组
function arrConversion(arr) {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
arrConversion(arr[i])
} else {
newArr.push(arr[i])
}
}
}
arrConversion(arr)
console.log(newArr)
//(18) [1, 2, {…}, true, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
七、使用Array.isArray和instanceof数组之间的区别
isArray是一个ES5方法,所以不支持旧的浏览器,但它可靠地确定一个对象是否是一个数组。当不存在 Array.isArray() ,可以用 Object.prototype.toString.call() 实现
instanceof只检查Array.prototype是否在对象的[[Prototype]]链上。它在跨框架检查数组时失败,因为用于实例的Array构造函数可能与用于测试的数组不同。
八、写出执行结果
console.log(111)
p()
.then(result => {
console.log(`p result:${result}`)
})
.catch(err => {
console.log(`p err :${err}`)
})
p1()
.then(result => {
console.log(`p1 result:${result}`)
})
.catch(err => {
console.log(`p1 err :${err}`)
})
p2()
.then(result => {
console.log(`p2 result:${result}`)
})
.catch(err => {
console.log(`p2 err :${err.message}`)
})
function p() {
return new Promise((resolve, reject) => {
console.log(222)
setTimeout(() => {
console.log('async in p')
reject('err in p')
console.log('content after p reject')
}, 200)
})
}
function p1() {
return new Promise((resolve, reject) => {
console.log(333)
setTimeout(() => {
console.log('async in p1')
resolve('resolev in p1')
console.log('content after p1 resolve')
}, 250)
})
}
function p2() {
return new Promise((resoleve, reject) => {
console.log(444)
setTimeout(() => {
console.log('async in p2')
return reject(new Error('p2error'))
console.log('content after p2 return')
}, 300)
})
}
九、BFC和FFC
1.BFC
BFC(Block Formatting Contexts)直译为"块级格式化上下文"。
Block Formatting Contexts就是页面上的一个隔离的渲染区域,容器里面的子元素不会在布局上影响到外面的元素,反之也是如此。
如何产生BFC?
-
float的值不为none。
-
overflow的值不为visible。
-
position的值不为relative和static。
-
display的值为table-cell, table-caption, inline-block中的任何一个。
那BFC一般有什么用呢?
比如常见的多栏布局,结合块级别元素浮动,里面的元素则是在一个相对隔离的环境里运行。
bfc 解决什么样的问题?
bfc区域不与float 区域重叠。
双边距问题。
计算bfc高度,浮动元素也参与计算。
子集浮动元素,父级overflow:hidden 具有高度
2.FFC
FFC(Flex formatting contexts):自适应格式上下文。
display
值为flex
或者inline-flex
的元素将会生成自适应容器
(flex container),可惜这个牛逼的属性只有谷歌和火狐支持,不过在移动端也足够了,至少safari和chrome还是OK的,毕竟这俩在移动端才是王道。
Flex Box由伸缩容器和伸缩项目组成。通过设置元素的 display属性为 flex 或 inline-flex 可以得到一个伸缩容器。设置为 flex 的容器被渲染为一个块级元素,而设置为 inline-flex 的容器则渲染为一个行内元素。伸缩容器中的每一个子元素都是一个伸缩项目。伸缩项目可以是任意数量的。伸缩容器外和伸缩项目内的一切元素都不受影响。简单地说,Flexbox 定义了伸缩容器内伸缩项目该如何布局。
十、eventLoop
Event Loop
在JavaScript
中,任务被分为两种,一种宏任务(MacroTask
)也叫Task
,一种叫微任务(MicroTask
)。
MacroTask(宏任务)
script
全部代码、setTimeout
、setInterval
、setImmediate
(浏览器暂时不支持,只有IE10支持,具体可见MDN
)、I/O
、UI Rendering
。
MicroTask(微任务)
Process.nextTick(Node独有)
、Promise
、Object.observe(废弃)
、MutationObserver
(具体使用方式查看这里)
浏览器中的Event Loop
Javascript
有一个 main thread
主线程和 call-stack
调用栈(执行栈),所有的任务都会被放到调用栈等待主线程执行。
JS调用栈
JS调用栈采用的是后进先出的规则,当函数执行的时候,会被添加到栈的顶部,当执行栈执行完成后,就会从栈顶移出,直到栈内被清空。
同步任务和异步任务
Javascript
单线程任务被分为同步任务和异步任务,同步任务会在调用栈中按照顺序等待主线程依次执行,异步任务会在异步任务有了结果后,将注册的回调函数放入任务队列中等待主线程空闲的时候(调用栈被清空),被读取到栈内等待主线程的执行。
事件循环的进程模型
- 选择当前要执行的任务队列,选择任务队列中最先进入的任务,如果任务队列为空即
null
,则执行跳转到微任务(MicroTask
)的执行步骤。 - 将事件循环中的任务设置为已选择任务。
- 执行任务。
- 将事件循环中当前运行任务设置为null。
- 将已经运行完成的任务从任务队列中删除。
- microtasks步骤:进入microtask检查点。
- 更新界面渲染。
- 返回第一步。
执行进入microtask检查点时,用户代理会执行以下步骤:
- 设置microtask检查点标志为true。
- 当事件循环
microtask
执行不为空时:选择一个最先进入的microtask
队列的microtask
,将事件循环的microtask
设置为已选择的microtask
,运行microtask
,将已经执行完成的microtask
为null
,移出microtask
中的microtask
。 - 清理IndexDB事务
- 设置进入microtask检查点的标志为false
十一、webpack中loader和plugin的概念理解
对于loader,它就是一个转换器,将A文件进行编译形成B文件,这里操作的是文件,比如将A.scss或A.less转变为B.css,单纯的文件转换过程;
对于plugin,它就是一个扩展器,它丰富了wepack本身,针对是loader结束后,webpack打包的整个过程,它并不直接操作文件,而是基于事件机制工作,会监听webpack打包过程中的某些节点,例如
run:开始编译
make:从entry开始递归分析依赖并对依赖进行build
build-moodule:使用loader加载文件并build模块
normal-module-loader:对loader加载的文件用acorn编译,生成抽象语法树AST
program:开始对AST进行遍历,当遇到require时触发call require事件
seal:所有依赖build完成,开始对chunk进行优化(抽取公共模块、加hash等)
optimize-chunk-assets:压缩代码
emit:把各个chunk输出到结果文件
通过对节点的监听,从而找到合适的节点对文件做适当的处理。
十二、不用input,实现vmodel
使用v-model的时候,vue会绑定组件的value属性,在自定义组件上使用v-model,然后浏览器审查元素,就会发现组件上做了一个vue属性。
如果在组件做出修改的话,就可以直接发射一个input的事件,把对应的值弹出到外面,就实现了双向绑定
// 父组件
<template>
<div id="app">
<HelloWorld v-model="msg" />
<h1 style="color:green">{{msg}}</h1>
<button @click="test()">ok</button>
</div>
</template>
<script>
import HelloWorld from "./components/HelloWorld.vue";
export default {
name: "app",
components: {
HelloWorld
},
data() {
return {
msg: 2
};
},
methods: {
test() {
this.msg -= 1;
}
}
};
</script>
// 子组件
<template>
<div class="hello">
<h1 v-bind:title="value" @click="close()">{{ value }}</h1>
</div>
</template>
<script>
export default {
name: "HelloWorld",
props: {
value: Number
},
data() {
return {
};
},
methods: {
close() {
this.num+=1;
this.$emit("input", this.value+1);
}
}
};
</script>