前端知识点自我总结 三

    Vant 中的样式默认使用 px 作为单位,如果需要使用 rem 单位,推荐使用以下两个工具:

  • 一个页面从输入URL到页面加载完成,这个过程发生了啥什么

  • 浏览器查找域名对应的ip地址

  • 浏览器向web服务器发送一个http请求

  • 服务器301重定向

  • 浏览器跟踪重定向地址,请求另一个带www的网址

  • 服务器处理请求

  • 服务器返回一个HTTP响应

  • 浏览器进DOm树构建

  • 浏览器发送请求获取嵌套在html中的资源,比如图片,音频等

  • 浏览器显示完成页面

  • 浏览器发送异步请求

  •  new 操作符做了什么操作

  • 创建一个空对象,并且this变量引入该对象,同时还继承了函数的原型

  • 设置原型链 空对象指向构造函数的原型对象

  • 执行函数体 修改构造函数this指针指向空对象,并执行函数体

  • 判断返回值 返回对象就用该对象,没有的话就创建一个对象

js的基本数据类型

Number,String,Boolean,Null,Undefined,Symbol,bigInt

引用数据类型

Object,Array,Date,Function,RegExp

箭头函数和普通函数的区别

函数体内的this对象,就是定义时所在的对象,而不是使用时所在的对象

不可以当作构造函数,也就是说 不可以使用new命令,否则会抛出一个错误

不可以使用arguments对象,该对象在函数体内不存在,如果要用,可以用Rest参数代替

不可以使用yield命令,因此箭头函数不能用作Generator函数

如何解决跨域

jsonp跨域

document。domain+ifarame跨域

nodejs中间件代理跨域

后端在头部信息里面设置安全域名

Vue自定义指令-directive

vue中内置了很多的指令,比如v-model、v-show、v-html等,但是有时候这些功能并不能满足我们,或者我们想为元素附加一些特别的功能,这时候,我们就需要用到vue中一个强大的功能了-----自定义指令。

使用的地方:有的情况下,你仍然需要对普通Dom元素进行底层操作,这时候就会用到自定义指令

钩子函数:

inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

update: 所在组件的 VNode 更新时调用,但是可能发生在其子 VNode 更新之前。指令的值可能发生了改变,也可能没有。但是你可以通过比较更新前后的值来忽略不必要的模板更新。

componentUpdated:指令所在组件的 VNode 及其子 VNode 全部更新后调用。

unbind:只调用一次,指令与元素解绑时调用。

vue全局定义

使用<span v-指令名称> welcome </span> 也可以 v-指令名称='传递的参数'

定义:Vue.directive(指令名称,{指令钩子:功能函数}

 

<div id="root">
        <span v-red>welcome</span>
    </div>
    <script type="text/javascript">
        Vue.directive('red',{       //定义 ⬅⬅⬅
            inserted:function(el){  //钩子函数 ⬅⬅⬅
                el.style.background = 'red';
            }
        });
        var vm = new Vue({
       		el:"#root"
            data:{
            
            },
        })
    </script>

局部定义(vue-cli)

使用<div v-指令名称='传递的参数'></div> 传递参数可以根据功能需求进行操作

定义 : directives{指令名称:{钩子函数:功能函数}}

<template>
  <div class="hello">
  	<div v-test='name'></div>
  </div>
</template>
<script>

export default {
  data () {
    return {
     name:'userName',
    }
  },
  directives:{     //自定义指令 ⬅⬅⬅
  	test:{
	    inserted: function (el,binding) { //e为绑定元素,可以对其进行dom操作
	       console.log(binding)          //一个对象,包含很多属性属性(在下面)
	    },
	    bind: function (el, binding, vnode) {
		    el.innerHTML =binding.value
		  }
  	}
  },
  methods:{
 	... ...
  }
}
</script>

钩子函数中的参数

el:指令保定的元素,可以用来直接操作dom

binging:一个对象,包含以下property:

 ~name:指令名,不包括v-前缀

~value:指令的绑定只,例如: v-my-directive='1+1' 中 绑定值为2

~ oldValue: 指令绑定的前一个值,仅在update和componentUpdated钩子中可用。无论值是否改变都可用。

~ expression : 字符串形式的指令表达式。例如 v-my-directive=“1 + 1” 中,表达式为 “1 + 1”。
 ~ arg:传给指令的参数,可选。例如 v-my-directive:foo 中,参数为 “foo”。
~ modifiers:一个包含修饰符的对象。例如:v-my-directive.foo.bar 中,修饰符对象为 { foo: true, bar: true }。
vnode:Vue 编译生成的虚拟节点。
oldVnode:上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。

vuex是什么?vuex有哪几种属性?

vuex是vue框架中状态管理。
有五种,State、 Getter、Mutation 、Action、 Module
state: 基本数据(数据源存放地)
getters: 从基本数据派生出来的数据
mutations : 提交更改数据的方法,同步!
actions : 像一个装饰器,包裹mutations,使之可以异步。
modules : 模块化Vuex

route和router的区别

$route是“路由信息对象”,包括path,params,hash,query,fullPath,matched,name等路由信息参数。
$router是“路由实例”对象包括了路由的跳转方法,钩子函数等

怎样理解 Vue 的单项数据流

数据总是从父组件传到子组件,子组件没有权利修改父组件传过来的数据,只能请求父组件对原始数据进行修改。这样会防止从子组件意外改变父组件的状态,从而导致你的应用的数据流向难以理解。
注意:在子组件直接用 v-model 绑定父组件传过来的 props 这样是不规范的写法,开发环境会报警告。
如果实在要改变父组件的 props 值可以再data里面定义一个变量,并用 prop 的值初始化它,之后用$emit 通知父组件去修改。

Vuex 页面刷新数据丢失怎么解决?

需要做 vuex 数据持久化,一般使用本地储存的方案来保存数据,可以自己设计存储方案,也可以使用第三方插件。
推荐使用 vuex-persist (脯肉赛斯特)插件,它是为 Vuex 持久化储存而生的一个插件。不需要你手动存取 storage,而是直接将状态保存至 cookie 或者 localStorage中。

堆和栈存储机制有什么区别

堆 是一种非连续的树形储存数据结构,每个节点有一个值,整棵树是经过排序的。特点是根结点的值最小(或最大),且根结点的两个子树也是一个堆。常用来实现优先队列,存取随意。

栈 是一种连续储存的数据结构,具有先进后出的性质。
通常的操作有入栈(压栈),出栈和栈顶元素。想要读取栈中的某个元素,就是将其之间的所有元素出栈才能完成。

数组方法

  1、sort( ):sort 排序 如果下面参数的正反 控制 升序和降序 ,返回的是从新排序的原数组
  2、splice( ):向数组的指定index处插入 返回的是被删除掉的元素的集合,会改变原有数组;截取类 没有参数,返回空数组,原数组不变;一个参数,从该参数表示的索引位开始截取,直至数组结束,返回截取的 数组,原数组改变;两个参数,第一个参数表示开始截取的索引位,第二个参数表示截取的长度,返回截取的 数组,原数组改变;三个或者更多参数,第三个及以后的参数表示要从截取位插入的值。会改变原数据
  3、pop( ):从尾部删除一个元素 返回被删除掉的元素,改变原有数组。
  4、push( ):向数组的末尾追加 返回值是添加数据后数组的新长度,改变原有数组。
  5、unshift( ):向数组的开头添加 返回值是添加数据后数组的新长度,改变原有数组。
  6、shift( ):从头部删除一个元素 返回被删除掉的元素,改变原有数组。
  7、reverse( ): 原数组倒序  它的返回值是倒序之后的原数组
  8、concat( ):数组合并。
  9、slice( ):数组元素的截取,返回一个新数组,新数组是截取的元素,可以为负值。从数组中截取,如果不传参,会返回原数组。如果只传入一个参数,会从头部开始删除,直到数组结束,原数组不会改变;传入两个参数,第一个是开始截取的索引,第二个是结束截取的索引,不包含结束截取的这一项,原数组不会改变。最多可以接受两个参数。
  10、join( ):讲数组进行分割成为字符串  这能分割一层在套一层就分隔不了了
  11、toString( ):数组转字符串;
  12、toLocaleString( ):将数组转换为本地数组。
  13、forEach( ):数组进行遍历;
  14、map( ):没有return时,对数组的遍历。有return时,返回一个新数组,该新数组的元素是经过过滤(逻辑处理)过的函数。
  15、filter( ):对数组中的每一运行给定的函数,会返回满足该函数的项组成的数组。
  16、every( ):当数组中每一个元素在callback上被返回true时就返回true。(注:every其实类似filter,只不过它的功能是判断是不是数组中的所有元素都符合条件,并且返回的是布尔值)。
  17、some( ):当数组中有一个元素在callback上被返回true时就返回true。(注:every其实类似filter,只不过它的功能是判断是不是数组中的所有元素都符合条件,并且返回的是布尔值)。
  18、reduce( ):回调函数中有4个参数。prev(之前计算过的值),next(之前计算过的下一个的值),index,arr。把数组列表计算成一个
  19、isArray() 判断是否是数组
  20、indexOf  找索如果找到了就会返回当前的一个下标,若果没找到就会反回-1
  21、lastIndexOf 它是从最后一个值向前查找的 找索如果找到了就会返回当前的一个下标,若果没找到就会反回-1
  22、Array.of() 填充单个值
  23、Array.from() 来源是类数组    
  24、fill填充方法 可以传入3各参数 可以填充数组里的值也就是替换 如果一个值全部都替换掉 ,    第一个参数就是值 第二个参数 从起始第几个 第三个参数就是最后一个
  find  查找这一组数 符合条件的第一个数 给他返回出来
  findIndex() 查找这一组数 符合条件的第一数的下标 给他返回出来     没有返回 -1  
  keys 属性名  values属性值  entries属性和属性值
  forEach 循环便利 有3个参数 无法使用 break continue , 参数一就是每个元素 参数二就是每个下标 参数三就是每个一项包扩下标和元素

改变数组本身的api

  1、pop()  尾部弹出一个元素
  2、push() 尾部插入一个元素
  3、shift() 头部弹出一个元素
  4、unshift() 头部插入一个元素
  5、sort([func]) 对数组进行排序,func有2各参数,其返回值小于0,那么参数1被排列到参数2之前,反之参数2排在参数1之前
  6、reverse() 原位反转数组中的元素
  7、splice(pos,deleteCount,...item)  返回修改后的数组,从pos开始删除deleteCount个元素,并在当前位置插入items
  8、copyWithin(pos[, start[, end]]) 复制从start到end(不包括end)的元素,到pos开始的索引,返回改变后的数组,浅拷贝
  9、arr.fill(value[, start[, end]]) 从start到end默认到数组最后一个位置,不包括end,填充val,返回填充后的数组

谈谈你对call、apply、bind理解

都是来改变this指向和函数的调⽤,实际上call与apply的功能是相同的,只是两者的传参方式不一样,

call⽅法跟的是⼀个参数列表,
apply跟⼀个 数组作为参数,call⽅法和apply使⽤后就直接调⽤
bind 传参后不会立即执行,而是返回一个改变了this指向的函数,这个函数可以继续传参,且执行,需要类似于bind()()两个括号才能调⽤。

谈谈你对JS eventloop(事件循环)的理解

浏览器内核是多线程,JavaScript是单线程;

JS单线程详解:因为 js 是面向客户端的一门语言,主要是用户交互,操作dom,渲染数据。试想一下。
如果是多线程,我们在一个线程删除了一个dom节点,另外一个线程添加了一个dom节点,以那个线程为主呢,
就会出现混乱的情况。当然你可以说我们在操作一个dom之后加上锁,只允许一个线程操作,这样其实增加了程序的复杂度,
并不是一个好办法。
单线程产生的问题:必须要等待前一个程序执行完毕才执行下一个,所以将程序分为了两类:同步任务和异步任务。

异步任务又可以分为宏任务和微任务。

栈:先进后出的数据结构,存储基本数据类型的变量。
堆:主要负责引用数据类型的存储。

任务队列:为什么会有任务队列呢,还是因为 javascript 单线程的原因,单线程,就意味着一个任务一个任务的执行,
执行完当前任务,执行下一个任务,这样也会遇到一个问题,就比如说,要向服务端通信,加载大量数据,如果是同步执行,
js 主线程就得等着这个通信完成,然后才能渲染数据,为了高效率的利用cpu, 就有了同步任务和异步任务之分。
同步任务: 指的是在主线程上排队执行的任务,只有前一个任务执行完毕,才能执行后一个任务。

异步任务: 指的是不进入主线程,某个异步任务可以执行了,该任务才会进入主线程执行。

微任务:
promise 的回调、node 中的 process.nextTick 、对 Dom 变化监听的 MutationObserver。

宏任务:
script 脚本的执行、setTimeout ,setInterval ,setImmediate 一类的定时事件,还有如 I/O 操作、UI 渲染等。

require与import的区别和使用

  1、import是ES6中的语法标准也是用来加载模块文件的,import函数可以读取并执行一个JavaScript文件,然后返回该模块的export命令指定输出的代码。export与export default均可用于导出常量、函数、文件、模块,export可以有多个,export default只能有一个。

  2、require 定义模块:module变量代表当前模块,它的exports属性是对外的接口。通过exports可以将模块从模块中导出,其他文件加载该模块实际上就是读取module.exports变量,他们可以是变量、函数、对象等。在node中如果用exports进行导出的话系统会系统帮您转成module.exports的,只是导出需要定义导出名。

  require与import的区别

  1、require是CommonJS规范的模块化语法,import是ECMAScript 6规范的模块化语法;

  2、require是运行时加载,import是编译时加载;

  3、require可以写在代码的任意位置,import只能写在文件的最顶端且不可在条件语句或函数作用域中使用;

  4、require通过module.exports导出的值就不能再变化,import通过export导出的值可以改变;

  5、require通过module.exports导出的是exports对象,import通过export导出是指定输出的代码;

  6、require运行时才引入模块的属性所以性能相对较低,import编译时引入模块的属性所以性能稍高。

for...in 迭代和 for...of 有什么区别

1、 推荐在循环对象属性的时候,使用 for...in,在遍历数组的时候的时候使用for...of。

2、 for in遍历的是数组的索引,而for of遍历的是数组元素值

3、for...of 不能循环普通的对象,需要通过和 Object.keys()搭配使用

4、for...in 便利顺序以数字为先 无法便利 symbol 属性 可以便利到公有中可枚举的

5、从遍历对象的角度来说,for···in会遍历出来的为对象的key,但for···of会直接报错。

谈谈你对promise、Generator、async/await理解

promise和async/await是专门用于处理异步操作的

Generator并不是为异步而设计出来的,它还有其他功能(对象迭代、控制输出、部署Interator接口…)

promise编写代码相比Generator、async更为复杂化,且可读性也稍差

Generator、async需要与promise对象搭配处理异步情况

async实质是Generator的语法糖,相当于会自动执行Generator函数

async使用上更为简洁,将异步代码以同步的形式进行编写,是处理异步编程的最终方案

谈谈你对模块化开发的理解?

我对模块的理解是,一个模块是实现一个特定功能的一组方法。在最开始的时候,js 只实现一些简单的功能,
所以并没有模块的概念,但随着程序越来越复杂,代码的模块化开发变得越来越重要。

由于函数具有独立作用域的特点,最原始的写法是使用函数来作为模块,几个函数作为一个模块,但是这种方式容易造成全局变量的污染,并且模块间没有联系。

对象写法,通过将函数作为一个对象的方法来实现,这样解决了直接使用函数作为模块的一些缺点,但是这种办法会暴露所有的模块成员,外部代码可以修改内部属性的值。

现在最常用的是立即执行函数的写法,通过利用闭包来实现模块私有作用域的建立,同时不会对全局作用域造成污染。

js的几种模块规范?

js 中现在比较成熟的有四种模块加载方案:

第一种是 CommonJS 方案,它通过 require 来引入模块,通过 module.exports 定义模块的输出接口。这种模块加载方案是服务器端的解决方案,它是以同步的方式来引入模块的,因为在服务端文件都存储在本地磁盘,所以读取非常快,所以以同步的方式加载没有问题。但如果是在浏览器端,由于模块的加载是使用网络请求,因此使用异步加载的方式更加合适。

第二种是 AMD 方案,这种方案采用异步加载的方式来加载模块,模块的加载不影响后面语句的执行,所有依赖这个模块的语句都定义在一个回调函数里,等到加载完成后再执行回调函数。require.js 实现了 AMD 规范。

第三种是 CMD 方案,这种方案和 AMD 方案都是为了解决异步模块加载的问题,sea.js 实现了 CMD 规范。它和require.js的区别在于模块定义时对依赖的处理不同和对依赖模块的执行时机的处理不同。

第四种方案是 ES6 提出的方案,使用 import 和 export 的形式来导入导出模块。

你有对 Vue 项目进行哪些优化?

(1)、代码层面的优化
v-if 和 v-show 区分使用场景
computed 和 watch  区分使用场景
v-for 遍历必须为 item 添加 key,且避免同时使用 v-if
长列表性能优化
事件的销毁
图片资源懒加载
路由懒加载
第三方插件的按需引入
优化无限列表性能
服务端渲染 SSR or 预渲染

(2)、Webpack 层面的优化
Webpack 对图片进行压缩
减少 ES6 转为 ES5 的冗余代码
提取公共代码
模板预编译
提取组件的 CSS
优化 SourceMap
构建结果输出分析
Vue 项目的编译优化

(3)、基础的 Web 技术的优化
开启 gzip 压缩
浏览器缓存
CDN 的使用
使用 Chrome Performance 查找性能瓶颈

2、vue3.0 特性你有什么了解的吗?

Vue 3.0 增加以下这些新特性:

(1)、监测机制的改变
3.0 将带来基于代理 Proxy 的 observer 实现,提供全语言覆盖的反应性跟踪。这消除了 Vue 2 当中基于 Object.defineProperty 的实现所存在的很多限制:

只能监测属性,不能监测对象

检测属性的添加和删除;

检测数组索引和长度的变更;

支持 Map、Set、WeakMap 和 WeakSet。

新的 observer 还提供了以下特性:

用于创建 observable 的公开 API。这为中小规模场景提供了简单轻量级的跨组件状态管理解决方案。

默认采用惰性观察。在 2.x 中,不管反应式数据有多大,都会在启动时被观察到。如果你的数据集很大,这可能会在应用启动时带来明显的开销。在 3.x 中,只观察用于渲染应用程序最初可见部分的数据。

更精确的变更通知。在 2.x 中,通过 Vue.set 强制添加新属性将导致依赖于该对象的 watcher 收到变更通知。在 3.x 中,只有依赖于特定属性的 watcher 才会收到通知。

不可变的 observable:我们可以创建值的“不可变”版本(即使是嵌套属性),除非系统在内部暂时将其“解禁”。这个机制可用于冻结 prop 传递或 Vuex 状态树以外的变化。

更好的调试功能:我们可以使用新的 renderTracked 和 renderTriggered 钩子精确地跟踪组件在什么时候以及为什么重新渲染。

(2)、模板
模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。

同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom。

(3)、对象式的组件声明方式
vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。

此外,vue 的源码也改用了 TypeScript 来写。其实当代码的功能复杂之后,必须有一个静态类型系统来做一些辅助管理。现在 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外暴露的 api 更容易结合 TypeScript。静态类型系统对于复杂代码的维护确实很有必要。

(4)、其它方面的更改
vue3.0 的改变是全面的,上面只涉及到主要的 3 个方面,还有一些其他的更改:

支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式。

支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理。

基于 treeshaking 优化,提供了更多的内置功能。

Vue 模板编译原理

Vue 的编译过程就是将 template 转化为 render 函数的过程 分为以下三步

第一步是将 模板字符串 转换成 element ASTs(解析器)
第二步是对 AST 进行静态节点标记,主要用来做虚拟DOM的渲染优化(优化器)
第三步是 使用 element ASTs 生成 render 函数代码字符串(代码生成器)

Vue.extend 作用和原理

官方解释:Vue.extend 使用基础 Vue 构造器,创建一个“子类”。参数是一个包含组件选项的对象。

其实就是一个子类构造器 是 Vue 组件的核心 api 实现思路就是使用原型继承的方法返回了 Vue 的子类 并且利用 mergeOptions 把传入组件的 options 和父类的 options 进行了合并

nextTick 使用场景和原理

nextTick 中的回调是在下次 DOM 更新循环结束之后执行的延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。主要思路就是采用微任务优先的方式调用异步方法去执行 nextTick 包装的方法

diff算法

时间复杂度: 个树的完全 diff 算法是一个时间复杂度为 O(n*3) ,vue进行优化转化成 O(n) 。

理解:
最小量更新, key 很重要。这个可以是这个节点的唯一标识,告诉 diff 算法,在更改前后它们是同一个DOM节点
扩展 v-for 为什么要有 key ,没有 key 会暴力复用,举例子的话随便说一个比如移动节点或者增加节点(修改DOM),加 key 只会移动减少操作DOM。
只有是同一个虚拟节点才会进行精细化比较,否则就是暴力删除旧的,插入新的。
只进行同层比较,不会进行跨层比较。

Vue中组件生命周期调用顺序说一下

组件的调用顺序都是先父后子,渲染完成的顺序是先子后父。
组件的销毁操作是先父后子,销毁完成的顺序是先子后父。

加载渲染过程
父beforeCreate->父created->父beforeMount->子beforeCreate->子created->子beforeMount- >子mounted->父mounted

子组件更新过程
父beforeUpdate->子beforeUpdate->子updated->父updated

父组件更新过程
父 beforeUpdate -> 父 updated

销毁过程
父beforeDestroy->子beforeDestroy->子destroyed->父destroyed

写过自定义指令吗?原理是什么?

指令本质上是装饰器,是 vue 对 HTML 元素的扩展,给 HTML 元素增加自定义功能。vue 编译 DOM 时,会找到指令对象,执行指令的相关方法。

自定义指令有五个生命周期(也叫钩子函数),分别是 bind、inserted、update、componentUpdated、unbind

1.bind:只调用一次,指令第一次绑定到元素时调用。在这里可以进行一次性的初始化设置。

2.inserted:被绑定元素插入父节点时调用 (仅保证父节点存在,但不一定已被插入文档中)。

3.update:被绑定于元素所在的模板更新时调用,而无论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新。

4.componentUpdated:被绑定元素所在模板完成一次更新周期时调用。

5.unbind:只调用一次,指令与元素解绑时调用。

原理
1.在生成 ast 语法树时,遇到指令会给当前元素添加 directives 属性
2.通过 genDirectives 生成指令代码
3.在 patch 前将指令的钩子提取到 cbs 中,在 patch 过程中调用对应的钩子
4.当执行指令对应钩子函数时,调用对应指令定义的方法

​link和import的区别

页面中使用CSS的方式主要有3种:行内添加定义style属性值,页面头部内嵌调用和外面链接调用,其中外面引用有两种:link和@import。外部引用CSS两种方式link和@import的方式分别是:

XML/HTML代码
<link rel="stylesheet" rev="stylesheet" href="CSS文件" type="text/css" media="all" />   
XML/HTML代码
<style type="text/css" media="screen">   
@import url("CSS文件");   
</style>  

两者都是外部引用CSS的方式,但是存在一定的区别:

  区别1:link是XHTML标签,除了加载CSS外,还可以定义RSS等其他事务;@import属于CSS范畴,只能加载CSS。

  区别2:link引用CSS时,在页面载入时同时加载;@import需要页面网页完全载入以后加载。

  区别3:link是XHTML标签,无兼容问题;@import是在CSS2.1提出的,低版本的浏览器不支持。

  区别4:ink支持使用Javascript控制DOM去改变样式;而@import不支持。

补充:@import最优写法
@import的写法一般有下列几种:

@import 'style.css' //Windows IE4/ NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别
@import "style.css" //Windows IE4/ NS4, Macintosh IE4/NS4不识别
@import url(style.css) //Windows NS4, Macintosh NS4不识别
@import url('style.css') //Windows NS4, Mac OS X IE5, Macintosh IE4/IE5/NS4不识别
@import url("style.css") //Windows NS4, Macintosh NS4不识别
由上分析知道,@import url(style.css) 和@import url("style.css")是最优的选择,兼容的浏览器最多。从字节优化的角度来看@import url(style.css)最值得推荐。

什么是盒子模型?
把所有的网页元素都看成一个盒子,它具有: content,padding,border,margin 四个属性,这就是盒子模型。

盒子模型有几种模式?
1、W3C标准盒子模型
2、IE盒子模型

W3C标准盒子模型
标准模式下,一个块的宽度 = width+padding(内边距)+border(边框)+margin(外边距);
W3C模型中:
      CSS中的宽(width)=内容(content)的宽
      CSS中的高(height)=内容(content)的高

IE盒子模型
怪异模式下,一个块的宽度 = width+margin(外边距) (即怪异模式下,width包含了border以及padding)。
IE模型中:
      CSS中的宽(width)=内容(content)的宽+(border+padding)*2
      CSS中的高(height)=内容(content)的高+(border+padding)*2

CSS3 box-sizing
box-sizing:content-box||border-box||inherit
box-sizing:content-box; 将采用标准模式的盒子模型标准

box-sizing:border-box; 将采用怪异模式的盒子模型标准

box-sizing:inherit; 规定应从父元素继承 box-sizing 属性的值。

总结
IE5.5及更早的版本使用的是IE盒模型。IE6及其以上的版本在标准兼容模式下使用的是W3C的盒模型标准。我们说这是一个好消息因为这意味着此盒模型问题只会出现在IE5.5及其更早的版本中。只要为文档设置一个DOCTYPE,就会使得IE遵循标准兼容模式的方式工作
 

什么是内存泄漏?

程序的运行需要内存,只要程序提出要求,操作系统或者运行是就必须供给内存。

对于持续运行的服务进程,必须及时释放内存,否则,内存占用越来越高,轻则影响系统性能,重则导致进程崩溃。

不再用到的内存,没有及时释放,就叫做内存泄漏。

有些语言(比如c语言)必须手动释放内存,程序员负责内存管理。

这很麻烦,所以大多数语言提供自动内存管理,减轻程序员的负担,这被称为"垃圾回收机制"。

javascript垃圾回收机制原理:

解决内存的泄露,垃圾回收机制会定期(周期性)找出那些不再用到的内存(变量),然后释放其内存。

现在各大浏览器通常采用的垃圾回收机制有两种方法:标记清除,引用计数。

 异步加载js的方法:

  1)async   HTML5的属性,让JavaScript代码进行异步加载

<script type="text/javascript" src="05.js" async="async">
</script>
 

  2)defer   老版本IE专用

<script type="text/javascript" defer="defer">
</script>
            
 

  3)动态的创建script的标签(可以解决兼容h5以及低版本ie的问题),代码如下:

        <script type="text/javascript">
            function asyncLoaded(url,callback){
                var script = document.createElement("script");
//                script.src = url;   假如说网速非常好,直接执行完成了,后面就监听不到状态的改变了
                if(script.readyState){
                    script.onreadystatechange = function(){
                        if(script.readyState == "complete" || script.readyState =="loaded"){
//                            执行某个函数
                            callback()
                        }
                    }
                }else{
                    script.onload = function(){
//                        执行某个函数
                        callback()
                    }
                }
                script.src = url;    //异步的过程
                document.head.appendChild(script)    
            }
            asyncLoaded("05.js",function(){
                fn()          //05.js中的函数
            })
        </script>
 

vue-router 有 3 种路由模式:hash、history、abstract,对应的源码如下所示:

switch (mode) {
  case 'history':
    this.history = new HTML5History(this, options.base)
    break
  case 'hash':
    this.history = new HashHistory(this, options.base, this.fallback)
    break
  case 'abstract':
    this.history = new AbstractHistory(this, options.base)
    break
  default:
    if (process.env.NODE_ENV !== 'production') {
      assert(false, `invalid mode: ${mode}`)
    }
}


其中,3 种路由模式的说明如下:

hash: 使用 URL hash 值来作路由。支持所有浏览器,包括不支持 HTML5 History Api 的浏览器;
history : 依赖 HTML5 History API 和服务器配置。具体可以查看 HTML5 History 模式;
abstract : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.
 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值