考察点:
① Vue2.0:
(1)Vue的生命周期?
(2)Vue 和 React的区别?
(3)Vue 的双向数据绑定原理?
(4)Vue2 和 Vue3 的区别?
(5)Vue组件通信常用方式?
(6)Vue中computed和watch的区别,那个可以进行异步操作?
(7)Vue的状态管理模式?
(1)Vue的生命周期?
生命周期 | 描述 |
beforeCreate | 组件实例被创建之初 |
created | 组件实例已经完全创建 |
beforeMount | 组件挂载之前 |
mounted | 组件挂载到实例上去之后 |
beforeUpdate | 组件数据发生变化,更新之前 |
updated | 组件数据更新之后 |
beforeDestroy | 组件实例销毁之前 |
destroyed | 组件实例销毁之后 |
activated | keep-alive 缓存的组件激活时 |
deactivated | keep-alive 缓存的组件停用是调用 |
errorCaptured | 捕获一个来自子孙组件的错误时被调用 |
(2)Vue 和 React的区别?
① 监听数据变化的实现原理不同
vue 使用代理/拦截的方式,通过getter/setter 以及修改data就能精准知道数据变化,而react使用setState api来实现。vue要知道修改了哪些内容通过watch/computed等钩子供开发人员使用,但react需要通过业务逻辑层diff才知道。
② 数据绑定不同
vue是双向绑定,vue最核心的功能有两个:一是响应式的数据绑定系统,二是组件系统。
③ 组件通信不同
Vue中有三种方式可以实现组件通信:
- 父组件通过props向子组件传递数据或者回调,虽然可以传递回调,但一般只传数据;
- 子组件通过事件向父组件发送消息;
- 通过V2.0中新增的provide/inject来实现父组件向子组件注入数据,可以跨越多个层级。
React中也有对应的三种方式:
- 父组件通过props可以向子组件传递数据或者回调;
- 可以通过 context 进行跨层级的通信,这其实和 provide/inject 起到的作用差不多。
④ 框架本质不同
Vue本质是MVVM框架,由MVC发展而来;
React是前端组件化框架,由后端组件化发展而来。
react和vue的优缺点
Vue的优缺点:简单、快速、强大、对模块友好,但不支持IE8。
React的优缺点:速度快、跨浏览器兼容、模块化;但学习曲线陡峭,需要深度的知识来构建应用程序。
(3)vue的双向数据绑定原理?
vue 的双向绑定由三个重要部分构成:数据层Model、视图层View、业务逻辑层ViewModel
- 数据层(Model):应用的数据及业务逻辑
- 视图层(View):应用的展示效果,各类UI组件
- 业务逻辑层(ViewModel):框架封装的核心,它负责将数据与视图关联起来
ViewModel:由两个主要部分组成
监听器(Observer):对所有数据的属性进行监听。
解析器(Compiler):对每个元素节点的质量进行扫描根解析,根据指令模版替换数据,以及绑定相应的更新函数。
双向绑定:(发布订阅 更新回调)
new Vue()
首先执行初始化,对data
执行响应化处理,这个过程发生Observe
中- 同时对模板执行编译,找到其中动态绑定的数据,从
data
中获取并初始化视图,这个过程发生在Compile
中 - 同时定义⼀个更新函数和
Watcher
,将来对应数据变化时Watcher
会调用更新函数 - 由于
data
的某个key
在⼀个视图中可能出现多次,所以每个key
都需要⼀个管家Dep
来管理多个Watcher
- 将来data中数据⼀旦发生变化,会首先找到对应的
Dep
,通知所有Watcher
执行更新函数
(4)vue2 和 vue3的区别?
https://blog.csdn.net/m0_64346035/article/details/124855972
1.vue2和vue3的双向数据绑定原理发生了改变。
vue2 双向数据绑定是利用ES5中的一个API Object.definePropert()对数据进行劫持 结合 发布订阅模式的方式来实现的。
(vue2的双向数据绑定原理通过object.defineProperty中的set方法来实现数据劫持,但是无法监听数组内部的数据变化)
vue3 使用ES6语法的proxy对象来实现双向数据绑定的,可以检测到数组内部数据的变化。
Proxy用于修改某些操作的默认行为,相当于在目标对象之前架设一层拦截,外部所有的访问都必须先通过这层拦截,因此提供了一种机制,可以对外部的访问进行过滤和修改。
2. vue3支持碎片化(Fragments)
// vue2
<template>
<div class='form-element'>
<h2> {{ title }} </h2>
</div>
</template>
// vue3
<template>
<div class='form-element'>
</div>
<h2> {{ title }} </h2>
</template>
3. Composition API
Vue2 与vue3 最大的区别是vue2使用选项类型api,对比vue3合成型api。
旧得选项型api在代码里分割了不同得属性:data,computed,methods等;
4. 建立数据data
vue2-把数据放入data属性中
export default {
props:{
title: String
},
data(){
return {
username: '',
password: ''
}
}
}
在Vue3.0 需要使用一个新的setup() 方法,次方法在组件初始化构造时触发。
import { reactive } from 'vue'
export default {
props: {
title: String
},
setup(){
const state = reactive({
username: '',
password: ''
})
return { state }
}
}
5. 生命周期钩子 Hooks
Vue2 | Vue3 |
beforeCreate | setup() |
created | setup() |
beforeMount | onBeforeMount |
Mounted | onMounted |
beforeUpdate | onBeforeUpdate |
update | onUpdated |
beforeDestroy | onBeforeUnmount |
destroyed | onUnmountd |
activate | onActivated |
deactivate | onDeactived |
(5)Vue组件通信常用方式?
组件间通信分类可以分为:
· 父子组件之间的通信
· 兄弟组件之间的通信
· 祖孙与后代组件之间的通信
· 非关系组件间的通信
Vue的8种通信方案:
1. 通过props 传递
2. 通过$emit 触发自定义事件
3. 使用ref
4. EventBus
5. parent 或 root
6. attrs 或 listeners
7. Provide 与 inject
8. Vuex
(6)Vue中computed和watch的区别,那个可以进行异步操作?
· computed 是计算属性,依赖其他属性计算值,并且 computed 的值有缓存,只有当计算值变化才会返回内容。
· watch 监听到值的变化就会执行回调,在调用中可以进行一些逻辑操作。
所以一般来说,需要依赖别的属性来动态获得值的时候可以使用computed,对于监听到值的变化需要做一些复杂业务逻辑的情况可以使用 watch
。
另外 computer
和 watch
还都支持对象的写法,这种方式知道的人并不多。
(7)Vue的状态管理模式?
② 服务器上部署
① 购买阿里云域名和远程服务器,进行域名解析和实名制认证;
将前端项目npm run build打包之后生成一个dist文件夹(静态文件 - 静态文件是经过压缩的,所以代码加载速度更快),
② 然后把这个文件夹放在服务器上一个目录下,记住这个目录路径,开一个对应的端口号。
③ 然后在nginx配置中将这个端口号和路径进行映射(nginx前端配置),再重启nginx就可以了(解决前后端跨域问题)。
④ 再进入前端页面即可。
③ Element-UI 搭建Component组件(三栏布局 十二分栏布局如何实现)
三栏布局:
- 两边使用 float,中间使用 margin
- 两边使用 absolute,中间使用 margin
- 两边使用 float 和 负 margin
- display:table 实现
- grid 网格布局
④ axios 进行二次封装,⑤ 设置请求拦截器、响应拦截器
对 axios 进行二次封装,设置request拦截器请求token进行异步处理,对身份进行认证;设置response拦截器作全局状态统一处理,根据请求得到的res.code状态码判断用户登录情况,并给出提示;
axios 是一个轻量级的 Http 客户端,基于XMLHttpRequest服务来执行Http请求,支持丰富的配置,支持Promise,支持浏览器端和Node.js端。
特性:
- 从浏览器中创建
XMLHttpRequests
- 从
node.js
创建http
请求 - 支持
Promise
API - 拦截请求和响应
- 转换请求数据和响应数据
- 取消请求
- 自动转换
JSON
数据 - 客户端支持防御
XSRF
设置 请求头、状态码state、请求方法 get/post、请求拦截器(根据请求的请求头设定,来决定哪些请求可以访问)、响应拦截器(根据后端返回的状态码判定执行不同的业务)
// 发送请求
import axios from 'axios'
axios(config) // 直接传入配置
axios(url[ , config]) // 传入url和配置
axois[method](url[, option]) // 直接调用请求方式方法,传入url和配置
axois[method](url[, data[, option]]) // 直接调用请求方式方法,传入data、url和配置
axois.request(option) // 调用request方法
const axiosInstance = axois.create(config)
// axiosInstance 也具有以上 axios 的能力
axios.all([axiosInstance1, axiosInstance2]).then(axios.spread(response1, response2))
// 调用 all 和传入 spread 回调
// 请求拦截器
axois.interceptors.request.use(function(config){
// 写发送请求前处理的代码
return config;
},function(error){
// 写发送请求错误相关的代码
return Promise.reject(error);
});
// 响应拦截器
axois.interceptor.response.use(function(response){
// 这里写得到响应数据后处理的代码
return response;
}, function(error){
// 这里写错误响应处理的代码
return Promise.reject(error);
});
《程序喵》项目的请求/响应处理:
// import axios from 'axios'
// import {Message} from 'element-ui'
import store from '@/store'
import {getToken} from '@/request/token'
const service = axios.create({
baseURL: process.env.BASE_API,
timeout: 10000
})
//request拦截器
service.interceptors.request.use(config => {
if (store.state.token) {
config.headers['Oauth-Token'] = getToken()
}
return config
}, error => {
Promise.reject(error)
})
// respone拦截器
service.interceptors.response.use(
response => {
//全局统一处理 Session超时
if (response.headers['session_time_out'] == 'timeout') {
store.dispatch('fedLogOut')
}
const res = response.data;
//0 为成功状态
if (res.code !== 200) {
//90001 Session超时
if (res.code === 90001) {
return Promise.reject('error');
}
//20001 用户未登录
if (res.code === 90002) {
this.$message({
type: 'warning',
showClose: true,
message: '未登录或登录超时,请重新登录哦'
})
return Promise.reject('error');
}
//70001 权限认证错误
if (res.code === 70001) {
this.$message({
type: 'warning',
showClose: true,
message: '你没有权限访问哦'
})
return Promise.reject('error');
}
return Promise.reject(res.msg);
} else {
return response.data;
}
},
error => {
this.$message({
type: 'warning',
showClose: true,
message: '连接超时'
})
return Promise.reject('error')
})
export default service
简易版 axois:
class Axios {
constructor() {
}
request(config) {
return new Promise(resolve => {
const {url = '', method = 'get', data = {}} = config;
// 发送ajax请求
const xhr = new XMLHttpRequest();
xhr.open(method, url, true);
xhr.onload = function() {
console.log(xhr.responseText)
resolve(xhr.responseText);
}
xhr.send(data);
})
}
}
⑤ 登录过程 即 过滤拦截器的使用:
若依登陆过程及过滤器拦截器的使用:
用户登陆接口:
1、 把用户信息通过uuid即token作为key,存储在缓存中,并设置过期时间。
2、通过jwt存储token,userId,userName在map中,设置过期时间,通过jwt(Json Web Token)创建一个编码后 access_token和expireTime,并返回token在前端。
3、过滤器:用户前端传递的access_token通过Jwt解析,尝试获取userkey(即token),userid,username并判断是否过期,为空等。如果异常即刻报错,否则将解析的userkey,userid,username纳入请求头中,请求接着交给拦截器。
4、拦截器:拦截器从请求头中获取userkey,userid,username,通过userkey从缓存中获取用户信息,并刷新缓存中用户信息的过期时间。并将用户信息加入到本地的 TransmittableThreadLocal<Map<String, Object>>中,方便用户获取当前用户信息。
⑥ token进行身份认证
https://blog.csdn.net/qq_19322833/article/details/127152528
token 的登录流程:
1. 客户端用账户密码请求登录;
2. 服务器收到请求后,需要去验证账号密码;
3. 验证成功之后,服务端会签发一个token,把这个 token 发送给客户端;
4. 客户端收到 token 后保存起来,可以防止 cookie 也可以是 localstorage;
5. 客户端每次向服务器发送请求资源的时候,都需要携带这个 token;
6. 服务器收到请求,接着去验证客户端里的 token,验证成功后才会返回客户端请求的数据。
=> 根据《程序喵》项目做对应说明:(这个流程 要改)
本地对 登录注册的username和password是通过session还是cookie哪一种方式进行存储的?
vue项目解决思路:
前端:vue2、vue-router、axios
后端:Node.js、express-generator、jsonwebtoken
前端方面:用到vue-router导航守卫 和 Axois的请求拦截器,前者主要验证用户是否登录,后者主要实现验证token是否过期。
将token存放到localStorage 通过封装好的Axios方法获取到后端返回的 token 并存入 localStorage
this.$network({
url: `adminLogin?account=${form.account}&password=${form.password}`,
}).then((res) => {
// 判断请求是否正常请自行发挥
if (res.code == 200) {// 如果正常
//将后端返回的token存入localStorage
localStorage.setItem("token", res.token);
}
})
vue-router的导航守卫:router.beforeEach
通过导航守卫进行 本地是否登录判断,判断当前页面是否是登录注册页(或其他需要排除的页面),如果是 则进行是否 已登录 验证;如果不是,则进行是否未登录验证。
// 注:这里我们使用的是 `router.beforeEach`
if (to.fullPath == '/login') {// 排除页面
if (localStorage.getItem('token') != null) {
console.log('您已登录,是否访问首页?');
}
} else if (localStorage.getItem('token') == null) {
// 如果访问的是其它路由页面而且token不存在,即为未登录
localStorage.clear();// 清除一次 localStorage
console.log('您未登录,是否访问登录页?');
return
}
Axio的拦截器 通过axois的请求拦截器interceptors 进行请求前、请求后的事件。
请求前:interceptors.request 首先需要在 请求前 interceptors.request
里将 token
放到 headers中的Authorization中
,以便 每次发起网络请求时携带
。
// 请求前 interceptors.request
config.headers.Authorization = localStorage.getItem("token");
请求后:请求后 interceptors.response
里进行token是否过期验证
// 请求后 interceptors.response
if (window.location.pathname != '/login') {// 排除页面
if (res.data.loginStatus == false) {// 如果token已过期
localStorage.clear();// 清除一次 localStorage
console.log('登录状态已失效,是否访问登录页?');
}
}
后端方面:使用Node.js 实现
// token验证,生成时和请求验证时的都可以调用!返回token状态,false为已过期
function tokenVerify(token) {
let status;
jwt.verify(token, 'userLogin', (err, data) => {
if (err) {// 过期token
status = false
} else {// 有效token
status = true
}
})
return status
}
// token生成,只用于登录时调用!通过调用token验证函数,判断token是否过期,
// 若未过期,则返回true,前端token值不变;若过期,则重新生成,前端重新保存token
function tokenGenerate(token, account, password, time) {
let status = tokenVerify(token);
if (status) {// 若token未过期
token = true;
} else {// 若token已过期
token = jwt.sign({
account: account,
password: password },
'userLogin', { expiresIn: time });
}
return token
}
⑦ vuex 对博客进行全局状态管理
还可以使用react-redux进行全局状态管理。
import Vue from 'vue'
import Vuex from 'vuex'
Vue.use(Vuex)
export default new Vuex.Store({
//数据,相当于data
state: {
//数据源 提供唯一的公共数据源,所有共享的数据统一放到store的state进行储存,相似data.
},
getters: {
//类似于vue中的computed,进行缓存,对于Store中的数据进行加工处理形成新的数据
},
//里面定义方法,操作state方发
mutations: {
//每个 mutation 都有一个字符串的事件类型 (type)和一个回调函数 (handler)
},
// 操作异步操作mutation
actions: {
//进行异步操作
},
modules: {
//Vuex 允许我们将 store 分割成模块(module)。每个模块拥有自己的 state、mutation、action、getter、甚至是嵌套子模块——从上至下进行同样方式的分割
},
})
⑧ session/storage 存储数据
Cookie、sessionStorage和localStorage的区别
(一)Cookie、sessionStorage和localStorage的区别
共同点:都是保存在浏览器端,且同源的。
区别:
cookie数据始终在同源的http请求中携带,即 cookie在浏览器和服务器间来回传递,而sessionStorage和localStorage不会自动把数据发送给服务器,仅在本地保存。
存储大小限制:cookie数据不能超过4k,只适合保存很小的数据,如会话标识。sessionStorage和localStorage可以达到5M或更多。
数据有效期不同:sessionStorage:仅在当前浏览器窗口关闭之前有效;localStorage:始终有效,窗口或浏览器关闭也一直保存,因此作用更持久;cookie:只在设置的cookie国企时间之前有效,即使窗口关闭或浏览器关闭。
作用域不同:sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面;localstorage在所有同源窗口中都是共享的;cookie在所有同源窗口中都是共享的。
cookie和session的区别
1、数据位置:cookie数据存放在客户的浏览器上,session数据放在服务器上
2、安全性:cookie不是很安全,别人可以分析存放在本地的cookie并进行cookie欺骗,考虑到安全应
当使用session
3、性能:session会在一定时间内保存在服务器上,当访问增多,会比较占用你服务器的性能,考虑到
减轻服务器性能方面,应当使用cookie
4、数据量:单个cookie保存的数据不能超过4K,很多浏览器都限制一个站点最多保存20个cookie
5、信息存放:建议将登录信息等重要信息存放为session,其他信息如果需要保留,可以放在cookie中
6、保存位置:session保存在服务器,客户端不知道其中的信心;cookie保存在客户端,服务器能够知
道其中的信息
7、保存对象:session中保存的是对象,cookie中保存的是字符串
8、路径:session不能区分路径,同一个用户在访问一个网站期间,所有的session在任何一个地方都可
以访问到,而cookie中如果设置了路径参数,那么同一个网站中不同路径下的cookie互相是访问不到
的。
9、COOKIE:是服务端向客户端写入的小的片段信息。cookie信息保存在服务器缓存区,不会在客户端显
现。当你第一次登陆一个网站,服务器向你的机器写得片段信息。你可以在Internet选项中找到存放
cookie的文件夹。如果不删除,cookie就一直在这个文件夹中。
10、session需要借助cookie才能正常工作。如果客户端完全禁止cookie,session将失效。 但是如果服务器端启用了url编码,也就是用 URLEncoder.encode()把所有的url编码了,则会在url后面出现如下类似的东西 index.jsp:jsessionid=fdsaffjdlks;jaf;lkdjsf 服务器通过这个进行session的判断。
11、Cookie支持跨域名访问,例如将domain属性设置为“.biaodianfu.com”,则以“.biaodianfu.com”为后缀的一切域名均能够访问该Cookie。跨域名Cookie如今被普遍用在网络中,例如Google、Baidu、Sina等,而Session则不会支持跨域名访问。Session仅在他所在的域名内有效。仅运用Cookie或者仅运用Session可能完成不了理想的效果。这时应该尝试一下同时运用Cookie与Session。Cookie与Session的搭配运用在实践项目中会完成很多意想不到的效果。
⑨ git 仓库进行项目管理
git init 进行Git 仓库的创建
git add readme.md 把文件添加到版本库
git reset --hard HEAD^ 版本回退
git checkout -- readme.md 撤销修改
git remote add origin git@github.com:luxinfeng/GitTest.git 添加远程库(GitHub)
git branch dev 创建/合并分支
⑩ 跨域问题
跨域问题:由于浏览器的 同源策略 限制,当一个请求url的协议、域名、端口号三者之间有任意一个与当前的url不同即为跨域。
同源策略是一种约定,它是浏览器中最核心也最基本的安全功能。同源策略会阻止一个域的 Javascript 脚本和另一个域的内容进行交互。
同源(即指在同一个域)就是两个页面具有相同的协议(protocol)、主机(host) 和 端口号 (port)。
博客系统项目中出现跨域问题 是由于这是前后端分离项目,前端访问路径的端口和后端访问路径的端口不一致,因此出现了跨域问题,解决方案是对前端做跨域配置。
常见解决跨域问题的方式:
1. 使用 jsonp 来实现跨域请求:(jsonp函数封装)JSONP 方式实现跨域请求数据_jsonp跨域请求实现示例_TKOP_的博客-CSDN博客
原理:通过动态构建 script 标签来实现跨域请求, 因为浏览器对 script 标签的引入没有跨域的访问限制。
过程:通过在请求的url后指定一个回调函数,然后服务器在返回数据的时候,构建一个json数据的包装,这个包装就是回调函数,然后返回给前端。
前端接受到数据后,因为请求的是脚本文件 所以会直接执行,这样之前定义好的回调函数就可以被调用,从而实现了跨域请求的处理。
<body>
<h2>A服务器的页面</h2>
<button id="btn">向B发送jsonp请求</button>
<script type="text/javascript">
var btn = document.getElementById('btn');
function jsonp(options) {
// 处理其他参数的拼接
var params = '';
for (var k in options.data) {
params += '&' + k + '=' + options.data[k];
}
// 响应处理函数
var fnName = 'myJsonp' + Math.random().toString().replace('.', '');
window[fnName] = options.success;
// 请求完整地址
var url = options.url + '?callback=' + fnName + params;
// 创建script标签
var script = document.createElement('script');
// 设置script标签的src属性
script.src = url;
// 将script标签追加到页面中
document.body.appendChild(script);
// 在script标签追加完成请求发送后将其删除
script.onload = function() {
document.body.removeChild(script);
window[fnName] = null;
}
}
btn.onclick = function() {
jsonp({
// 地址
url: 'http://localhost:3001/jsonp3',
// 其他请求参数
data: {
name: 'tkop',
age: 18
},
// 响应处理函数
success: function(data) {
console.log(data);
}
})
}
</script>
</body>
2. 使用 CORS 的方式:
跨越资源共享CORS,它运行浏览器向跨源服务器发出 XMLHttpRequest 或 Fetch 请求。目前浏览器都支持这个功能,只需要服务器设置 Access-Control-Allow-Origin 就可以开启 CORS。
app.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*')
ctx.set('Access-Control-Allow-Headers','Content-Type,Content-Length,Authorization,Accept,X-Requested-With')
ctx.set('Access-Control-Allow-Methods', 'PUT,POST,GET,DELETE,OPTIONS')
if (ctx.method === 'OPTIONS') {
ctx.body = 200;
} else {
await next()
}
});
3. 使用 Node
同源策略是浏览器需要遵循的标准,如果是服务器 向 服务器 请求 就无需遵循同源策略。
所以可以使用Node中间件代码(两次跨域):
接受客户端请求 → 将请求转发给服务器 → 拿到服务器响应数据 → 将响应转发给客户端
4. 使用代理服务器
有跨域的请求操作时发送请求给后端,让后端代为请求,然后最后将获取的结果返回。因为服务器没有跨域接口限制。
module.exports = {
NODE_ENV: '"production"',
// BASE_API: '"http://www.wanqi.ink:8888"'
BASE_API: '"http://8.134.24.26:8888"'
}
(11)网页执行异常
产生的原因:语法错误、运行时错误、逻辑错误、网络错误、跨域问题、DOM操作错误、异步代码执行顺序问题、资源加载顺序问题、内存泄漏等。
Http 状态码:
- 1XX:表示目前是协议处理的中间状态,还需要后续操作。
- 2XX:表示成功状态。
- 3XX:重定向状态,资源位置发生变动,需要重新请求。
- 4XX:请求报文有误。
- 5XX:服务器端发生错误。
-
101 Switching Protocols :在 HTTP 升级为 WebSocket 的时候,如果服务器同意变更,就会发送状态码为 101 。
-
200 OK :请求成功状态码,响应体中含有数据。
-
204 No Content :含义同 200 ,但是响应报文不含实体的主体部分。
-
206 Partial Content :表示部分内容请求成功。使用场景为 HTTP 分块下载和断点续传,当 然也会带上相应的响应头字段 Content-Range 。
-
301 Move Permanently :永久重定向。 HTTP 升级 HTTPS ,之前站点再也不用,那就是 301。
-
302 Found :临时重定向。当前站点暂时不可用,那就是 302 ,后续可能换回来。
-
304 Not Modified :当命中协商缓存时会返回这个状态码。
-
400 Bad Request :请求无效。通常为前后端数据格式不一致或者其他原因。
-
403 Forbidden :服务器已经得到请求,但是拒绝执行,比如没权限、法律禁止等。
-
404 Not Found :资源未找到,服务器不存在对应的资源。
-
500 Internal Server Error :服务器报错,有些时候可以在 Response 看到后端 PHP 等技 术的报错信息等。
-
502 Bad Gateway :服务器正常,但是访问出错。
-
503 Service Unavailable :服务器繁忙或者停机维护,暂时无法处理请求。
-