一. 题库
前端中的hack
CSS hack由于不同厂商的浏览器,比如Internet Explorer,Safari,Mozilla Firefox,Chrome等,或者是同一厂商的浏览器的不同版本,如IE6和IE7,对CSS的解析认识不完全一样,因此会导致生成的页面效果不一样,得不到我们所需要的页面效果。 这个时候我们就需要针对不同的浏览器去写不同的CSS,让它能够同时兼容不同的浏览器,能在不同的浏览器中也能得到我们想要的页面效果。
简单的说,CSS hack的目的就是使你的CSS代码兼容不同的浏览器。当然,我们也可以反过来利用CSS hack为不同版本的浏览器定制编写不同的CSS效果。
css hack原理就是针对不同的浏览器编写不同的样式代码,添加css样式前缀。
css hack的几种方式
- 属性Hack
如 width:100px;
+width:100px; //IE6 IE7
*width:100px; // IE6 IE7
width:200px/9 //IE6~IE10
- 类选择器Hack
*html *IE6生效
*+html *+IE7生效
@media screen\9{...}IE6/7
@media \0screen {body { background: red; }}IE8
- 条件注释Hack
<!--[if IE]>
这段文字只在IE浏览器显示
<![endif]-->
<!--[if IE 6]>
这段文字只在IE6浏览器显示
<![endif]-->
<!--[if gte IE 6]>
这段文字只在IE6以上(包括)版本IE浏览器显示
<![endif]-->
<!--[if ! IE 8]>
这段文字在非IE8浏览器显示
<![endif]-->
<!--[if !IE]>
这段文字只在非IE浏览器显示
<![endif]-->
浏览器内核
浏览器 | 内核 |
---|---|
Firefox | Firefox内核(Gecko内核) |
IE | IE内核(Trident内核) |
Chrome | Webkit内核,现在是Blink内核 |
Safari | Webkit内核 |
Opera | 最初是自己的Presto内核,后来加入谷歌,从Webkit又到了Blink |
360 | IE+chrome |
Trident(兼容模式)+Webkit(高速模式) |
什么是BFC?
块级格式化上下文,它是指一个独立的块级渲染区域,只有block-level box参与,该区域有一套渲染规则来约束块级盒子布局,且与区域外部无关。
如何创建?
- float的值不是none
- position的值不是static或relative即可
- display的值是inline-block、flex或者inline-flex
- overflow:hidden
解决margin塌陷
响应式解决方案
- rem布局
- 百分比布局
- bootstrap等框架布局
Html5的新特性
语义化标签
header(网页的头部等)、footer(尾部)、section(部分标签定义网页中的区域)、aside(旁边(侧边栏))和articl(导航内容)是一起使用、nav(导航链接)、hgroup(分组)
媒体标签
video、aduio(视频、音频)
video标签
<video width="500" height="500" controls>
<source src="video.mp4" type="video/mp4">
<source src="video.ogg" type="video/ogg">
</video>
controls 显示播放控件
表单
date、time、email、url、search 等类型
<input type="date" name="lname" />
html兼容解决方案
html5shiv
html5shiv 是一个针对 IE 浏览器的 HTML5 JavaScript 补丁,目的是让 IE 识别并支持 HTML5 元素。
<!-- if lt IE 9 -->
<script src="https://cdn.bootcss.com/html5shiv/r29/html5.js"></script>
<!-- endif -->
respond.js
作用:使ie9及以下兼容@media与ie6兼容max-width;
Respond.js 是一个快速、轻量的 polyfill,用于为 IE6-8 以及其它不支持 CSS3 Media Queries 的浏览器提供媒体查询的 min-width 和 max-width 特性,实现响应式网页设计(Responsive Web Design)。
<!-- if lt IE 9 -->
<script src="https://cdn.bootcss.com/response.js/0.10.0/response.js"></script>
<!-- endif -->
Promise是什么?
Promise是异步编程的一种解决方案,它是一个容器,里面保存着某个未来才会结束的事件的结果。它有三种状态(pending进行中,fulfilled已成功,rejected已失败),只有异步操作的结果才能决定当前的状态,不受外界因素的影响。而一旦状态改变,就不会再变,也就是状态凝固了(resolved),任何时候都可以得到这个结果。
vue是什么
Vue 是一套用于构建用户界面的渐进式框架
框架 和 库 的区别
1.库(插件):是一种封装好的特定方法集合,对项目的侵入性较小,提供给开发者使用,控制权在使用者手中,如果某个库无法完成某些需求,可以很容易切换到其它库实现需求
2.框架:是一套架构,会基于自身特点向用户提供一套相当完整的解决方案,而且控制权在框架本身;对项目的侵入性较大,使用者要按照框架所规定的某种特定规范进行开发,项目如果需要更换框架,则需要重新架构整个项目
vue的特点
1.构建用户界面,只需要关系view层
2.简单易学,轻量快速
3.渐进式框架
vue的两个核心
1.响应式的数据绑定:当数据发生改变,视图可以自动更新,可以不用关心dom操作,而专心数据操作
2.可组合的视图组件:把视图按照功能切分成若干基本单元,组件可以一级一级组合整个应用形成倒置组件树,可维护,可重用,可测试
vue的生命周期
-
创建前(befroecreate)
实例刚在内存中被创建出来,此时,还没有初始化好data和method,换句话说 就当前实例只是一个空壳,无法访问到数据和真实的dom,一般不做操作挂在数据,绑定事件等 -
创建后(created)
在这个阶段vue实例已经 创建,初始化了data和method,但是这个时候仍然不能获取dom元素,这时候可以更改数据,不会触发其他的钩子函数,一般可以在这里做一些初始数据的获取,接下去开始找实例或者组件对应的模板,之后就开始进入下一个生命周期 -
渲染前(befroemount)
这时候虚拟dom已经创建完成了,完成了模板编译.马上就要渲染,在这里也可以更改数据,不会触发updated,一般在这里可以做初始数据的获取 -
渲染后(Mountd)
mounted是我们平常用的最多的函数,一般我们的异步请求都写在这里.接下来开始渲染render,渲染真实的dom,将编译好的模板,挂载到页面指定的容器显示 -
更新前(beforeupdate)
状态更新前执行此函数,此时dat中的状态值是最新的,但是界面上显示的数据还是旧的,因为此时还没有渲染don节点 -
更新后(updated)
实例更新完毕后调用此函数,dom会和更改过的内容同步然后界面重新渲染 -
销毁前(beforeDestroy)
当经过某种途径调用$destroy方法后(清除vue实例和dom的关联),立即执行beforeDestroy,这时候vue实例已经从运行阶段进入了销毁阶段
一般在这里进行一些善后工作,例如清除计时器、清除非指令绑定的时间等等 -
销毁后(destroyed)
组件的数据绑定、监听去掉后只剩下dom空壳,这个时候,执行destroyed
可以定义多个vue组件实例吗?
可以
spa应用里面是没有机会定义多个vue实例的
所谓的spa就是:
单页Web应用(single page web application,SPA),就是只有一张Web页面的应用,是加载单个HTML
页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
v-on:事件绑定
v-bind:属性绑定
原生js的属性绑定
js:document .getElementById(‘id’).setAttribute(属性名, 属性值)
jQuery:$(’#id’).attr(属性名, 属性值)/.attr({属性1: 属性值1, 属性2: 属性值2})
v-for: 用来做数组循环
v-show: 条件渲染
v-if: 条件分支显示
v-model: 数据双向绑定(仅适用于表单控件)
v-if和v-show的区别
v-if判断值为false的时候会连同代码从文档流中去除
v-show在false的时候只是将元素属性变成了display: none
所以:
v-if性能更差但安全性高
v-show则相反,通常用于频繁的切换显示和隐藏时使用
vue.js的MVVM原理理解
M: model数据模型层,可以定义数据修改和操作逻辑
V: 视图层代表ui组件,将数据模型转换成ui呈现出来
VM:viewmodel,监听数据的改变和控制视图行为,可以理解为view和model的同步,连接view和model的桥梁
传统的mvc
m:指的是业务模型
v:指的是用户界面
c:指的是控制器
mvc是将m和v的实现代码分离,是业务逻辑更加清晰。
vue的生命周期总共分为八个阶段
实例创建前后,beforecreate 实例已经创建但是el未挂载,data还未初始化
created,date已经初始化,可以发送异步请求获取初始化数据
实例载入前后,beforemount,虚拟dome已经创建,准备开始渲染,
mounted,数据已经成功渲染为真实dom,vue实例已经挂载完成
实例更新前后 beforeupdate 数据更新前,update数据更新后触发
实例销毁前后destorey
Vue中的全局API
Vue.extend()
参数object
用法:使用基础vue构造器创建一个子类。参数是一个包含组件选项的对象
// 创建构造器
var Profile = Vue.extend({
template: '<p>{{firstName}} {{lastName}} aka {{alias}}</p>',
data: function () {
return {
firstName: 'Walter',
lastName: 'White',
alias: 'Heisenberg'
}
}
})
// 创建 Profile 实例,并挂载到一个元素上。
new Profile().$mount('#mount-point')
Vue.nexTick([callback])
含义:在下次Dom更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的DOM。
使用方法
<template>
<div>
<div>
<button id="firstBtn" @click="testClick()" ref="btn">{{testMsg}}</button>
</div>
</div>
</template>
<script>
export default {
data () {
return {
test:"原始值",
}
},
methods:{
testClick:function(){
let that=this;
that.test="修改后的值";
console.log(that.$refs.btn.innerText); //that.$refs.btn获取指定DOM,输出:原始值
}
}
}
</script>
注意:Vue 实现响应式并不是数据发生变化之后 DOM 立即变化,而是按一定的策略进行 DOM 的更新。$nextTick 是在下次 DOM 更新循环结束之后执行延迟回调,在修改数据之后使用 $nextTick,则可以在回调中获取更新后的 DOM
Vue.set(targey,propertyName,value)
含义:向响应式对象中添加一个 property,并确保这个新 property 同样是响应式的,且触发视图更新。它必须用于向响应式对象上添加新 property,因为 Vue 无法探测普通的新增 property。
使用方法
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
</head>
<body>
<div id="app2">
<p v-for="item in items" :key="item.id">
{{item.message}}
</p>
<button class="btn" @click="btn2Click()">动态赋值</button><br/><br/>
<button class="btn" @click="btn3Click()">为data新增属性</button>
</div>
<script src="../../dist/vue.min.js"></script>
<script>
var vm2=new Vue({
el:"#app2",
data:{
items:[
{message:"Test one",id:"1"},
{message:"Test two",id:"2"},
{message:"Test three",id:"3"}
]
},
methods:{
btn2Click:function(){
//Vue methods中的this 指向的是Vue的实例,这里可以直接在this中找到items
Vue.set(this.items,0,{message:"Change Test",id:'10'})
},
btn3Click:function(){
var itemLen=this.items.length;
Vue.set(this.items,itemLen,{message:"Test add attr",id:itemLen});
//此时items数组新增了一个对象{message:"Test add attr",id:itemLen}
}
}
});
</script>
</body>
</html>
Vue中如何监听路由变化
通过watch属性监听路由变化从而做出相应逻辑操作
watch: {
$route(to, from) {
if (to.path === "/allv") {
this.activeIndex = "1";
this.fenye1(1, this.type);
console.log(this.activeIndex);
}
},
},
还可以通过beforeRouteUpdate守卫判断
beforeRouteUpdate(to,from,next){
console.log(to,from,next)
debugger
if(to.fullPath!=from.fullPath){
next()
this.changeUser()
}
},
vue-router 导航解析流程
1、导航被触发。
2、在失活的组件里调用离开守卫。
3、调用全局的 beforeEach守卫。
4、在重用的组件里调用 beforeRouteUpdate守卫 (2.2+)。
5、在路由配置里调用beforeEnter。
6、解析异步路由组件。
7、在被激活的组件里调用beforeRouteEnter。
8、调用全局的 beforeResole 守卫 (2.5+)。
9、导航被确认。
10、调用全局的afterEach 钩子。
11、触发 DOM 更新。
12、用创建好的实例调用beforeRouteEnter 守卫中传给 next 的回调函数。
1、全局守卫: router.beforeEach
2、全局解析守卫: router.beforeResolve
3、全局后置钩子: router.afterEach
4、路由独享的守卫: beforeEnter
5、组件内的守卫: beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave
vue中控制浏览器滚动条
scrollbehavior
可以空值浏览器滚动条的位置
下图表示跳转到顶部
Vuex是什么?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
特点:
集中管理vue组件中的共享数据。
响应式数据,当vuex中数据改变时,页面也会最值更新。
1.state提供唯一的数据资源,所有的共享数据统一放到store中的state中
2.mutation用于变更state中的数据,可以集中监控所有数据变化
3.action用于处理异步任务
4.getter对state中的数据进行进行加工处理形成新的数据,类似vue中的计算属性
5.module,当应用程序比较大时,vuex为我们提供了一个模块化管理机制,每个模块有自己对应的state、mutation等
Vue和React的区别
- 监听数据变化的实现原理不同
vue是通过getter/setter以及函数劫持,能精确知道数据变化,React默认是通过比较引用的方式进行的,即diff算法,如果不优化可能导致不必要的VDOMd的更新渲染,这是vue和react的设计理念上的区别。 - 数据流的不同
vue可以通过v-model实现双向数据绑定,而react单项数据流,要通过
setState来更新数据。 - 模板渲染方式不同
vue是像是一种扩展的html语法,通过v-bind,v-on等指令来控制变化,而react是使用的jsx,更偏向于原生js。
Vue响应式数据的原理
核心是object.defineProperty
vue实例在初始数据时,会给data中的属性使用objec.defineProerty重新定义所有属性,当页面取到所有属性时会进行依赖收集(watcher)如果属性变化会通知相关依赖更新。
$on 和 $emit
一、$emit
1、this $emit(‘自定义时间名’,要传送的数据);
2、触发当前实例上的时间,要传递的数据会传给监听器;
二、 o n 1 、 V M . on 1、VM. on1、VM.on(‘事件名’,callback) --------------------callback回调$emit要传送的数据;
2、监听当前实例上自定义时间;
vm.$ on( event, callback ):监听当前实例上的自定义事件。事件可以由vm.$
emit触发。回调函数会接收所有传入事件触发函数的额外参数。vm.$emit( event, […args] ):触发当前实例上的事件。附加参数都会传给监听器回调。
jQuery的出现解决了什么问题?
- 提高了开发效率
- 进行兼容性处理
弊端
- 本质还是操作Dom(必然触发重绘与回流,影响性能)
- 没有做业务分层