vue的双向绑定原理是什么?里面的关键点在哪里?
- 双向绑定是采用数据劫持,结合发布者,订阅者模式的方式,通过Object.difineProperty来劫持各个属性的setter和getter
- 然后当数据发生改变时发布信息给订阅者,触发对对应的监听回调,去实现数据的双向绑定
- 关键点在于Object.defineProperty方法去劫持属性
现水平垂直居中的方式?
- flex布局居中
- 绝对定位
- tabel-cell垂直居中
- gril设置居中
- 容器添加微元素,等同容器高度,子级设置display:inline-block
- 容器固定宽高,相对定位,上左下右为0,margin为默认
用伪元素有哪一些?
- :first-letter 向文本的第一个字母添加特殊样式
- :first-line 向文本的首行添加特殊样式
- :before 在元素之前添加内容
- :after 在元素之后添加内容
- :placeholder 匹配占位符,不过该元素设置了placeholder属性,伪元素才会生效
- :selection CSS伪元素应用于文档中被用户高亮的部分
移动动端如何适配不同屏幕尺寸?
- 使用js去修改rem的大小
- 媒体查询去匹配
- flex布局
本地存储有哪一些?他们三者有什么区别?
cookie,sessionStorage,localStorage
- 存储大小区别,cookie数据大小不超过4k。localStorage和sessionStorage数据大小5mb,不过跟浏览器厂商有关系
- 有效时长区别,cookie设置的会⼀直有效。即使窗⼝或浏览器关闭,localStorage持久化的本地存储,除非主动删除数据,否则数据是永远不会过期的。sessionStorage和
localStorage使用方法基本一致,唯一不同的是生命周期,一旦页面会话关闭,sessionStorage 将会删除数据 - 交互方式区别,cookie的数据会主动向服务器传递。sessionStorage和localStorage不会自动把数据发给服务器,仅在本地保存
JS的数据类型?如何判断js的数据类型?
js的数据类型分为两种,基本数据类型、引用数据类型
- 基本数据类型:string,number,null,undefined,boolean
- 引用数据类型:array,function,object
- 判断数据类型的方法
- typeof,instanceof,constructor,object.prototype.tostring.call()
讲一下ES6的新特性有哪些?
- 新增了let、const、symbol关键字
- 新增解构赋值
- 数据类型判断
- 新增了模块化,export和import
- promise
- 新增class关键字
- 模板字符串
- Map和Met
let、const、var三者有什么区别?
- var存在变量提升,let和const不存在变量提升
- var定义的变量可以被声明多次。let和const不能声明多次,会报错
- var和let声明的变量可以被再次赋值,const声明的变量不能再次赋值
- var声明的变量没有自身的作用域,而let、const声明的变量有自身的作用域
数组去重有哪些办法?
- 新增构造函数set,利用set具有天然去重功能
- 数组迭代
说一下深拷贝和浅拷贝,如何自己实现一个深拷贝?
- 浅拷贝创造新的数据,对原有数据属性值得一份精确拷贝
let a=[0,1,2,3,4], b=a;
console.log(a===b);
a[0]=1;
console.log(a,b);
- 深拷贝开辟一个新的栈,两个对象完全相同,但是对应不同的地址,修改一个对象的属性,不会改变另一个对象的属性
//原理其实很简单,先将对象转成JSON字符串后并复制一份,再通过stringfy还原成对象,依次达到深拷贝的目的:
function deepClone(obj) { // 转JSON字符串并复制
let _obj = JSON.stringify(obj),
// 还原成对象
objClone = JSON.parse(_obj);
return objClone
}
let a = [0, 1, [2, 3], 4], b = deepClone(a);
a[0] = 1;
a[2][0] = 1;
console.log(a, b);
两者区别在于浅拷贝只拷贝属性指向某个对象的指针,而不是对象本身,修改拷贝后的数据,原数据也会修改。深拷贝则会创造一个一模一样的对象,新对象与原对象不共享内存,修改新对象的数据不会对原数据进行修改
Vue的生命周期有哪一些?说一下它们每个阶段做什么操作?
Vue实例从创建到销毁的过程,就是生命周期。 也就是:开始创建->初始化数据->编译模板->挂载dom->数据更新重新渲染虚拟 dom->最后销毁。这一系列的过程就是vue的生命周期。所以在mounted阶段真实的DOM就已经存在了
组件通讯方式有哪一些?
-
Props适用于父传子,也适用于子传父(首先要求父组件给子组件传一个函数用来接收回调)
-
绑定自定义事件
-
全局事件总线eventBus
-
ref和#ref
-
provide/inject
-
parent和children
parent和$children这两种方法是直接获取组件实例,可以直接调组件的方法或者数据
-
Vuex
Vuex有几个属性及作用?
Vuex 的 5 个核心属性分别是 State、 Getter、Mutation 、Action、 Module
- state 为单一状态树,在 state 中需要定义我们所需要管理的数组、对象、字符 串等等,只有在这里定义了,在 Vue.js 的组件中才能获取你定义的这个对象的状态。
- getter 有点类似 Vue.js 的计算属性,当我们需要从 store 的 state 中派生出一些 状态,那么我们就需要使用 getter,getter 会接收 state 作为第一个参数,而且 getter
的返回值会根据它的依赖被缓存起来,只有 getter 中的依赖值(state 中的某个需 要派生状态的值)发生改变的时候才会被重新计算。 - 更改 store 中 state 状态的唯一方法就是提交 mutation,就很类似事件。每个 mutation 都有一个字符串类型的事件类型和一个回调函数,我们需要改变 state
的值就要在回调函数中改变。我们要执行这个回调函数,那么我们需要执行一个 相应的调用方法:store.commit。 - action 可以提交 mutation,在 action 中可以执行 store.commit,而且 action 中可 以有任何的异步操作。在页面中如果我们要调用这个 action,则需要执行 store.dispatch
- module模块化其实只是解决了当state中很复杂臃肿的时候,module可以将store 分割成模块,每个模块中拥有自己的 state、mutation、action 和 getter
Vue的监听属性和计算属性有什么区别?
computed特性
- 是计算值,
- 应用:就是简化tempalte里面{{}}计算和处理props或$emit的传值
- 具有缓存性,页面重新渲染值不变化,计算属性会立即返回之前的计算结果,而不必再次执行函数
watch特性
- 是观察的动作,
- 应用:监听props,$emit或本组件的值执行异步操作
- 无缓存性,页面重新渲染时值不变化也会执行
说一下防抖和节流。怎么实现?
防抖:高频事件下,控制执行最后一次
function debounce(func, wait) { var timeout; return function () { clearTimeout(timeout) timeout = setTimeout(func, wait); } } function get() { setTimeout(()=>{ console.log('111') },3000) } debounce(get(),3000)
节流:高频事件下,控制(函数)执行的次数。也就是一个单位时间内,只允许执行1次。
function throttle(func, wait) {
var context, args;
var previous = 0;
return function () {
var now = +new Date();
context = this;
args = arguments;
if (now - previous > wait) {
func.apply(context, args);
previous = now;
} // 时间没到,啥都不干 } } function get() { setTimeout(()=>{ console.log('111')
}, 3000
)
}
throttle(get(), 3000)
Vue的导航守卫有哪一些?
- 全局前置守卫beforeEach
- 全局解析守卫beforeResolve
- 路由独享的守卫beforeEnter
- 组件内的守卫beforeRouteEnter、beforeRouteLeave
你的登录拦截怎么实现的?
闭包是什么?如何实现?
-
闭包是指能够读取其他函数内部变量的函数
-
实现方法,在函数的内部,定义一个函数,把内部函数座位返回值
function a() {
var num = 10;
return function () {
console.log(num);
}
}
var b = a();
b();
Vue2.0和vue3.0有什么区别?
vue3相对于vue2来说更小更快
-
vue2采用的是面向对象变成,vue3采用的是函数式变成
-
vue3修改了细腻dom算法,只针对变化的层进行diff,而vue2是对所有的dom进行diff
-
加强了typescript的支持
-
api一致性,提高可维护能力
-
把更多的底层功能开放出来,比如render,依赖收集功能
-
vue2使用的是defineProperty,vue3使用的是proxy
Vue常用的指令有哪些?
v-if、v-for、v-show、v-bind、v-model、v-on等
v-If和v-show有什么区别?
v-if会操纵dom实行添加删除操作,v-show使用display来实现显示和隐藏
v-for为什么要加一个key?
key是给每一个vnode的唯一id,也是diff的一种优化策略,可以根据key,更准确, 更快的找到对应的vnode节点
你是如何封装一个组件的?
创建封装成全局组件的文件、构建组件结构、注册组件、使用组件
有自己从0到1搭建过项目吗?
如果有,引文:从0到1搭建一个前端项目,具体过程
-
项目启动
-
项目搭建初始化
-
项目功能配置
-
项目优化配置
有用过uni-app吗?
。。。
你会写后台吗?有搞过服务端渲染吗?
。。。
说一下你项目中遇到的难点,如何解决?
。。。
Url到浏览器的一个过程有哪些步骤?
-
用户在浏览器输入url
-
浏览器解析域名得到服务器ip地址
-
Tcp三次握手建立客户端和服务端的链接
-
客户端发送http请求获取服务器端的静态资源
-
服务器发送HTTP响应报文给客户端,客户端获取到页面静态资源
-
TCP四次挥手关闭客户端和服务器的连接
-
浏览器解析文档资源并渲染页面
如何实现小程序的request封装及拦截?
-
创建一个request.js
-
确定http、upload和websocket前缀
-
封装wx.request
-
导出模块
-
使用request
-
拦截器完整代码
const apiHttp = "https://*****.com";
const socketHttp = "wss://*****.com/wss";
function fun(url, method, data, header) {
data = data || {};
header = header || {};
let sessionId = wx.getStorageSync("UserSessionId");
if (sessionId) {
if (!header || !header["SESSIONID"]) {
header["SESSIONID"] = sessionId;
}
}
wx.showNavigationBarLoading();
let promise = new Promise(function (resolve, reject) {
wx.request({
url: apiHttp + url,
header: header,
data: data,
method: method,
success: function (res) {
if (typeof res.data === "object") {
if (res.data.status) {
if (res.data.status === -200) {
wx.showToast({
title: "为确保能向您提供最准确的服务,请退出应用重新授权",
icon: "none"
});
reject("请重新登录");
} else if (res.data.status === -201) {
wx.showToast({
title: res.data.msg,
icon: "none"
});
setTimeout(function () {
wx.navigateTo({
url: "/pages/user/supplement/supplement"
});
}, 1000);
reject(res.data.msg);
}
}
}
resolve(res);
},
fail: reject,
complete: function () {
wx.hideNavigationBarLoading();
}
});
});
return promise;
}
function upload(url, name, filePath) {
let header = {};
let sessionId = wx.getStorageSync("UserSessionId"); //从缓存中拿该信息
if (sessionId) {
if (!header || !header["SESSIONID"]) {
header["SESSIONID"] = sessionId; //添加到请求头中
}
}
wx.showNavigationBarLoading();
let promise = new Promise(function (resolve, reject) {
wx.uploadFile({
url: apiHttp + url,
filePath: filePath,
name: name,
header: header,
success: function (res) {
resolve(res);
},
fail: reject,
complete: function () {
wx.hideNavigationBarLoading();
}
});
});
return promise;
}
module.exports = {
apiHttp: apiHttp,
socketHttp: socketHttp,
"get": function (url, data, header) {
return fun(url, "GET", data, header);
},
"post": function (url, data, header) {
return fun(url, "POST", data, header);
},
upload: function (url, name, filePath) {
return upload(url, name, filePath);
}
};
在vue的项目应用中,不使用框架,怎么封装?
- 创建vue实例
<div id="app">
//里面引入公共组件
<com></com>
</div>
- 定义外部vue模板组件,且是公共组件
<template id="box">
<div>
<h1>我是一个公共组件</h1>
</div>
</template>
var app = new Vue({
el: '#app',
data: {},
method: {},
});
- 开始封装公共组件
Vue.component('com', {
template: '#box'
})
什么是Js原型?原型链是什么?
原型在JavaScript是一个很重要的概念,它是面向对象可以继承的基础。知道吗,JavaScript的设计模式就是原型模式(二十三个经典设计模式之一),正是因为它有这个模式,所以它才十分的灵活。可以基于原型模式实现更多的面向对象设计模式。
原型链是原型的查找机制,是一条寻址链。其实原型上的方法或属性查找,都是按照一定的顺序沿着原型链进行查找的。如果查找到最后仍然没有找到这个原型和方法,那么就真的没有了
用闭包的原理做过哪些?
闭包是什么
闭包是一种特殊的对象。 它由两部分组成。执行上下文(代号A),以及在该执行上下文中创建的函数(代号B)。
当B执行时,如果访问了A中变量对象中的值,那么闭包就会产生。
在大多数理解中,包括许多著名的书籍,文章里都以函数B的名字代指这里生成的闭包。而在chrome中,则以执行上下文A的函数名代指闭包。
闭包的应用场景分为柯里化和模块化
- 函数柯里化就是我们给一个函数传入一部分参数,此时就会返回一个函数来接收剩余的参数。
- 模块化开发是一种管理方式,一种生产方式,一种解决问题的方案。一个模块就是实现某个特定功能的文件,我们可以很方便的使用别人的代码,想要什么模块,就引入那个模块。
作用域是什么?
作用域是在运行时代码中的某些特定部分中变量,函数和对象的可访问性。换句话说,作用域决定了代码区块中变量和其他资源的可见性。
function outFun2() {
var inVariable = "内层变量2";
}
outFun2();//要先执行这个函数,否则根本不知道里面是啥
console.log(inVariable); // Uncaught ReferenceError: inVariable is not defined
操作数组的方式有哪些?
for、forEach、concat、filter、slice、push等
0.1 + 0.2 等于 0.3吗?为什么?如何解决?
。。。
keep-alive是什么?有哪几个生命周期阶段?
keep-alive是 Vue 提供的一个内置组件,用来对组件进行缓存
当引入keep-alive的时候,页面第一次进入,钩子的触发顺序created-> mounted-> activated,退出时触发deactivated。当再次进入(前进或者后退)时,只触发activated
判断一个变量是否是数组,有哪些办法?
- isArray
- 对象原型
- instanceof
- Object.prototype.toString.call()
判断一个变量是否是对象,有哪些办法?
- typeof
- instanceof
- constructor
- Object.prototype.toString.call()
(附加) 讲解下Object.prototype.toString.call()
Object.prototype.toString.call()方法可以精准判断变量类型,它返回[object constructorName]的字符串格式,这里的constructorName就是call参数的函数名
对象/数组常用方法有哪些?
toSting、pop、join、slice、shift、push等
创建一个空数组/空对象有哪些方式?
空数组
var arr = [ ] ;
var arr = new Array( );
空对象
var obj = {};
var obj=new Object()
哪些遍历方式会改变原数组?
forEach、map
Set和Map各是什么?
Set
set类似于数组,但是成员的值都是唯一的,没有重复的值。可以用于数组去重。
Map
JavaScript对象object本质上是键值对的集合,Hash结构。
如何改变一个函数a的上下文?
- 将函数挂载在对象上
- call
- apply
- bind
Call和replay有什么区别?
共同
call和apply都是用来修改函数中this的指向问题;
不同
传参方式不同。call方法可以传给该函数的参数分别作为自己的多个参数,而apply方法必须将传给该函数的参数合并成一个数组作为自己的一个参数。
Evenbus是什么东西?
全局事件总线
父子组件生命周期执行顺序是怎么样的?
父beforeCreate -> 父created -> 父beforeMount -> 子beforeCreate -> 子created -> 子beforeMount -> 子mounted -> 父mounted
mixins有几个生命周期阶段?
弹性布局,一行两列,一列固定宽,如何实现?
mixin的beforeCreate > 父beforeCreate > mixin的created > 父created > mixin的beforeMount > 父beforeMount > 子beforeCreate > 子created > 子beforeMount > 子mounted > mixin的mounted >父mounted
Flex:1 包含哪三种属性
flex-grow、flex-shrink 、 flex-basis
同源策略和跨域
同源
同源策略会阻止一个域的javascrip脚本和另一个域的内容进行交互,是用于隔离潜在恶意文件的关键安全机制;
跨域
当一个请求url的协议、域名、端口三者之间任意一个与当前页面url不同即为跨域
rem和em区别
- rem是相对于根元素进行计算,而em是相对于 当前元素或父元素的字体大小。
- rem不仅可以设置字体的大小,还支持元素宽、高等属性。
- em是相对于当前元素或父元素进行换算,层级越深,换算越复杂。而rem是相对于根元素计算,避免层级关系。
http和https区别
http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议 http和https使用的是完全不同的连接方式用的端口也不一样