1、margin合并(兄弟元素)和塌陷(父子元素)
解决方法:
(1)position:absolute/fixed
(2)display:inline-block;
(3)float:left/right
(4)overflow:hidden
2、flex布局
a、设置在容器上面
flex-direction:row | row-reverse | column | column-reverse;
flex-wrap:nowrap | wrap | wrap-reverse;
flex-flow: || ; 简写 row noworp
justify-content: flex-start | flex-end | center | space-between | space-around;
align-items: flex-start | flex-end | center | baseline | stretch;
align-content:flex-start | flex-end | center | space-between | space-around | stretch;
b、设置在子容器上项目的属性
order
flex-grow:分发父容器剩余的空间,若子元素像素设定,则不生效
flex-shrink
flex-basis
flex
align-self
1、事件冒泡,事件捕获,事件委托
冒泡:由下到上
捕获:由泛到具体
阻止事件冒泡:e.stopPropagation()
阻止默认事件:e.preventDefault()
2、原型链
3、继承
4、创建对象
a、实例化一个构造函数经过的过程
A) 创建一个新对象
B) 构造函数的作用域赋给新对象(this指向新对象)
C) 执行构造函数中的代码(为新对象添加属性)
D) 返回新对象
5、数组降维
var arr1 = [1, 2, 3, [4, 5, [61, 62, 63]], 7, 8, 9]
//1、
arr1.flat(2) //不改变原数组
//2、
while (arr1.some(Array.isArray)) {
arr1 = [].concat(...arr1); //原数组进行改变
console.log('扩展运算符')
}
//3、递归
let newArr = []
function digui(arr) {
for (let i = 0; i < arr.length; i++) {
if (Array.isArray(arr[i])) {
digui(arr[i])
} else {
newArr.push(arr[i])
}
}
}
digui(arr1)
6、变量提升还是作用域提升来着
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);
7、深拷贝与浅拷贝
浅拷贝:只是引用地址,更改b同样会影响a
深拷贝:
1、JSON.parse(JSON.stringify(arr))
2、递归
function deepClone(obj) {
var newObj = obj instanceof Array ? [] : {};
if (typeof obj !== 'object') {
return obj;
} else {
for (var i in obj) {
newObj[i] = typeof obj[i] === 'object' ? deepClone(obj[i]) : obj[i];
}
}
return newObj;
}
8、数组去重
//1、
new Set()
//2、for循环
for (let i = 0; i < arr10.length; i++) {
if (arr11.indexOf(arr10[i]) === -1) {
arr11.push(arr10[i])
}
}
9、判断一个变量是不是数组
使用 Array.isArray 判断,如果返回 true, 说明是数组;
使用 instanceof Array 判断,如果返回 true, 说明是数组;
10、交换两个变量方法
1、解构赋值,2.借助第三个参数,3,利用object
1、三次握手和四次挥手
三次握手: 保证通讯双方的数据收发都无问题
四次挥手: 保证确认断开并且数据传输完毕后断开
2、浏览器状态码
百度可查
3、访问一个网站时浏览器的处理过程
1、DNS解析域名,查找网页所对应的IP地址
2、客户端和服务器通过三次握手建立TCP连接
3、发出HTTP请求
4、服务器处理请求并返回HTTP响应报文
5、浏览器解析渲染界面
6、四次握手释放TCP连接
4、移动端布局
https://www.jianshu.com/p/8178c5c976f2
1、模块化的理解:
模块是可组合、分解和更换的单元,是一种处理复杂系统分解成为更好的可管理模块的方式
2、与接口交互的数据类型:
json 和 xml和formData
1、对于MVVM的理解
Module代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View代表UI 组件,它负责将数据模型转化成UI 展现出来。
viewModule监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。
2、Vue的生命周期
beforeCreate(创建前) 在数据观测和初始化事件还未开始
created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$ e l el el属性还没有显示出来
beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
3、 Vue实现数据双向绑定的原理:Object.defineProperty()
vue的数据双向绑定 将MVVM作为数据绑定的入口,整合Observer观察者,Compile编译者和Watcher三者,通过Observer来监听自己的model的数据变化,通过Compile来解析编译模板指令(vue中是用来解析 {{}}),最终利用watcher搭起observer和Compile之间的通信桥梁,达到数据变化 —>视图更新;视图交互变化(input)—>数据model变更双向绑定效果。
4、vue如何自定义一个过滤器?
html代码:
<div id="app">
<input type="text" v-model="msg" />
{{msg| capitalize }}
div>
JS代码:
var vm=new Vue({
el:"#app",
data:{
msg:''
},
filters: {
capitalize: function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
}
}
})
//全局定义过滤器
Vue.filter('capitalize', function (value) {
if (!value) return ''
value = value.toString()
return value.charAt(0).toUpperCase() + value.slice(1)
})
//过滤器接收表达式的值 (msg) 作为第一个参数。capitalize 过滤器将会收到 msg的值作为第一个参数。
5、vue-cli如何新增自定义指令?
<div id="hook-arguments-example" v-demo:foo.a.b="message">div>
//1.创建局部指令
var app = new Vue({
el: '#app',
data: {
},
// 创建指令(可以多个)
directives: {
// 指令名称
dir1: {
inserted(el) {
// 指令中第一个参数是当前使用指令的DOM
console.log(el);
console.log(arguments);
// 对DOM进行操作
el.style.width = '200px';
el.style.height = '200px';
el.style.background = '#000';
}
}
}
})
//2.全局指令
Vue.directive('dir2', {
inserted(el) {
console.log(el);
}
})
//3.指令的使用
<div id="app">
<div v-dir1>div>
<div v-dir2>div>
div>
6、Vue组件间的参数传递
7、Vue中的常用修饰符
.passive、.capture 和 .once 这些事件修饰符
注:passive和prevent冲突,不能同时绑定在一个监听器上。
8、vue的混入mixin
来分发 Vue 组件中的可复用功能
9、路由守卫
10、v-if和v-show的异同和应用场景
一般来说,v-if 有更高的切换开销,而 v-show 有更高的初始渲染开销。因此,如果需要非常频繁地切换,则使用 v-show 较好;如果在运行时条件很少改变,则使用 v-if 较好。
11、Vue父组件调用子组件中的方法怎么做
利用ref
12、为什么vue中data必须是一个函数
类比引用数据类型
javascipt只有函数构成作用域(注意理解作用域,只有函数的{}构成作用域,对象的{}以及 if(){}都不构成作用域),data是一个函数时,每个组件实例都有自己的作用域,每个实例相互独立,不会相互影响
13、vuex
需要实现一个组件更改某个数据,多个组件自动获取更改后的数据进行业务逻辑处理,这时候使用vuex比较合适