盒子由:content、padding、border、margin四部分组成。
盒子模型有两种:
标准盒模型怪异盒模型标准和怪异模型的转换: 1.box-sizing:content-box; 标准盒模型 2.box-sizing:border-box; 怪异盒模型 3.box-sizing:inherit; 规定应从父元素继承 box-sizing 属性的值。
解决问题:父子边距重叠、兄弟边距重叠
1.父级边距重叠可以把父元素设置为BFC(overflow:hidden) 2.同级边距重叠可通过添加空元素或伪类元素,设置overflow:hidden;
1.可以用来自适应布局 2.可以清除浮动 3.解决垂直边距重叠
答:清除浮动主要是为了解决,父元素因为子级元素浮动引起的内部高度为0的问题
清除浮动的几种方式:
注: zoom(IE专有属性)可解决ie6,ie7浮动问题
用法:
.clearfix:after{/*伪元素是行内元素 正常浏览器清除浮动方法*/ content: ""; display: block; height: 0; clear:both; visibility: hidden; } .clearfix{ *zoom: 1;/*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/ }用法:
.father{ border: 1px solid black; *zoom: 1; /*ie6清除浮动的方式 *号只有IE6-IE7执行,其他浏览器不执行*/ } .clearfix:after,.clearfix:before{ content: ""; display: block; clear: both; }子元素代码: position: absolute; left: 50%; top: 50%; margin-left: -100px; margin-top: -100px;
每个函数都有一个prototype属性,被称为显示原型
每个实例对象都会有_ _proto_ _属性,其被称为隐式原型
每一个实例对象的隐式原型_ _proto_ _属性指向自身构造函数的显式原型prototype
每个prototype原型都有一个constructor属性,指向它关联的构造函数。
获取对象属性时,如果对象本身没有这个属性,那就会去他的原型__proto__上去找,如果还查不到,就去找原型的原型,一直找到最顶层(Object.prototype)为止。Object.prototype对象也有__proto__属性值为null。
注意:Object是属于原型链的顶层,所有构造函数的的prototype都指向 Object.prototype
变量作用域:就是一个变量可以使用的范围。
注意: es6作用域,只适用于const,let
注:所有的自由变量的查找,是在函数定义的地方,向上级作用域查找 不是在执行的地方!!!
自由变量向上级作用域一层一层查找,直到找到为止,最高找到全局作用域,就形成了作用域链。
var声明的变量,function声明的函数存在变量提升 let const 不会变量提升
隐藏数据 做一个简单的缓存工具
// 闭包隐藏数据,只提供 API function createCache() { const num=100 const data = {} // 闭包中的数据,被隐藏,不被外界访问 return { num:num, set: function (key, val) { data[key] = val }, get: function (key) { return data[key] } } } const c = createCache() console.log(c.num)//num此时就作为c私有属性 c.set('a', 100) //set此时作为c的私有方法 console.log( c.get('a') )1.什么是闭包?
①函数嵌套函数; ②内部函数可以直接访问外部函数的内部变量或参数; ③变量或参数不会被垃圾回收机制回收。
2.闭包优点?
①变量长期驻扎在内存中; ②避免全局变量的污染; ③私有成员的存在。
3.闭包的应用场景?
①函数作为参数被传递 ②函数作为返回值被返回 ③实际应用(隐藏数据):为什么说隐藏数据了呢,因为普通用户只能通过get、set等api对数据进行查看和更改等操作,没法对data直接更改,达到所谓隐藏数据的效果;jquery就利用了这一特性,必须调用$.ajax()才能访问内部属性方法。 封装功能时(需要使用私有的属性和方法), 函数防抖、函数节流 单例模式
4.闭包的缺点?
常驻内存,增大内存的使用量,使用不当会造成内存泄漏。
5大调用场景:
普通函数、 对象方法、 call apply bind class 箭头函数
注意:this取什么值,是在执行时确认的,定义时无法确认
全局下,普通函数fn1执行,相当于window执行了fn1函数,所以this是window call apply bind可以修改this
function fn1(this={x:100}){ fn1,call({x:100}) ==> console.log(this) }bind也可以修改,但是多了一步执行。
对象方法中的this,指向当前对象(因为当前对象执行了方法)。 setTimeout函数中的this,相当于普通函数中的this,因为setTimeout触发的函数执行,并不是外部对象执行的。 setTimeout中函数是箭头函数,this为当前对象。因为箭头函数中的this始终是父级上下文中的this.
es6 class中的this,当前实例本身。
普通函数中调用,this指向window 对象方法中调用,this指向当前对象 call apply bind中调用, this指向被传入的对象 class中的方法中调用, this指向实例对象 箭头函数,this就是父级上下文中的this
宏任务包括:setTimeout setInterval Ajax DOM事件 微任务:Promise async/await 微任务比宏任务的执行时间要早
1)所有的同步任务都在主线程上执行,行成一个执行栈。 2)除了主线程之外,还存在一个任务列队,只要异步任务有了运行结果,就在任务列队中植入一个时间标记。 3)主线程完成所有任务(执行栈清空),就会读取任务列队,先执行微任务队列在执行宏任务队列。 4)重复上面三步。
只要主线程空了,就会读取任务列队,这就是js的运行机制,也被称为 event loop(事件循环)。
1.主线程上宏任务、微任务执行顺序
console.log('---start---');//第一轮主线程 setTimeout(() => { console.log('setTimeout'); // 将回调代码放入个宏任务队列,第二轮宏任务执行 }, 0); new Promise((resolve, reject) => { console.log('---Promise第一轮微任务同步执行---');//第一轮微任务同步执行 resolve() }).then(()=>{ console.log('Promise.then实例成功回调执行'); // 将回调代码放入微任务队列,第一轮宏任务执行完后立即执行 }); console.log('---end---');//第一轮主线程结束执行顺序:主线程 >> 主线程上创建的微任务 >> 主线程上创建的宏任务
2.宏任务中包含微任务
// 宏任务队列 1 setTimeout(() => { // 宏任务队列 2.1 console.log('timer_1'); setTimeout(() => { // 宏任务队列 3 console.log('timer_3') }, 0) new Promise(resolve => { resolve() console.log('new promise') }).then(() => { // 微任务队列 1 console.log('promise then') }) }, 0) setTimeout(() => { // 宏任务队列 2.2 console.log('timer_2') }, 0) console.log('========== Sync queue ==========')执行顺序:主线程 >> 主线程上的宏任务队列1 >> 宏任务队列1中创建的微任务
事件委托,又名事件代理。事件委托就是利用事件冒泡,就是把子元素的事件都绑定到父元素上。如果子元素阻止了事件冒泡,那么委托也就没法实现了。
提高性能,减少了事件绑定,从而减少内存占用
我们经常遇到vue中v-for一个列表,列表的每一项都绑定了@click处理事件。我们都知道绑定这么多监听,从性能方面来说是不太好的。那我们我们可以通过把每个item的click事件委托给父元素的形式来实现。
获取item元素中title值为edit的id
//html <table @click="edit"> <tr v-for="item in list"> <td>{{item.name}}</td> ... <td> <button :data-id="item.id" title="eidt">编辑</button> </td> </tr> </table> //js edit (event){ if(event.target.title == "edit"){ //如果点击到了edit let id = evenr.target.dataset.id; //拿着id参数执行着相关的操作 this.$router.push({path:'/detail',query:{id:id}}) } }1、Promise对象的状态不受外界影响
1)pending 初始状态
2)fulfilled 成功状态
3)rejected 失败状态
Promise 有以上三种状态,只有异步操作的结果可以决定当前是哪一种状态,其他任何操作都无法改变这个状态
2、Promise的状态一旦改变,就不会再变,任何时候都可以得到这个结果,状态不可以逆,只能由 pending变成fulfilled或者由pending变成rejected
Promise接受一个「函数」作为参数,该函数的两个参数分别是resolve和reject。这两个函数就是就是「回调函数」
resolve函数的作用:在异步操作成功时调用,并将异步操作的结果,作为参数传递出去;
reject函数的作用:在异步操作失败时调用,并将异步操作报出的错误,作为参数传递出去。
then()方法
then 方法就是把原来的回调写法分离出来,在异步操作执行完后,用链式调用的方式执行回调函数。
而 Promise 的优势就在于这个链式调用。我们可以在 then 方法中继续写 Promise 对象并返回,然后继续调用 then 来进行回调操作。
可有两个参数,第一个是成功 resolve 调用的方法,第二个是失败 reject 调用的方法
1.方便级联调用:即调用依次发生的场景;
2.同步代码编写方式: Promise使用then函数进行链式调用,一直点点点,是一种从左向右的横向写法;async/await从上到下,顺序执行,就像写同步代码一样,更符合代码编写习惯;
3.多个参数传递: Promise的then函数只能传递一个参数,虽然可以通过包装成对象来传递多个参数,但是会导致传递冗余信息,频繁的解析又重新组合参数,比较麻烦;async/await没有这个限制,可以当做普通的局部变量来处理,用let或者const定义的块级变量想怎么用就怎么用,想定义几个就定义几个,完全没有限制,也没有冗余工作;
4.同步代码和异步代码可以一起编写: 使用Promise的时候最好将同步代码和异步代码放在不同的then节点中,这样结构更加清晰;async/await整个书写习惯都是同步的,不需要纠结同步和异步的区别,当然,异步过程需要包装成一个Promise对象放在await关键字后面;
5.async/await是对Promise的优化: async/await是基于Promise的,是进一步的一种优化,不过在写代码时,Promise本身的API出现得很少,很接近同步代码的写法;
async主要来处理异步的操作,
一、箭头函数是匿名函数,不能作为构造函数,不能使用new 二、箭头函数不绑定arguments,取而代之需要用展开运算符解决…解决 三、箭头函数不绑定this,会捕获其所在的上下文的this值,作为自己的this值 四、箭头函数通过 call() 或 apply() 方法调用一个函数时,只传入了一个参数,对 this 并没有影响。 五、箭头函数没有原型属性
var声明的变量存在变量提升 let和const不存在变量提升
let和const存在暂时性死区。即只要块级作用域内存在let命令,它所声明的变量就“绑定”(binding)这个区域,不再受外部的影响。
总之,暂时性死区的本质就是,只要一进入当前作用域,所要使用的变量就已经存在了,但是不可获取,只有等到声明变量的那一行代码出现,才可以获取和使用该变量。
var允许重复声明变量。 let和const在同一作用域不允许重复声明变量。
var不存在块级作用域。 let和const存在块级作用域。
var和let可以。 const声明一个只读的常量。一旦声明,常量的值就不能改变。const声明的变量不得改变值,这意味着,const一旦声明变量,就必须立即初始化,不能留到以后赋值。
我用vue开发的所有项目,都是采用组件化的思想开发的。一般我在搭建项目的时候,会创建一个views目录和一个commen目录和一个feature目录,views目录中放页面级的组件,commen中放公共组件(如:head(公共头组件),foot(公共底部组件)等),feature目录内放功能组件(如:swiper(轮播功能组件),tabbar(切换功能组件)、list(上拉加载更多功能组件))
首先,组件可以提升整个项目的开发效率。能够把页面抽象成多个相对独立的模块,解决了我们传统项目开发:效率低、难维护、复用性低等问题。
使用Vue.extend方法创建一个组件,然后使用Vue.component方法注册组件。但是我们一般用脚手架开发项目,每个 .vue单文件就是一个组件。在另一组件import 导入,并在components中注册,子组件需要数据,可以在props中接受定义。而子组件修改好数据后,想把数据传递给父组件。可以采用emit方法。
具体实现:父组件通过 import 引入子组件,并注册,在子组件标签上添加要传递的属性,子组件通过 props 接收,接收有两种形式一是通过数组形式[‘要接收的属性’ ],二是通过对象形式{ }来接收,对象形式可以设置要传递的数据类型和默认值,而数组只是简单的接收
具体实现: 子组件通过通过绑定事件触发函数, 在其中设置this.e m i t ( ‘ 要 派 发 的 自 定 义 事 件 ’ , 要 传 递 的 值 ) ,emit 中有两个参数一是要派发的自定义事件,第二个参数是要传递的值
方法一:通过 event bus 实现
具体实现:创建一个空的 vue 并暴露出去,这个作为公共的 bus,即当作两个组件的桥梁,在两个兄弟组件中分别引入刚才创建的bus,在组件 A 中通过 bus.e m i t ( ’ 自 定 义 事 件 名 ’ , 要 发 送 的 值 ) 发 送 数 据 ,在组件B中通过bus.on(‘自定义事件名‘,function(v) { //v 即为要接收的值 })接收数据
1.定义:Vuex是一个专为Vue.js应用程序开发的状态管理模式。Vuex的状态存储是响应式的:就是当你的组件使用到了这个Vuex的状态,一旦它改变了,所有关联的组件都会自动更新相对应的数据,它采用集中式储存管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
2.使用场景:在我们开发一个中大型项目时,这时就用到了Vuex,因为在组件中有很多兄弟组件之间的通信,很繁琐。这样的话我们就把数据都存放在Vuex中,A1、A2、A3组件需要数据的话都去Vuex里面去拿,这样的话就不用组件之间的通信了
3.优点:在state中定义了一个数据之后,可以在任何一个组件里进行获取、进行修改、并且你的修改可以得到全局的响应变更。
4.运行机制 在组件中通过dispath派发actions,然后在actions中通过context.commit提交到mutations,在mutations中完成对store的修改。store中的数据只能由mutations来修改
5.核心: ①state: 存储数据的地方,类似一个仓库 ②mutations:同步操作,只有mutations才可以修改state中的数据 ③actions:异步操作,其实就是调用mutations里面的方法。 ④module:面对复杂的应用程序,当管理的状态比较多时;我们需要将vuex的store对象分割成模块(modules)。模块化 modeA, modeB,modeC ⑤getters:是state的计算属性。
hash模式原理
history模式的原理