一、盒子模型
参考:https://segmentfault.com/a/11...
二、HTML4和5的区别
1、语法简化
HTML、XHTML的DOCTYPE、html、meta、script等标签,在HTML5中有大幅度的简化。
2、统一网页内嵌多媒体语法
以前,在网页中播放多媒体时,需要使用ActiveX或Plug-in的方式来完成。有了HTML5之后,使用<video>或<audio>标签播放视频和音频,不需要在安装其他的什么来播放了。
3、新增了语义标签
为了增加网页的可读性,HTML5增加了<header>、<footer>、<section>、<article>、<nav>、<hgroup>、<aside>、<figure>语义标签。
4、HTML5废除了一些旧标签
废除的大部分是网页美化方面的标签,例如:<big>、<u>、<font>、<basefont>、<center>、<s>、<tt>。对<frame>框架,不能使用。
5、全新的表单设计
表单是网页设计者最常用的功能,HTML5对表单做了很大的更改,不但新增了几项新的标签,对原来的<form>标签也增加了许多属性。
6、新增了<canvas>标签,可以绘制图形
HTML5新增了具有绘图功能的<canvas>
扩展资料
HTML5新特征
1、表单是实现用户与页面后台交互主要组成部分,HTML5在表单的设计上功能更加强大。input类型和属性的多样性大大地增强了HTML可表达的表单形式,再加上新增加的一些表单标签,使得原本需要JavaScript来实现的控件,可以直接使用HTML5的表单来实现。
2、HTML5较之传统的数据存储有自已的存储方式,允许在客户端实现较大规模的数据存储。为了满足不同的需求,HTML5支持DOM Storage和Web SQL Database 两种存储机制。
其中,DOM Storage 适用于具有key/value对的基本本地存储;而WebSQLDatabase是适用于关系型数据库的存储方式,开发者可以使用SQL语法对这些数据进行查询、插入等操作。
3、HTML5最大特色之一就是支持音频视频,在通过增加了<audio>、<video>两个标签来实现对多媒体中的音频、视频使用的支持,只要在Web网页中嵌入这两个标签,而无需第三方插件(如Flash)就可以实现音视频的播放功能。
HTML5对音频、视频文件的支持使得浏览器摆脱了对插件的依赖,加快了页面的加载速度,扩展了互联网多媒体技术的发展空间。
三、本地存储方式
相同:在本地(浏览器端)存储数据
不同:
- localStorage只要在相同的协议、相同的主机名、相同的端口下,就能读取/修改到同一份localStorage数据。sessionStorage比localStorage更严苛一点,除了协议、主机名、端口外,还要求在同一窗口(也就是浏览器的标签页)下。
- localStorage是永久存储,除非手动删除。
- sessionStorage当会话结束(当前页面关闭的时候,自动销毁)
- cookie的数据会在每一次发送http请求的时候,同时发送给服务器而localStorage、sessionStorage不会。
四、跨域
前端通信类的问题,主要包括以下内容:
1、什么是同源策略及限制
同源策略是一个概念,就一句话。有什么限制,就三句话。能说出来即可。
2、前后端如何通信
如果你不准备,估计也就只能说出ajax。这个可以考察出知识面。
3、如何创建Ajax
Ajax在前后端通信中经常用到。做业务时,可以借助第三方的库,比如vue框架里的库、jQuery也有封装好的方法。但如果让你用原生的js去实现,该怎么做?
这就是考察你的动手能力,以及框架原理的掌握。如果能写出来,可以体现出你的基本功。是加分项。
4、跨域通信的几种方式
这部分非常重要。无非就是问你:什么是跨域、跨域有什么限制、跨域有几种方式。
下面分别讲解。
同源策略的概念和具体限制
同源策略:限制从一个源加载的文档或脚本如何与来自另一个源的资源进行交互。这是一个用于隔离潜在恶意文件的关键的安全机制。(来自MDN官方的解释)
具体解释:
(1)源包括三个部分:协议、域名、端口(http协议的默认端口是80)。如果有任何一个部分不同,则源不同,那就是跨域了。
(2)限制:这个源的文档没有权利去操作另一个源的文档。这个限制体现在:(要记住)
Cookie、LocalStorage和IndexDB无法获取。
无法获取和操作DOM。
不能发送Ajax请求。我们要注意,Ajax只适合同源的通信。
前后端如何通信
主要有以下几种方式:
Ajax:不支持跨域。
WebSocket:不受同源策略的限制,支持跨域。
CORS:不受同源策略的限制,支持跨域。一种新的通信协议标准。可以理解成是:同时支持同源和跨域的Ajax。
如何创建Ajax
关于Ajax请求,可以看本人的基础文章:Ajax入门和发送http请求
在回答 Ajax 的问题时,要回答以下几个方面:
1、XMLHttpRequest 的工作原理
2、兼容性处理
XMLHttpRequest只有在高级浏览器中才支持。在回答问题时,这个兼容性问题不要忽略。
3、事件的触发条件
4、事件的触发顺序
XMLHttpRequest有很多触发事件,每个事件是怎么触发的。
发送 Ajax 请求的五个步骤(XMLHttpRequest的工作原理)
(1)创建XMLHttpRequest 对象。
(2)使用open方法设置请求的参数。open(method, url, 是否异步)。
(3)发送请求。
(4)注册事件。 注册onreadystatechange事件,状态改变时就会调用。
如果要在数据完整请求回来的时候才调用,我们需要手动写一些判断的逻辑。
(5)获取返回的数据,更新UI。
发送 get 请求和 post 请求
get请求举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Ajax 发送 get 请求</h1>
<input type="button" value="发送get_ajax请求" id='btnAjax'>
<script type="text/javascript">
// 绑定点击事件
document.querySelector('#btnAjax').onclick = function () {
// 发送ajax 请求 需要 五步
// (1)创建异步对象
var ajaxObj = new XMLHttpRequest();
// (2)设置请求的参数。包括:请求的方法、请求的url。
ajaxObj.open('get', '02-ajax.php');
// (3)发送请求
ajaxObj.send();
//(4)注册事件。 onreadystatechange事件,状态改变时就会调用。
//如果要在数据完整请求回来的时候才调用,我们需要手动写一些判断的逻辑。
ajaxObj.onreadystatechange = function () {
// 为了保证 数据 完整返回,我们一般会判断 两个值
if (ajaxObj.readyState == 4 && ajaxObj.status == 200) {
// 如果能够进到这个判断 说明 数据 完美的回来了,并且请求的页面是存在的
// 5.在注册的事件中 获取 返回的 内容 并修改页面的显示
console.log('数据返回成功');
// 数据是保存在 异步对象的 属性中
console.log(ajaxObj.responseText);
// 修改页面的显示
document.querySelector('h1').innerHTML = ajaxObj.responseText;
}
}
}
</script>
</body>
</html>
post 请求举例:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1>Ajax 发送 get 请求</h1>
<input type="button" value="发送put_ajax请求" id='btnAjax'>
<script type="text/javascript">
// 异步对象
var xhr = new XMLHttpRequest();
// 设置属性
xhr.open('post', '02.post.php');
// 如果想要使用post提交数据,必须添加此行
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
// 将数据通过send方法传递
xhr.send('name=fox&age=18');
// 发送并接受返回值
xhr.onreadystatechange = function () {
// 这步为判断服务器是否正确响应
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
};
</script>
</body>
</html>
onreadystatechange 事件
注册 onreadystatechange 事件后,每当 readyState 属性改变时,就会调用 onreadystatechange 函数。
readyState:(存有 XMLHttpRequest 的状态。从 0 到 4 发生变化)
0: 请求未初始化
1: 服务器连接已建立
2: 请求已接收
3: 请求处理中
4: 请求已完成,且响应已就绪
事件的触发条件
事件的触发顺序
上图的参考链接:
你真的会使用XMLHttpRequest吗?
实际开发中用的 原生Ajax请求
var util = {};
//获取 ajax 请求之后的json
util.json = function (options) {
var opt = {
url: '',
type: 'get',
data: {},
success: function () {
},
error: function () {
},
};
util.extend(opt, options);
if (opt.url) {
//IE兼容性处理:浏览器特征检查。检查该浏览器是否存在XMLHttpRequest这个api,没有的话,就用IE的api
var xhr = XMLHttpRequest ? new XMLHttpRequest() : new window.ActiveXObject('Microsoft.XMLHTTP');
var data = opt.data,
url = opt.url,
type = opt.type.toUpperCase();
dataArr = [];
}
for (var key in data) {
dataArr.push(key + '=' + data[key]);
}
if (type === 'GET') {
url = url + '?' + dataArr.join('&');
xhr.open(type, url.replace(/\?$/g, ''), true);
xhr.send();
}
if (type === 'POST') {
xhr.open(type, url, true);
// 如果想要使用post提交数据,必须添加此行
xhr.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhr.send(dataArr.join('&'));
}
xhr.onload = function () {
if (xhr.status === 200 || xhr.status === 304) { //304表示:用缓存即可。206表示获取媒体资源的前面一部分
var res;
if (opt.success && opt.success instanceof Function) {
res = xhr.responseText;
if (typeof res === 'string') {
res = JSON.parse(res); //将字符串转成json
opt.success.call(xhr, res);
}
}
} else {
if (opt.error && opt.error instanceof Function) {
opt.error.call(xhr, res);
}
}
};
}
Ajax 的推荐链接:https://segmentfault.com/a/11...
跨域通信的几种方式
方式如下:
1、JSONP
2、WebSocket
3、CORS
4、Hash
5、postMessage
上面这五种方式,在面试时,都要说出来。
1、JSONP
面试会问:JSONP的原理是什么?怎么实现的?
在CORS和postMessage以前,我们一直都是通过JSONP来做跨域通信的。
JSONP的原理:通过<script>标签的异步加载来实现的。比如说,实际开发中,我们发现,head标签里,可以通过<script>标签的src,里面放url,加载很多在线的插件。这就是用到了JSONP。
JSONP的实现:
比如说,客户端这样写:
<script src="http://www.smyhvae.com/?data=name&callback=myjsonp"></script>
上面的src中,data=name是get请求的参数,myjsonp是和后台约定好的函数名。 服务器端这样写:
myjsonp({
data: {}
})
于是,本地要求创建一个myjsonp 的全局函数,才能将返回的数据执行出来。
实际开发中,前端的JSONP是这样实现的:
<script>
var util = {};
//定义方法:动态创建 script 标签
/**
* [function 在页面中注入js脚本]
* @param {[type]} url [description]
* @param {[type]} charset [description]
* @return {[type]} [description]
*/
util.createScript = function (url, charset) {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
charset && script.setAttribute('charset', charset);
script.setAttribute('src', url);
script.async = true;
return script;
};
/**
* [function 处理jsonp]
* @param {[type]} url [description]
* @param {[type]} onsucess [description]
* @param {[type]} onerror [description]
* @param {[type]} charset [description]
* @return {[type]} [description]
*/
util.jsonp = function (url, onsuccess, onerror, charset) {
var callbackName = util.getName('tt_player'); //事先约定好的 函数名
window[callbackName] = function () { //根据回调名称注册一个全局的函数
if (onsuccess && util.isFunction(onsuccess)) {
onsuccess(arguments[0]);
}
};
var script = util.createScript(url + '&callback=' + callbackName, charset); //动态创建一个script标签
script.onload = script.onreadystatechange = function () { //监听加载成功的事件,获取数据
if (!script.readyState || /loaded|complete/.test(script.readyState)) {
script.onload = script.onreadystatechange = null;
// 移除该script的 DOM 对象
if (script.parentNode) {
script.parentNode.removeChild(script);
}
// 删除函数或变量
window[callbackName] = null; //最后不要忘了删除
}
};
script.onerror = function () {
if (onerror && util.isFunction(onerror)) {
onerror();
}
};
document.getElementsByTagName('head')[0].appendChild(script); //往html中增加这个标签,目的是把请求发送出去
};
</script>
2、WebSocket
WebSocket的用法如下:
//
var ws = new WebSocket('wss://echo.websocket.org'); //创建WebSocket的对象。参数可以是 ws 或 wss,后者表示加密。
//把请求发出去
ws.onopen = function (evt) {
console.log('Connection open ...');
ws.send('Hello WebSockets!');
};
//对方发消息过来时,我接收
ws.onmessage = function (evt) {
console.log('Received Message: ', evt.data);
ws.close();
};
//关闭连接
ws.onclose = function (evt) {
console.log('Connection closed.');
};
Websocket的推荐链接:http://www.ruanyifeng.com/blo...
面试一般不会让你写这个代码,一般是考察你是否了解 WebSocket概念,知道有这么回事即可。
3、CORS
CORS 可以理解成是既可以同步、也可以异步的Ajax。
fetch 是一个比较新的API,用来实现CORS通信。用法如下:
// url(必选),options(可选)
fetch('/some/url/', {
method: 'get',
}).then(function (response) { //类似于 ES6中的promise
}).catch(function (err) {
// 出错了,等价于 then 的第二个参数,但这样更好用更直观
});
CORS的推荐链接:http://www.ruanyifeng.com/blo...
推荐链接里有详细的配置。
另外,如果面试官问:“CORS为什么支持跨域的通信?”
答案:跨域时,浏览器会拦截Ajax请求,并在http头中加Origin。
4、Hash
url的#后面的内容就叫Hash。Hash的改变,页面不会刷新。这就是用 Hash 做跨域通信的基本原理。
补充:url的?后面的内容叫Search。Search的改变,会导致页面刷新,因此不能做跨域通信。
使用举例:
场景:我的页面 A 通过iframe或frame嵌入了跨域的页面 B。
现在,我这个A页面想给B页面发消息,怎么操作呢?
(1)首先,在我的A页面中:
//伪代码
var B = document.getElementsByTagName('iframe');
B.src = B.src + '#' + 'jsonString'; //我们可以把JS 对象,通过 JSON.stringify()方法转成 json字符串,发给 B
(2)然后,在B页面中:
// B中的伪代码
window.onhashchange = function () { //通过onhashchange方法监听,url中的 hash 是否发生变化
var data = window.location.hash;
};
5、postMessage()方法
H5中新增的postMessage()方法,可以用来做跨域通信。既然是H5中新增的,那就一定要提到。
场景:窗口 A (http:A.com)向跨域的窗口 B (http:B.com)发送信息。步骤如下。
(1)在A窗口中操作如下:向B窗口发送数据:
// 窗口A(http:A.com)向跨域的窗口B(http:B.com)发送信息
Bwindow.postMessage('data', 'http://B.com'); //这里强调的是B窗口里的window对象
(2)在B窗口中操作如下:
// 在窗口B中监听 message 事件
Awindow.addEventListener('message', function (event) { //这里强调的是A窗口里的window对象
console.log(event.origin); //获取 :url。这里指:http://A.com
console.log(event.source); //获取:A window对象
console.log(event.data); //获取传过来的数据
}, false);
五、性能优化
参考:https://www.jianshu.com/p/fa25121c0f5f
六、vue的mvvm模式
MVVM 是 Model-View-ViewModel 的缩写。
Model代表数据模型,也可以在Model中定义数据修改和操作的业务逻辑。
View代表UI 组件,它负责将数据模型转化成UI 展现出来。
ViewModel监听模型数据的改变和控制视图行为、处理用户交互,简单理解就是一个同步View 和 Model的对象,连接Model和View。
在MVVM架构下,View 和 Model 之间并没有直接的联系,而是通过ViewModel进行交互,Model 和 ViewModel 之间的交互是双向的, 因此View 数据的变化会同步到Model中,而Model 数据的变化也会立即反应到View 上。
ViewModel通过双向数据绑定把 View 层和 Model 层连接了起来,而View 和 Model 之间的同步工作完全是自动的,无需人为干涉,因此开发者只需关注业务逻辑,不需要手动操作DOM, 不需要关注数据状态的同步问题,复杂的数据状态维护完全由 MVVM 来统一管理。
MVVM的优缺点?
优点:
分离视图(View)和模型(Model),降低代码耦合,提高视图或者逻辑的重用性: 比如视图(View)可以独立于Model变化和修改,一个ViewModel可以绑定不同的"View"上,当View变化的时候Model不可以不变,当Model变化的时候View也可以不变。你可以把一些视图逻辑放在一个ViewModel里面,让很多view重用这段视图逻辑
提高可测试性: ViewModel的存在可以帮助开发者更好地编写测试代码
自动更新dom: 利用双向绑定,数据更新后视图自动更新,让开发者从繁琐的手动dom中解放
缺点:
Bug很难被调试: 因为使用双向绑定的模式,当你看到界面异常了,有可能是你View的代码有Bug,也可能是Model的代码有问题。数据绑定使得一个位置的Bug被快速传递到别的位置,要定位原始出问题的地方就变得不那么容易了。另外,数据绑定的声明是指令式地写在View的模版当中的,这些内容是没办法去打断点debug的
一个大的模块中model也会很大,虽然使用方便了也很容易保证了数据的一致性,当时长期持有,不释放内存就造成了花费更多的内存
对于大型的图形应用程序,视图状态较多,ViewModel的构建和维护的成本都会比较高。
七、vue的生命周期
beforeCreate(创建前) 在数据观测和初始化事件还未开始
created(创建后) 完成数据观测,属性和方法的运算,初始化事件,$el属性还没有显示出来
beforeMount(载入前) 在挂载开始之前被调用,相关的render函数首次被调用。实例已完成以下的配置:编译模板,把data里面的数据和模板生成html。注意此时还没有挂载html到页面上。
mounted(载入后) 在el 被新创建的 vm.$el 替换,并挂载到实例上去之后调用。实例已完成以下的配置:用上面编译好的html内容替换el属性指向的DOM对象。完成模板中的html渲染到html页面中。此过程中进行ajax交互。
beforeUpdate(更新前) 在数据更新之前调用,发生在虚拟DOM重新渲染和打补丁之前。可以在该钩子中进一步地更改状态,不会触发附加的重渲染过程。
updated(更新后) 在由于数据更改导致的虚拟DOM重新渲染和打补丁之后调用。调用时,组件DOM已经更新,所以可以执行依赖于DOM的操作。然而在大多数情况下,应该避免在此期间更改状态,因为这可能会导致更新无限循环。该钩子在服务器端渲染期间不被调用。
beforeDestroy(销毁前) 在实例销毁之前调用。实例仍然完全可用。
destroyed(销毁后) 在实例销毁之后调用。调用后,所有的事件监听器会被移除,所有的子实例也会被销毁。该钩子在服务器端渲染期间不被调用。
1.什么是vue生命周期?
答: Vue 实例从创建到销毁的过程,就是生命周期。从开始创建、初始化数据、编译模板、挂载Dom→渲染、更新→渲染、销毁等一系列过程,称之为 Vue 的生命周期。
2.vue生命周期的作用是什么?
答:它的生命周期中有多个事件钩子,让我们在控制整个Vue实例的过程时更容易形成好的逻辑。
3.vue生命周期总共有几个阶段?
答:它可以总共分为8个阶段:创建前/后, 载入前/后,更新前/后,销毁前/销毁后。
4.第一次页面加载会触发哪几个钩子?
答:会触发 下面这几个beforeCreate, created, beforeMount, mounted 。
5.DOM 渲染在 哪个周期中就已经完成?
答:DOM 渲染在 mounted 中就已经完成了。
八、vue组件通讯方式,兄弟组件
Vue 组件间通信只要指以下 3 类通信:父子组件通信、隔代组件通信、兄弟组件通信
(1)props / $emit适用 父子组件通信
这种方法是 Vue 组件的基础,相信大部分同学耳闻能详,所以此处就不举例展开介绍。
(2)ref 与 $parent / $children适用 父子组件通信
ref:如果在普通的 DOM 元素上使用,引用指向的就是 DOM 元素;如果用在子组件上,引用就指向组件实例
$parent / $children:访问父 / 子实例
(3)EventBus ($emit / $on)适用于 父子、隔代、兄弟组件通信
这种方法通过一个空的 Vue 实例作为中央事件总线(事件中心),用它来触发事件和监听事件,从而实现任何组件间的通信,包括父子、隔代、兄弟组件。
(4)$attrs/$listeners适用于 隔代组件通信
$attrs:包含了父作用域中不被 prop 所识别 (且获取) 的特性绑定 ( class 和 style 除外 )。当一个组件没有声明任何 prop 时,这里会包含所有父作用域的绑定 ( class 和 style 除外 ),并且可以通过 v-bind="$attrs" 传入内部组件。通常配合 inheritAttrs 选项一起使用。
$listeners:包含了父作用域中的 (不含 .native 修饰器的) v-on 事件监听器。它可以通过 v-on="$listeners" 传入内部组件
(5)provide / inject适用于 隔代组件通信
祖先组件中通过 provider 来提供变量,然后在子孙组件中通过 inject 来注入变量。 provide / inject API 主要解决了跨级组件间的通信问题,不过它的使用场景,主要是子组件获取上级组件的状态,跨级组件间建立了一种主动提供与依赖注入的关系。
(6)Vuex适用于 父子、隔代、兄弟组件通信
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。“store” 基本上就是一个容器,它包含着你的应用中大部分的状态 ( state )。
Vuex 的状态存储是响应式的。当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新。
改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation。这样可以方便地跟踪每一个状态的变化。
九、vue的路由 hash模式 、 history模式、abstract模式
hash模式:在浏览器中符号“#”,#以及#后面的字符称之为hash,用window.location.hash读取;
特点:hash虽然在URL中,但不被包括在HTTP请求中;用来指导浏览器动作,对服务端安全无用,hash不会重加载页面。
hash 模式下,仅 hash 符号之前的内容会被包含在请求中,如 http://www.xxx.com,因此对于后端来说,即使没有做到对路由的全覆盖,也不会返回 404 错误。
hash 模式的实现原理
早期的前端路由的实现就是基于 location.hash 来实现的。其实现原理很简单,location.hash 的值就是 URL 中 # 后面的内容。比如下面这个网站,它的 location.hash 的值为 '#search':
https://www.abc.com#search
hash 路由模式的实现主要是基于下面几个特性:
URL 中 hash 值只是客户端的一种状态,也就是说当向服务器端发出请求时,hash 部分不会被发送;
hash 值的改变,都会在浏览器的访问历史中增加一个记录。因此我们能通过浏览器的回退、前进按钮控制hash 的切换;
可以通过 a 标签,并设置 href 属性,当用户点击这个标签后,URL 的 hash 值会发生改变;或者使用 JavaScript 来对 loaction.hash 进行赋值,改变 URL 的 hash 值;
我们可以使用 hashchange 事件来监听 hash 值的变化,从而对页面进行跳转(渲染)。
history模式:history采用HTML5的新特性;且提供了两个新方法:pushState(),replaceState()可以对浏览器历史记录栈进行修改,以及popState事件的监听到状态变更。
history 模式下,前端的 URL 必须和实际向后端发起请求的 URL 一致,如 http://www.xxx.com/items/id。后端如果缺少对 /items/id 的路由处理,将返回 404 错误。Vue-Router 官网里如此描述:“不过这种模式要玩好,还需要后台配置支持……所以呢,你要在服务端增加一个覆盖所有情况的候选资源:如果 URL 匹配不到任何静态资源,则应该返回同一个 index.html 页面,这个页面就是你 app 依赖的页面。”
history 模式的实现原理
HTML5 提供了 History API 来实现 URL 的变化。其中做最主要的 API 有以下两个:history.pushState() 和 history.repalceState()。这两个 API 可以在不进行刷新的情况下,操作浏览器的历史纪录。唯一不同的是,前者是新增一个历史记录,后者是直接替换当前的历史记录,如下所示:
window.history.pushState(null, null, path);
window.history.replaceState(null, null, path);
history 路由模式的实现主要基于存在下面几个特性:
pushState 和 repalceState 两个 API 来操作实现 URL 的变化 ;
我们可以使用 popstate 事件来监听 url 的变化,从而对页面进行跳转(渲染);
history.pushState() 或 history.replaceState() 不会触发 popstate 事件,这时我们需要手动触发页面跳转(渲染)。
abstract模式 : 支持所有 JavaScript 运行环境,如 Node.js 服务器端。如果发现没有浏览器的 API,路由会自动强制进入这个模式.
十、VueX状态管理
它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。
state
存放数据的状态,不可以直接修改。
this.$store.state.XX来获取(this.$store.state.app.opened
)
mutations
动态修改vueX的store的状态和数据(this.$store.commit("TOGGLE_SIDEBAR");
)
getter
类似vue的计算属性,用来过滤一些数据
action
异步操作,提交的是 mutation,而不是直接变更状态。store.dispatch('XX')来分发(this.$store.dispatch("app/toggleSideBar");
)
modules
项目特别复杂的时候,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
---app.js
const state = {
opened: true,
openPwdPop:false
}
const mutations = {
TOGGLE_SIDEBAR: state => {
state.opened = !state.opened
},
CHANGE_PWD: (state, isshow) => {
state.openPwdPop = isshow
}
}
const actions = {
toggleSideBar({ commit }) {
commit('TOGGLE_SIDEBAR')
},
showPwdPop({ commit }) {
commit('CHANGE_PWD',true)
},
hidePwdPop({ commit }) {
commit('CHANGE_PWD',false)
},
}
export default {
namespaced: true,//命名空间
state,
mutations,
actions
}
---index.js
import Vue from "vue";
import Vuex from "vuex";
import app from './modules/app'
Vue.use(Vuex);
export default new Vuex.Store({
modules: {
app
}
});
十一、vue全家桶
vue全家桶包含:vue-cli、vue-router、vuex、vue-Devtool调试工具、UI组件库;
十二、vue路由的钩子函数
beforeEach,afterEach等,一般用于页面title的修改。一些需要登录才能调整页面的重定向功能,加页面进度条效果等。
beforeEach主要有3个参数to,from,next:
to:route即将进入的目标路由对象,
from:route当前导航正要离开的路由
next:function一定要调用该方法resolve这个钩子。执行效果依赖next方法的调用参数。可以控制网页的跳转。
router.beforeEach((to, from, next) => {
if (to.meta.title != undefined) {
window.document.title = to.meta.title;
}
if (to.path !== from.path) {
NProgress.start();
}
if (to.matched.some(record => record.meta.requiresAuth)) {
//这里判断用户是否登录,验证本地存储是否有token
if (!window.localStorage.getItem('token')) { // 判断当前的token是否存在
next({path: '/',})
} else {
next();
}
} else {
next(); // 确保一定要调用 next()
}
})
router.afterEach(() => {
NProgress.done();
})
十二、vue面试参考文档
https://segmentfault.com/a/11...
其他问题
8.vue中 key 值的作用?
答:当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用“就地复用”策略。如果数据项的顺序被改变,Vue 将不会移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素。key的作用主要是为了高效的更新虚拟DOM。
9、v-model的理解?
答:v-model用于表单数据的双向绑定,其实它就是一个语法糖,这个背后就做了两个操作:
1)v-bind绑定一个value属性;
2)v-on指令给当前元素绑定input事件
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。