1、vue路由传参方式
答案:
通过路由属性中的name来确定匹配的路由,通过params来传递参数,获取参数:this.$route.params.id;
第二种:使用path来匹配路由,然后通过query来传递参数,这种情况下 query传递的参数会显示在url后
面?id=?,获取参数:this.$route.query.id。
2、登录页面怎么做的,思路是什么?
1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码
2、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token
3、前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面
4、前端每次跳转路由,就判断 localStroage 中有无 token ,没有就跳转到登录页面,有则跳转到对应路由页面
5、每次调后端接口,都要在请求头中加token
6、后端判断请求头中有无token,有token,就拿到token并验证token,验证成功就返回数据,验证失败(例如:token过期)就返回401,请求头中没有token也返回401
7、如果前端拿到状态码为401,就清除token信息并跳转到登录页面
3、登录鉴权如何做的
routes[]里用 mate.auth来标识是否需要鉴权。router.beforeEach做个全局路由守卫,根据是否需要鉴权
以及是否已经登录来进行不同操作。
4、第一次进入页面如何使一个组件快一个组件慢
答案:
1、关闭打包时生成的map文件
2、vue-router路由懒加载
5、如何处理快速点击事件的问题的处理
答案:1.方法一:用定时器定时,没跑完定时器,点击按钮无效
var isClick = true;
$("button").on("click",function(){
if(isClick) {
isClick = false;
//事件
console.log('我被点击了');
//定时器
setTimeout(function() {
isClick = true;
}, 1000);//一秒内不能重复点击
}else{
console.log('请勿过快点击');
}
});
2.方法二:用两次时间差决定点击是否有效:
var lastClick;
lockClick(){
var nowClick = new Date();
if (lastClick === undefined) {
lastClick = nowClick;
return true;
} else {
if (Math.round((nowClick.getTime() - lastClick.getTime())) > 500) {
lastClick = nowClick;
return true;
}
else {
lastClick = nowClick;
return false
}
}
}
this.on('click',()=>{
if (this.lockClick()) {
//你的函数代码
}
})
5、深拷贝的几种方式 浅拷贝的几种方式
答案:
assign()(只进行一层拷贝)、JSON 简单粗暴 弊端 转换时间、递归;浅拷贝:for循环
6、事件循环,宏任务和微任务
执行一个宏任务(执行栈中没有就从事件队列中获取)
执行过程中如果遇到微任务,就将它添加到微任务的任务队列中
宏任务里的同步代码执行完毕后,立即执行当前微任务队列中的所有微任务(依次执行)
当前宏任务执行完毕,开始检查渲染,然后GUI线程接管渲染
渲染完毕后,JS线程继续接管,开始下一个宏任务(从事件队列中获取)
原文链接:https://blog.csdn.net/m0_62181310/article/details/126924489
7、es中解决异步的几种的几种方式
async、await、promise
8、说一下promise?
Promise 是异步编程的一种解决方案,其实是一个构造函数,自己身上有all、reject、resolve这几个方法,原型上有then、catch等方法。
Promise对象有以下两个特点。
(1)对象的状态不受外界影响。Promise对象代表一个异步操作,有三种状态:pending(进行中)、fulfilled(已成功)和rejected(已失败)。
(2)一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从pending变为fulfilled和从pending变为rejected。
9、插槽的类别
默认插槽、具名插槽、作用域插槽
1、默认插槽:
父组件中:
<Category>
<div>html结构1</div>
</Category>
子组件中:
<template>
<div>
<!-- 定义插槽 -->
<slot>插槽默认内容...</slot>
</div>
</template>
2、具名插槽:
父组件中:
<Category>
<template slot="center">
<div>html结构1</div>
</template>
<template v-slot:footer>
<div>html结构2</div>
</template>
</Category>
子组件中:
<template>
<div>
<!-- 定义插槽 -->
<slot name="center">插槽默认内容...</slot>
<slot name="footer">插槽默认内容...</slot>
</div>
</template>
3、作用域插槽:
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category
组件中,但使用数据所遍历出来的结构由App组件决定)
具体编码:
父组件中:
<Category>
<template scope="scopeData">
<!-- 生成的是ul列表 -->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
<Category>
<template slot-scope="scopeData">
<!-- 生成的是h4标题 -->
<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
</template>
</Category>
子组件中:
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
//数据在子组件自身
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽']
}
},
}
</script>
原文链接:https://blog.csdn.net/m0_53022813/article/details/124441064
10、set和map的区别
Set输出的是value;Map输出的是key:value
11、git中遇到修改冲突怎么办
将有冲突的文件复制一份,然后回退一下代码,重新pull拉一下最新代码,然后对比一下你最新代码和你复制下来的代码,将你新写的代码拷贝回去之后再重新提交。
11、混入mixins的使用场景
提取公用的数据或者通用的方法,并且这些数据或者方法,不需要组件间进行维护,就可以使用mixins。(类似于js中封装的一些公用的方法)
12、nexttick的使用场景
答案:
在下次 DOM 更新循环结束之后执行延迟回调。在修改数据之后立即使用这个方法,获取更新后的 DOM。
简单来说,Vue 在修改数据后,视图不会立刻更新,而是等同一事件循环中的所有数据变化完成之后,再统一进行视图更新。
13、解决跨域的几种方式
1、Jsonp
2、跨域资源共享(CORS)
3、nginx代理跨域
4、nodejs中间件代理跨域
14、字符串转数字的几种方法
答案:
parseInt、parseFloat
15、computer和watch的区别
1、区别
Computed:
1.computed: 是计算属性,依赖其它属性值;
2.computed 的值有缓存,只有它依赖的属性值发生改变,下一次获取 computed 的值时才会从
新计算computed 的值;
3.不支持异步,当 Computed 中有异步操作时,无法监听数据的变化
5.如果 computed 属性的属性值是函数,那么默认使用 get 方法,函数的返回值就是属性的属性
值;在 computed 中,属性有一个 get 方法和一个 set 方法,当数据发生变化时,会调用 set 方法。
6.computed中的函数直接调用,不用()。
7.computed中的函数必须用return返回。
8.computed中不能对data中的属性进行赋值操作,如果对data中的属性进行赋值,data中的属性发
生变化,从而触发computed中的函数,就会形成死循环。
Watch:
1.watch:更多的是「观察」的作用,用于监听data中的数据变化,只在被监听的属性值发生变化
时执行;
2.watch不支持缓存,当一个属性发生变化时,它就会触发相应的操作;
3.watch支持异步监听
4.watch监听的函数接收两个参数,第一个参数是最新的值,第二个是变化之前的值
5.watch监听数据必须是 data 中声明的或者父组件传递过来的 props 中的数据,当发生变化时,
会触发其他操作
6.watch函数有两个的参数:
immediate:组件加载立即触发回调函数
deep:深度监听,发现数据内部的变化,在复杂数据类型中使用,例如数组中的对象发
生变化。
2、使用场景
computed: 一个数据收多个数据的影响
watch: 一个数据影响多个数据
原文链接:https://blog.csdn.net/qq_51066068/article/details/125703458
16、echarts中用了哪些图表
折现图、柱状图、瀑布图、雷达图、饼状图、地图等
17、简述一下项目中做了哪些模块,每个模块做什么用的?
18、最新的项目,有什么业务,列表太长怎么优化,点赞视频点赞多次怎么处理?
答案:列表太长可以通过虚拟列表来展示
19、监听对象的一个属性变化怎么解决?
答案:
直接监听对象属性
text: function (newV, oldV) {
console.log(newV, oldV)
if (newV == 1) {
this.name = "监听到了哦"
}
},
深度监听:
obj: {
//监听方法
handler(newV, oldV) {
console.log(newV, oldV)
},
deep: true, // 深度监听
immediate: true, //立即监听
}
20、router和route区别?
答案:
1、this.$router //获取路由路径
$router对象是全局路由的实例,是router构造方法的实例。
路由实例方法:
1、push
字符串this.$router.push(‘home’)
对象this.$router.push({path:‘home’})
命名的路由this.$router.push({name:‘user’,params:{userId:123}})
带查询参数,变成 /register?plan=123this.$router.push({path:‘register’,query:{plan:‘123’}})
push方法其实和是等同的。
注意:push方法的跳转会向 history 栈添加一个新的记录,当我们点击浏览器的返回按钮时可以
看到之前的页面。
2、go
页面路由跳转
前进或者后退this.$router.go(-1) // 后退
3、replace
push方法会向 history 栈添加一个新的记录,而replace方法是替换当前的页面,
不会向 history 栈添加一个新的记录
4.一般使用replace来做404页面
this.$router.replace(’/’)
配置路由时path有时候会加 ‘/’ 有时候不加,以’/'开头的会被当作根路径,就不会一直嵌套之前的路径。
2、this.$route //跳转路由参数
$route对象表示当前的路由信息,包含了当前 URL 解析得到的信息。包含当前的路径,参数,query对象等。
$route.path 字符串,对应当前路由的路径,总是解析为绝对路径,如"/foo/bar"。
$route.params 一个 key/value 对象,包含了动态片段和全匹配片段, 如果没有路由参数,就是一个空对象。
route . query一个key/value 对象 , 表示URL 查询参数 。 例如,对于路径 / foo ? user = 1 , 则 有 route.query
一个 key/value 对象,表示 URL 查询参数。 例如,对于路径 /foo?user=1,则有route.query一个key/value对
象,表示URL查询参数。例如,对于路径/foo?user=1,则有route.query.user == 1, 如果没有查询参数,则
是个空对象。
$route.hash 当前路由的hash值 (不带#) ,如果没有 hash 值,则为空字符串。锚点*
$route.fullPath 完成解析后的 URL,包含查询参数和hash的完整路径。
$route.matched 数组,包含当前匹配的路径中所包含的所有片段所对应的配置参数对象。
$route.name 当前路径名字
$route.meta 路由元信息
导航钩子的参数:
router.beforeEach((to,from, next)=>{//to 和from都是 路由信息对象,后面使用路由的钩子函数就容易理解了})
原文链接:https://blog.csdn.net/admin_djp/article/details/112200606
20、vue怎么返回上一页?
答案:
this.$router.go(-1);
21、push和replace的区别?
答案:
1.this.$router.push()
描述:跳转到不同的url,但这个方法会向history栈添加一个记录,点击后退会返回到上一个页面。
2.this.$router.replace()
描述:同样是跳转到指定的url,但是这个方法不会向history里面添加新的记录, 点击返回,会跳转到上上一个页面。上一个记录是不存在的。
22、树形结构 组织化,菜单,子菜单类型结构?数组去重,根据对象里面的一个属性去重,对象里面的id去重
答案:
1、ES6的set数据结构去除数组对象中的重复对象
let arr = [
{ name: '张三', age: 18 },
{ name: '张三', age: 18 },
{ name: '李四', age: 20 }
]
let noRepeat = [...new Set(arr.map(item=> JSON.stringify(item)))];
let newArr = noRepeat.map(item=> JSON.parse(item))
console.log(newArr)
2、reduce去除数组对象中的某个重复属性的对象
const arr = [
{ id:1, name:'张三' },
{ id:1, name:'李四' },
{ id:2, name:'张三' },
]
// 第一步,这里定义按照过滤的对象的属性名称
const name= 'name'
// 第二步, 数组属性对象 去重
const newArr = arr.reduce((all,next)=>all.some((item)=>item[name]==next[name])?all:[...all,next],[]);
console.log(newArr)
23、vue防抖是怎么做的?
答案:
防抖函数的作用就是控制函数在一定时间内的执行次数。防抖意味着 N 秒内函数只会被执行一次(最后一次),如果 N 秒内再次被触发,则重新计算延迟时间。
节流函数的作用是规定一个单位时间,在这个单位时间内最多只能触发一次函数执行,如果这个单位时间内多次触发函数,只能有一次生效。
1、在公共方法中(如 public.js 中),加入函数防抖和节流方法
2、在需要使用的组件引用
3、在 methods 中使用
24、浏览器渲染vue的过程?
答案:
Vue 推荐在绝大多数情况下使用 template 来创建你的 HTML。但是模板毕竟是模板,不是真实的dom节点。从模板到真实dom节点还需要经过一些步骤。
1、把模板编译为render函数
2、实例进行挂载, 根据根节点render函数的调用,递归的生成虚拟dom
3、对比虚拟dom,渲染到真实dom
4、组件内部data发生变化,组件和 子组件引用data作为props重新调用render函数,生成虚拟dom, 返回到步骤3
26、页面数据缓存是怎么做的,三者有什么区别?
答案:
localstorage、sessionstorage、cookie
1、存储大小不同
localStorage:具有更大的存储空间,通常是5M或者更多;
cookie:大小不能超过4K;
2、数据有效期不同
localStorage:永久有效,即使窗口被关闭也有效。除非手动清除。
sessionStorage:在当前会话有效,关闭浏览器或者手动清除后无效。属于临时性存储。
cookie:可以设置过期时间,过期间前都是有效的,即使关闭了浏览器。
3、作用域不同
sessionStorage:不在不同的浏览器窗口中共享,即使是同一个页面。
localStorage 和 cookie :在所有同源窗口都是共享的。
4、 localStorage 支持事件通知机制,可以将数据更新的通知发送给监听者
5、 cookie 数据始终在同源的 http 请求中携带(即使不需要),即 cookie 在浏览器和服务器间来回传递。而 sessionStorage 与 localStorage 均属于本地存储
原文链接:https://blog.csdn.net/qq_38290251/article/details/125622421
25、前端和后端联调是怎么联调的?
答案:
一、联调前:保证前后端各自没有问题。
后端用postman测试一下。
前端连接的jsonserver,保证数据格式和后端返回的数据格式一致。
二、前后端的计算机连在同一个局域网
可以在cmd 里,用命令 ping 对方的ip地址,来测试是否在同一个局域网里。
三、把config/index.js中的反向代理改一下
target改成后端的ip地址(如:10.35.162.1)和端口号(如:3000)
四、发送请求,获取数据。
27、 版本仓库用流水线还是单体的?
答案:
26、如何手动部署git?
答案:
git init
-- 将当前目录交给【本地】git管理(当前目录会出.git文件夹【隐藏的文件夹】)相当于初始化
git remote add origin 【远程仓库地址】
-- 将远程仓库和本地仓库进行关联(通讯)
git status
-- 查看本地仓库的状态(修改、新增、删除)
git add .
-- git默认不会把修改过的东西存在本地仓库(存储在本地仓库的临时仓库中)
-- .全部添加
git commit -m '提交的描述'
-- 将改变的文件提交到本地仓库(真正改变仓库的文件)
git push
-- 将本地仓库的内容提交到远程【在线码云】仓库
--u 保存此次提交的所有信息(每次提交其实都需要输入用户名和密码,记住密码)
--master 主分支(很多分支,一定有一个主分支)
git push -u origin master
【更新本地仓库】
git pull -- 拉取远程仓库的数据
【分支命令】
git branch --查看本地分支
git branch -a --查看本地和远程分支
git checkout 分支名
git checkout -b 【分支名】 -- 基于当前分支创建并切换到新分支(本地分支)
git checkout -b 【分支名】 origin/远程分支名 (创建并切换到新分支 基于远程分支创建本地分支,这样子有关联 )
git branch -D 【分支名】 --删除分支(但是必须先离开此分支)
git checkout -b dev origin/dev
git master 千万别动 设置成保护模式
创建分支 dev 在其他分支上修改 设置为默认分支
0
下载项目 修改完 上传 流程
git clone IP地址
git clone -b 分支名 IP地址
git add . 提交
git status
git commit -m '注释'
git pull 代码比较
git push
27、闭包的定义?优缺点?使用场景?
定义:一个函数可以访问其他函数内部变量的函数叫做闭包函数。
优点
(1)闭包可以避免全局变量污染。
(2)闭包可以延长变量的生命周期。
(3)闭包中的变量不会被垃圾回收或者机制回收。
缺点
(1)由于变量长期都贮存在内存中,导致内存消耗大。因此不能滥用闭包,否则会造成网页的性能问题。
(2)在低版本IE浏览器中可能导致内存泄露。解决方法是在退出函数之前,将不使用的局部变量全部删除。
原文链接:https://blog.csdn.net/Hanah_pln/article/details/127687704
使用场景:
1.setTimeout
原生的setTimeout传递的第一个函数不能带参数,通过闭包可以实现传参效果。
2.回调函数
3.函数防抖
4.封装私有变量
28、从地址栏输入url到页面展示经历那些过程?
答案:
二、域名解析(DNS)
三、TCP 三次握手
四、发送 HTTP 请求
五、服务器处理请求并返回 HTTP 报文
六、浏览器解析渲染页面
七、断开连接
30、 http有哪些请求方法,get,post区别,具体传参是怎么传参?
答案:
1、url可见性:
get,参数url可见
post,url参数不可见
2、数据传输上:
get,通过拼接url进行传递参数;
post,通过body主体传输参数
3、缓存性:
get请求是可以缓存的
post请求不可以缓存
4、后退页面的反应
get请求页面后退时,不产生影响
post请求页面后退时,会重新提交请求
5、传输数据的大小
get一般传输数据大小不超过2k-4k(根据浏览器不同,限制不一样,但相差不大)
post请求传输数据的大小根据php.ini 配置文件设定,也可以无限大。
6、安全性
这个也是最不好分析的,原则上post肯定要比get安全,毕竟传输参数时url不可见,但也挡不住部分人闲的
没事在那抓包玩。安全性个人觉得是没多大区别的,防君子不防小人就是这个道理。对传递的参数进行加密,
其实都一样
29、什么是同源,有什么方法可以解决跨域?
答案:
如果两个页面(接口)的协议、域名、端口号都相同,我们认为他们具有相同的源
1、Jsonp
2、跨域资源共享(CORS)
3、nginx代理跨域
4、nodejs中间件代理跨域
30、Scss的功能用过那些?
1、变量
Scss使用 $ 符号来标识变量,我们可以把反复使用的css属性值定义成变量,之后直接使用该变量就行了
2、嵌套规则
大多数情况下,使用简单的嵌套规则都没有问题,但是有些场景不行。比如想要在嵌套的选择器里面使用一个类似 :hover 的伪类。为了解决这种以及其他情况,sass提供了一个特殊结构 &。
$myColor: red;
p {
color: $myColor;
&:hover{
background-color: blue;
}
3、嵌套属性
很多 CSS 属性都有同样的前缀,例如:font-family, font-size 和 font-weight , text-align, text-transform 和 text-overflow。在 Sass 中,可以使用嵌套属性来编写它们。
嵌套属性的规则是这样的:把属性名从中划线-的地方断开,在根属性后边添加一个冒号:,紧跟一个{ }块,把子属性部分写在这个{ }块中:
p{
font: {
family: "微软雅黑";
size: 20px;
weight: bold;
style: italic;
}
}
(2)嵌套属性
很多 CSS 属性都有同样的前缀,例如:font-family, font-size 和 font-weight , text-align, text-transform 和 text-overflow。在 Sass 中,可以使用嵌套属性来编写它们。
嵌套属性的规则是这样的:把属性名从中划线-的地方断开,在根属性后边添加一个冒号:,紧跟一个{ }块,把子属性部分写在这个{ }块中:
p{
font: {
family: "微软雅黑";
size: 20px;
weight: bold;
style: italic;
}
}
4、@import
Sass提供了一个@import规则,在生成scss文件时就把相关文件导入进来;而scss中@import引用的CSS要等页面加载完后最后加载。
5、6、@mixin 与 @include
我们可以定义@mixin混合器实现大段样式的重用,它还支持我们动态传参;在样式表中通过@include来使用这个混合器
// 大段重复的样式用混合器
@mixin myfont($color, $fontsize) {
color: $color;
text-decoration: none;
font: {
size: $fontsize;
family: "microsoft yahei";
weight: normal;
style: noraml;
}
&:hover {
color: #f10215;
}
}
//使用
a {
@include myfont(#666, 18px);
}
31、ajax的原理,怎么用,几种状态
0 - (未初始化)还没有调用send()方法
1 - (载入)已调用send()方法,正在发送请求
2 - (载入完成)send()方法执行完成,已经接收到全部响应内容
3 - (交互)正在解析响应内容
4 - (完成)响应内容解析完成,可以在客户端调用了
32、展开讲讲继承,怎么实现继承?
答:
1.使用对象冒充
2.使用es6 class关键字实现
3.构造函数绑定
4.原型继承
34、讲讲原型链,什么是原型链,最后找到object上面
答案:
每个原型对象中都有 prototype 属性,指向一个对象,这个对象就叫做原型或者原型对象,每个对象
都有 __proto__ ,指向构造函数的原型对象,层层递进到 null 为止
33、promise有那些状态,用过那些方法?
答案:
pendind、fulfilled、rejected
then、catch
34、事件循环(Event Loop)有了解过吗?
答案:
同步和异步任务分别进入不同的执行"场所",同步的进入主线程,异步的进入Event Table并注册函数。
当指定的事情完成时,Event Table会将这个函数移入Event Queue。主线程内的任务执行完毕为空,
会去Event Queue读取对应的函数,进入主线程执行。上述过程会不断重复,也就是常说的Event Loop
(事件循环)
35、说说什么是宏任务、什么是微任务?
宏任务一般是:
包括整体代码script,setTimeout,setInterval。
微任务:Promise,process.nextTick
案例:
setTimeout(function() {
console.log('setTimeout');
})
new Promise(function(resolve){
console.log('promise');
}).then(function() {
console.log('then');
})
console.log('console');
· 这段代码作为宏任务,进入主线程。
· 先遇到setTimeout,那么将其回调函数注册后分发到宏任务Event Queue。(注册过程与上同,下文不再描述)
· 接下来遇到了Promise,new Promise立即执行,then函数分发到微任务Event Queue。
· 遇到console.log(),立即执行。
· 好啦,整体代码script作为第一个宏任务执行结束,看看有哪些微任务?我们发现了then在微任务
Event Queue里面,执行。
· ok,第一轮事件循环结束了,我们开始第二轮循环,当然要从宏任务Event Queue开始。我们发现了宏任务
Event Queue中setTimeout对应的回调函数,立即执行。
· 结束。
36、vue虚拟dom?
答案:
虚拟DOM其实就是用一个原生的JS对象去描述一个DOM节点,实际上它只是对真实 DOM 的一层抽象。
最终可以通过一系列操作使这棵树映射到真实环境上。相当于在js与DOM之间做了一个缓存,利用patch
(diff算法)对比新旧虚拟DOM记录到一个对象中按
需更新, 最后创建真实的DOM
37、webpack用过吗?
38、答案:
webpack的作用就是将在node中写好的代码(后端)解析为在浏览器下(前端)可以运行的代码;
所以打包的意思就是,不用再像浏览器那样,先引入a.js再引入b.js,完事儿a.js还要暴露为全局变量。而是直接将两个js打包成为一个bundle.js,然后在网页中直接引入bundle.js就行了。
40、前端常用的几种布局方式?
答案:
1、静态布局、
2、流式布局
3、响应式布局
4、弹性布局
5、flex布局
6、自适应布局(bootstrap)
7、浮动布局
8、定位布局
41、token过期如何进行判断?
答案:
1、判断token是否过期,前端请求后,后台会返回一个状态给你。根据状态判断是否过期,刷新token
2、.是否每次请求后端都会返回新的token给你。或者后端给你定义了一个刷新token的方法,那此时你自己需要定义时间去判断token刷新
我们可以通过挂载路由守卫和响应拦截器来判断
在main.js加入如下代码/* 响应拦截器 */
axios.interceptors.response.use(function (response) {
// ①10010 token过期(30天) ②10011 token无效
if (response.data.code === 1003) {
window.sessionStorage.removeItem('token');
router.replace({
path: '/login' // 到登录页重新获取token
})
}else if (response.data.token) {
// 判断token是否存在,如果存在说明需要更新token
window.sessionStorage.setItem("token",response.data.token);
// 覆盖原来的token(默认一天刷新一次)
}
})
42、promise.all()的用法详解?
答案:
promise.all()该方法用于将多个Promise实例,包装成一个新的Promise实例。
var p = Promise.all([p1,p2,p3]);
(1)只有p1、p2、p3的状态都变成fulfilled,p的状态才会变成fulfilled,此时p1、p2、p3的返回值组成一个数组,传递给p的回调函数。
(2)只要p1、p2、p3之中有一个被rejected,p的状态就变成rejected,此时第一个被reject的实例的返回值,会传递给p的回调函数。
请看下面示例:需要注意的是,promise.all()成功时,在then(result)中result是个数组
let p1 = new Promise((resolve, reject) => {
resolve('成功了')
})
let p2 = new Promise((resolve, reject) => {
resolve('success')
})
let p3 = Promise.reject('失败')
Promise.all([p1, p2]).then((result) => {
console.log(result) //['成功了', 'success']
}).catch((error) => {
console.log(error)
})
Promise.all([p1,p3,p2]).then((result) => {
console.log(result)
}).catch((error) => {
console.log(error) // 失败了,打出 '失败'
})
43、Promise.race是赛跑的意思,也就是说Promise.race([p1, p2, p3])里面的结果哪个获取的快,就返回哪个结果,不管结果本身是成功还是失败
let p1 = Promise.reject('aaa')
let p2 = Promise.resolve('bbb')
let p3 = Promise.reject('ccc')
let p4 = Promise.resolve('ddd')
Promise.race([p2, p1, p3, p4]).then(res => {
console.log('成功', res); //返回数组
}).catch(err => {
console.log('失败', err)
})
race的使用比如可以使用在一个请求在10s内请求成功的话就走then方法,如果10s内没有请求成功的话进入reject回调执行另一个操作。
//请求某个table数据
function requestTableList(){
var p = new Promise((resolve, reject) => {
//去后台请求数据,这里可以是ajax,可以是axios,可以是fetch
resolve(res);
});
return p;
}
//延时函数,用于给请求计时 10s
function timeout(){
var p = new Promise((resolve, reject) => {
setTimeout(() => {
reject('请求超时');
}, 10000);
});
return p;
}
Promise.race([requestTableList(), timeout()]).then((data) =>{
//进行成功回调处理
console.log(data);
}).catch((err) => {
// 失败回调处理
console.log(err);
});
44、javascript中的异步实现方式有以下几种?
答案:
1、callback (回调函数)
2、发布订阅模式
3、Promise对象
4、es6的生成器函数
5、 async/await
45、es5中有哪些模块化工具?
46、锚链接如何使用?
47、vue中路由跳转的几种方式?
答案:
1、vue-router,<router-link :to="{name:'home'}">
2、this.$router.push() (函数里面调用)
3、this.$router.replace() (用法同上,push)
4、this.$router.go(n)
48、如何在不刷新页面的情况下修改url地址
答案:
当前URL地址:
http://localhost:9600/home/check/JZ999/LP888/111?id=123456
改为:
http://localhost:9600/home/check/JZ999/LP888/222?id=123456
const url = window.location;
const arr = url.pathname.split('/');
arr.pop();
arr.push('222');
const newUrl = url.origin + arr.join('/') + url.search;
history.pushState('', '', newUrl); // 不刷新页面
// url.href = newUrl; // 刷新页面
1、window.location 只读属性,返回一个 Location 对象,其中包含有关文档当前位置的信息。
2、Location.pathname 包含URL中路径部分的一个DOMString,开头有一个“/"。
在上例中,是 /home/check/JZ999/LP888/111
3、split() / pop() / push() / join() 方法都很简单,自行百度
4、Location.origin (en-US) 只读属性,包含页面来源的域名的标准形式DOMString。
在上例中,是 http://localhost:9600
5、Location.search 包含URL参数的一个DOMString,开头有一个“?”。
在上例中,是 ?id=123456
所以,最后的newUrl就是修改后的地址
不刷新页面: history.pushState():
在 HTML 文档中,history.pushState() 方法向当前浏览器会话的历史堆栈中添加一个状态(state)。
查看history.pushState()
在这个例子中,前两个参数我传了空值,history.pushState(‘’,‘’, newUrl);
刷新页面: 直接写 url.href = newUrl; 不加 history.pushState() 这一句
pushState是向当前历史栈的栈顶增加数据,而replaceState则是替换当前栈顶的数据。
这两种方式都可以将url替换并且不刷新页面。
49、闭包函数内存回收的方法?
答:
调用完闭包函数之后给它赋一个null
50、改变this指向的三种方法?
this的指向基本遵循一句话:谁调用这个函数,函数里的this就指向谁。
一、call()方法
call() 方法的第一个参数必须是指定的对象,然后方法的原参数,挨个放在后面。
(1)第一个参数:传入该函数this执行的对象,传入什么强制指向什么;
(2)第二个参数开始:将原函数的参数往后顺延一位
var Person = {
name:"lixue",
age:21
}
function fn(x,y){
console.log(x+","+y);
console.log(this);
console.log(this.name);
console.log(this.age);
}
fn.call(Person, "hh", 20);
二、apply() 方法
apply() 方法的第一个参数是指定的对象,方法的原参数,统一放在第二个数组参数中。
(1)第一个参数:传入该函数this执行的对象,传入什么强制指向什么;
(2)第二个参数开始:将原函数的参数放在一个数组中
var Person = {
name:"lixue",
age:21
}
function fn(x,y){
console.log(x+","+y);
console.log(this);
console.log(this.name);
console.log(this.age);
}
fn.apply(Person, ["hh", 20]);
三、bind() 方法
bind() 方法的用法和call()一样,直接运行方法,需要注意的是:bind返回新的方法,需要重新
调用:是需要自己手动调用的
var Person = {
name:"lixue",
age:21
}
function fn(x,y){
console.log(x+","+y);
console.log(this);
console.log(this.name);
console.log(this.age);
}
// 方式一
fn.bind(Person, 'hh', 20)()
// 方式二
fn.bind(Person)('hh', 20)
原文链接:https://blog.csdn.net/qq_52421092/article/details/130417743
51、如何在es5中定义一个类?
52、js用new的时候进行了哪些操作?
53、文字垂直居中的几种方法?
1、line-height=height
2、flex布局
3、定位
54、css中如何使用伪类在span的下面画上一条线?
答案:
div {
position: relative;
}
div::after {
content: ''; //必须写
position: absolute;
left: 0;
bottom: 0;
width: 200px;
height: 1px;
background-color: #dcdcdc;
}
55、如何使用css画一个三角形?
.triangle{
width: 0px; /*设置宽高为0,所以div的内容为空,从才能形成三角形尖角*/
height: 0px;
border-bottom: 200px solid #00a3af;
border-left: 200px solid transparent; /*transparent 表示透明*/
border-right: 200px solid transparent;
}
56、css中position五种属性?分别说说他们
static:正常定位
relative:相对定位
fixed:固定定位
absolute:绝对定位
sticky:粘性定位
57、v-if和v-show的区别、应用场景?
1.原理
v-show指令:元素始终被渲染到HTML,它只是简单的伪元素设置css的style属性,当不满足条件的
元素被设置style=“display:none”的样,是通过修改元素的的CSS属性(display)来决定实现显示还是隐藏
v-if指令:满足条件是会渲染到html中,不满足条件时是不会渲染到html中的,是通过操纵dom元素来
进行切换显示
2.应用场景
v-if需要操作dom元素,有更高的切换消耗,v-show只是修改元素的的CSS属性有更高的初始渲染消耗,
如果需要非常频繁的切换,建议使用v-show较好,如果在运行时条件很少改变,则使用v-if较好
原文链接:https://blog.csdn.net/zjpjay/article/details/109816049
58、Vue中data为什么是一个函数?
因为组件是可以复用的,如果每个组件都使用同一个data对象,那么当一个组件改变了data的值,
其他组件的data值都会被改变。
59、mutations和actions的区别?
一: Mutations
mutations是用于修改Vuex状态的唯一方法。它们是同步操作,意味着它们必须是纯函数,以确保状态的可预测性。这意味着mutations应该只用于同步操作,例如在响应用户事件时更新状态。它们不应该包含任何异步代码,如API调用。
举个例子,下面的代码演示了如何定义一个名为increment的mutation,用于将state中的count属性增加
const store = new Vuex.Store({
state: {
count: 0
},
mutations: {
increment(state) {
state.count++
}
}
})
store.commit('increment') // 调用mutation
二:Actions
actions用于执行异步操作或包含异步操作的操作序列。它们可以包含任何异步代码,例如API调用或其他异步操作,但不能直接修改状态。相反,它们通过commit触发mutations来间接修改状态。
举个例子,下面的代码演示了如何定义一个名为fetchData的action,它会异步获取数据并提交mutation来更新状态:
const store = new Vuex.Store({
state: {
data: null
},
mutations: {
setData(state, data) {
state.data = data
}
},
actions: {
async fetchData({ commit }) {
const response = await fetch('https://api.example.com/data')
const data = await response.json()
commit('setData', data)
}
}
})
store.dispatch('fetchData') // 调用action
总之,mutations和actions有不同的角色和职责。mutations用于同步状态的修改,actions用于执行异步操作并间接修改状态。
原文链接:https://blog.csdn.net/weixin_56960330/article/details/129420007
60、父子组件之间通信的几种方式?
1.Props+$emit()
3.$parent+$children
6.ref 属性
61、vue数据挂载发生在哪个阶段?
mounted
62、简述一下v-model的原理?在js中如何实现数据的双向绑定?
使用原生js实现数据的双向绑定。
关于vue的双向数据绑定,其核心是 Object.defineProperty()方法
Object.defineProperty()的作用就是直接在一个对象上定义一个新属性,或者修改一个已经存在的属性
Object.defineProperty(obj, prop, desc)
obj:需要定义属性的当前对象。
prop:当前需要定义的属性名。
desc:具体的改变方法。
实现模块化普遍采用的是命名空间的方式
64、vue-loader是什么?使用的用途有哪些?
简单的说,他就是基于webpack的一个的loader,解析和转换 .vue 文件,提取出其中的逻辑代码 script、样式代码 style、以及 HTML 模版 template,再分别把它们交给对应的 Loader 去处理,核心的作用,就是提取,划重点。
65、v-for为什么使用key?
vue中列表循环需加:key=“唯一标识” 唯一标识可以是item里面id 等,因为vue组件高度复用增加Key可以标识组件的唯一性,为了更好地区别各个组件 key的作用主要是为了高效的更新虚拟DOM。但是我们不推荐使用index作为key!
总结
总结:key的作用主要就是为了高效的更新虚拟DOM,使用key值,它会基于key的变化重新排列元素顺序,并且会移除key不存在的元素。它也可以用于强制替换元素/组件而不是重复的使用它。
为何不推荐index作为key值?
当以数组为下标的index作为key值时,其中一个元素(例如增删改查)发生了变化就有可能导致所有的元素的key值发生改变。
diff算法时比较同级之间的不同,以key来进行关联,当对数组进行下标的变换时,比如删除第一条数据,那么以后所有的index都会发生改变,那么key自然也跟着全部发生改变,所以index作为key值是不稳定的,而这种不稳定性有可能导致性能的浪费,导致diff无法关联起上一次一样的数据。因此,能不使用index作为key就不使用index。
66、渐进式框架的理解?
主张最少;可以根据不同的需求选择不同的层级
67、vue和jquery的区别?
jQuery是使用选择器($)选取DOM对象,对其进行赋值、取值、事件绑定等操作,其实和原生的HTML的区别只在于可以更方便的选取和操作DOM对象,而数据和界面是在一起的。比如需要获取label标签的内容:$("lable").val();,它还是依赖DOM元素的值。
Vue则是通过Vue对象将数据和View完全分离开来了。对数据进行操作不再需要引用相应的DOM对象,可以说数据和View是分离的,他们通过Vue对象这个vm实现相互的绑定。这就是传说中的MVVM。
68、delete和vue.delete删除数组的区别?
delete只是被删除的元素变成了 empty/undefined 其他的元素的键值还是不变。Vue.delete 直接删除了数组 改变了数组的键值。
69、vue从初始化页面闪动问题?
在根元素上加:这里默认vue实例绑定到类名为app的div上。
<div class="app" style="display: none;" :style="{display: 'block'}">
{{message}}
</div>
这样应该就可以了。
原理:
vue在渲染之前,style="display: none;"让页面不显示
vue渲染完成了,:style="display: block;"让页面显示
70、vue更新数组时触发视图更新的方法?
push();pop();shift();unshift();splice(); sort();reverse()
71、vue中常用的组件库?
答案:
1.vant
2.Ant Design Vue
3.Element UI
72、vue中如何修改打包后静态资源路径?
找到文件路径Config里面的index.js
修改路径:assetsPublicPath: ‘/aa/’,修改成自己文件访问的路径即可
73、正则表达式里面()、[]、{}的理解?
正则表达式()、[]、{}各有着不同的意思;
()是为了提取匹配字符串的,表达式中有几个()就有几个相应的字符串,如(\s*)表示连续空格的字符串;。
[] 是定义匹配的字符范围。比如[a-zA-Z0-9]表示相应位置的字符要匹配英文字符和数字,如[\s*表示空格或者*号];
{}一般是用来匹配的长度。比如\s{3}表示匹配三个空格,\s[1,3]表示匹配1到3个空格;
74、vue的导航守卫有哪些?
Vue 路由导航守卫分为全局守卫、路由独享守卫、组件内置守卫
1、全局守卫
① beforeEach 全局前置导航钩子,路由进入之前触发,用来身份验证、路由拦截等操作。
② beforeResolve 路由确认之前
③ afterEach 全局后置导航钩子
2、路由独享守卫
beforeEnter 路由进入之前。对某个特定路由进行独立的前置验证或权限控制。
3、组件内置守卫
beforeRouteEnter 路由进入之前,一般用来初始化数据,此时组件还没被创建出来,因此 this 是 undefined
beforeRouteUpdate 路由更新之前
beforeRouteLeave 路由离开之前, 一般用来进行页面数据的保存或弹出提示等操作。
具体分析:
一、作用
路由守卫就是路由跳转的时候会触发的钩子函数我们把他称为路由守卫。
Vue Router 提供了多种导航钩子,可以在导航过程中执行相应的操作。
作用:可以控制导航跳转,例如 beforeEach,afterEach 等;一般用于页面 title 的修改。还有一些需要登录才能调整页面的重定向功能。
二、常用的导航钩子
Vue 路由导航守卫分为全局守卫、路由独享守卫、组件内置守卫
1、全局守卫
beforeEach 路由进入之前
beforeResolve 路由确认之前
afterEach 路由进入之后
① beforeEach 全局前置导航钩子
在每个路由跳转之前执行,可以用来进行用户身份验证、路由拦截等操作。
beforeEach 主要有3个参数 to,from,next。
to:即将进入的目标路由对象;
from:当前导航正要离开的路由。
next:一定要调用该方法,resolve这个钩子。可以控制网页的跳转。
next() // 直接进to所指的路由
next(false) // 中断当前路由
next('route') // 跳转指定的路由名称
next('error') // 跳转错误的路由名称
next({ path: 'xxxx' }) // 跳转到xxx的路由路径上
② beforeResolve 全局解析守卫
在每个路由跳转被确认之前调用,可以用于处理异步路由组件。
参数都是 to from next,这个在开发中几乎不用。
③ afterEach 全局后置导航钩子
在每次路由跳转之后执行,可以用来进行路由跳转后的操作,比如页面滚动、统计PV等操作
afterEach 不接收第三个参数 next 函数,也不会改变导航本身,开发中用得较少。
// 前置守卫
async function handleBeforeEach(to, from, next) {
const page = to.path
const isWhiteList = ['/xxx'].includes(page)
// 在白名单内,直接放行
if (isWhiteList) {
next()
return
}
// 不在白名单内,判断是否有token
const token = getToken()
if (!token) {
// 无token,跳转到登录页
next({ path: '/login', replace: true })
return
}
next()
}
// 后置守卫
function handleAfterEach(to, from) {
console.log(to, from)
}
// 绑定路由权限
export default function permission(router) {
router.beforeEach(handleBeforeEach)
router.afterEach(handleAfterEach)
return router
}
2、路由独享守卫
① beforeEnter 路由进入之前
在进入某个特定路由前调用,与全局 beforeEach 的区别是它可以针对某个具体路由进行设置。
也就是可以用于对该路由进行独立的前置验证或权限控制。
const router = new VueRouter({
routes: [
{
path: '/home',
component: Home,
beforeEnter: (to, from, next) => {
// 在进入 /home 路由前执行的逻辑
// 可以进行验证或权限控制
next();
}
},
// ...
]
});
3、组件内置守卫
beforeRouteEnter 路由进入之前
beforeRouteUpdate 路由更新之前
beforeRouteLeave 路由离开之前
① beforeRouteEnter 路由进入之前
组件还没被创建出来,因为函数内部 this 是undefined
先执行 beforeRouteEnter ,再执行组件内部钩子函数 beforeCreate
data() {
return {
}
},
beforeRouteEnter (to, from, next) {
if (to.meta.needLogin) {
next(vm => {
vm.needLogin = true
})
} else {
next()
}
}
② beforeRouteUpdate 路由更新之前
在路由更新时执行,比如路由参数发生变化时。
开发中比较少用
③ beforeRouteLeave 路由离开之前
在离开当前路由时执行,可以用来进行页面数据的保存或弹出提示等操作。
// 路由跳转之前保存当前滚动条的位置。
beforeRouteLeave(to, from, next) {
this.scroll = document.getElementsByClassName(
"el-table__body-wrapper"
)[0].scrollTop;
next();
},
4、总结
这些导航钩子提供了灵活的路由跳转控制机制,可以方便地实现各种复杂的路由跳转需求。
同时,VueRouter 还提供了一些其他的导航钩子和高级特性,比如路由元信息、动态路由、
命名路由等,可以进一步提高开发效率和应用的可维护性。
三、全局守卫、路由独享守卫、组件内置守卫的区别
1、作用范围不同
全局守卫:作用于所有页面;
路由独享守卫:守卫单个路由;
组件内置守卫:作用于单个组件;
2、代码写的位置不一样
全局守卫:写在 router/index.js 中;
路由独享守卫:写在路由规则里;
组件内置守卫:写在组件里 跟 data 同级;
3、执行顺序
beforeEach 【全局 - 进入之前】
beforeEnter【路由独享 - 进入之前】
beforeRouteEnter 【组件内置守卫 - 进入之前】
beforeResolve 【全局 - 解析】
afterEach 【全局 - 进入之后】
75、说说你发布订阅者模式的理解?
答案:
76、Vue自定义的组件上@click点击事件[失效]问题?为什么会这样?
1、@click.native=””
2、可以用:将事件传递至组件内,也符合组件间的单向数据流
3、使用$emit来实现事件传递
click事件作用于组件内部
77、什么是原型,原型链?
原型:
①所有引用类型有一个__proto__(隐式原型)属性,属性值是一个普通的对象
②所有函数都有一个prototype(原型)属性,属性值是一个普通的对象
③所有引用类型的__proto__属性指向它构造函数的prototype
原型链:
当访问一个对象的某个属性时,会先在这个对象本身属性上查找,如果没有找到,则会去它的__proto__隐式原型上查找,即它的构造函数的prototype,如果还没有找到就会再在构造函数的prototype的__proto__中查找,这样一层一层向上查找就会形成一个链式结构,我们称为原型链。
78、三次握手和四次挥手原理?
三次握手:
TCP是主机对主机层的传输控制协议,提供可靠的连接服务,采用三次握手确认建立一个连接:
TCP/IP协议中,TCP协议提供可靠的连接服务,采用三次握手建立一个连接,如图1所示。
(1)第一次握手:建立连接时,客户端A发送SYN包(SYN=j)到服务器B,并进入SYN_SEND状态,等待服务器B确认。
(2)第二次握手:服务器B收到SYN包,必须确认客户A的SYN(ACK=j+1),同时自己也发送一个SYN包(SYN=k),即SYN+ACK包,此时服务器B进入SYN_RECV状态。
(3)第三次握手:客户端A收到服务器B的SYN+ACK包,向服务器B发送确认包ACK(ACK=k+1),此包发送完毕,客户端A和服务器B进入ESTABLISHED(established)状态,完成三次握手。
完成三次握手,客户端与服务器开始传送数据。
四次挥手:
由于TCP连接是全双工的,因此每个方向都必须单独进行关闭。这个原则是当一方完成它的数据发送任务后就能发送一个FIN来终止这个方向的连接。收到一个 FIN只意味着这一方向上没有数据流动,一个TCP连接在收到一个FIN后仍能发送数据。首先进行关闭的一方将执行主动关闭,而另一方执行被动关闭。
TCP的连接的拆除需要发送四个包,因此称为四次挥手(four-way handshake)。客户端或服务器均可主动发起挥手动作,在socket编程中,任何一方执行close()操作即可产生挥手操作。
(1)客户端A发送一个FIN,用来关闭客户A到服务器B的数据传送。
(2)服务器B收到这个FIN,它发回一个ACK,确认序号为收到的序号加1。和SYN一样,一个FIN将占用一个序号。
(3)服务器B关闭与客户端A的连接,发送一个FIN给客户端A。
(4)客户端A发回ACK报文确认,并将确认序号设置为收到序号加1。
78、 Vue中SPA的意思?
答案:
79、前端路由的核心?
改变视图的同时不会向后端发出请求
80、vue中hash和history的区别?
hash —— 即地址栏URL中的 # 符号(此 hash 不是密码学里的散列运算)。比如这个 URL:http://www.abc.com/#/hello hash 的值为 #/hello。它的特点在于:hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。
history —— 利用了 HTML5 History Interface 中新增的pushState() 和 replaceState() 方法。(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。
使用场景
一般场景下,hash和history 都可以,除非你更在意颜值,# 符号夹杂在 URL 里看起来确实有些不太美丽。
如果不想要很丑的 hash,我们可以用路由的 history 模式,这种模式充分利用 history.pushState API 来完成URL 跳转而无须重新加载页面。
调用 history.pushState() 相比于直接修改 hash,存在以下优势:
pushState() 设置的新 URL 可以是与当前 URL 同源的任意 URL;而 hash 只可修改 # 后面的部分,因此只能设置与当前 URL 同文档的 URL;
pushState() 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;而 hash 设置的新值必须与原来不一样才会触发动作将记录添加到栈中;
pushState() 通过 stateObject 参数可以添加任意类型的数据到记录中;而 hash 只可添加短字符串;
pushState() 可额外设置 title 属性供后续使用。
81、初始化页面空白的解决方法?
82、vue中$set的用法详解?
当你利用索引直接设置一个索引项时,或者修改数组长度的时候vue不能监测数组长度的变化。
操作数组:this.$set(Array,index,newValue);
操作对象:this.$set(object,key,value);
83、px、em、rem、vh区别?
px:像素、
em:相对于当前文本字体大小的尺寸;默认是1em=16px、
rem:相对根元素字体大小的尺寸
84、Vue的生命周期方法有哪些?一般在哪一步发送请求?
beforeCreate: 在实例初始化之后,数据观测(data observe)和 event/watcher 事件配置之前被调用。在当前阶段 data、methods、computed 以及 watch 上的数据和方法都不能被访问。
created :实例已经创建完成之后被调用。在这一步,实例已经完成以下的配置:数据观测(data observe ),属性和方法的运算,watch/event 事件回调。这里没有 $el,如果非要想与 DOM 进行交互,可以通过vm.$nextTick 来访问 DOM。
beforeMount: 在挂载开始之前被调用:相关的 render 函数首次被调用。
mounted :在挂载完成后发生,在当前阶段,真实的 Dom 挂载完毕,数据完成双向绑定,可以访问到 Dom节点。
beforeUpdate :数据更新时调用,发生在虚拟 DOM 重新渲染和打补丁 (patch)之前。可以在这个钩子中进一步地更改状态,这不会触发附加的重渲染过程。
updated: 发生在更新完成之后,当前阶段组件 Dom 已经完成更新。要注意的是避免在此期间更新数据,因为这个可能导致无限循环的更新,该钩子在服务器渲染期间不被调用。
beforeDestroy: 实例销毁之前调用。在这一步,实力仍然完全可用。我们可以在这时进行 善后收尾工作,比如清除定时器。
destroy Vue实例销毁后调用。调用后,Vue实例指示的东西都会解绑定,所有的事件监听器会被移除,左右的子实例也会被销毁,该钩子在服务器端渲染不被调用。
activated: keep-alive 专属,组件被激活时调用
deactivated: keep-alive 专属,组件被销毁时调用
83、异步请求在哪一步发起?
可以在钩子函数 created、beforeMount、mounted 中进行异步请求,因为在这三个钩子函数中,data已经创建,可以将服务器端返回的数据进行赋值。
如果异步请求不需要依赖 DOM 推荐加载 created 钩子函数中调用异步请求,因为在 created 钩子函数中调用异步请求有以下优点:
能更快获取到服务端数据,减少页面loading时间;
ssr 不支持 beforeMount、mounted 钩子函数,所以放在 created 中有助于一致性。
84、es6中如何定义一个类和类的使用方法?
答案:
85、js中的几种继承方式?
答案:
1.原型链继承
2、构造继承
3、实例继承
4、拷贝继承
5、组合继承
6、寄生组合继承
86、常用的伪类选择器?
答案:hover,
87、伪类和伪元素的区别?
首先,我们来区分下伪类和伪元素的概念。本质区别在于他们是否创造了新的元素。
伪类:用于向某些选择器添加特殊的效果。例如:a标签的:link,:visited,:hover,:active;以及 :first-child, :last-child。
伪元素:是html中不存在的元素,用于将特殊的效果添加到某些选择器。例如:before,:after,:first-letter,:first-line。css3新增了一个伪元素::selection(改变用户所选取部分的样式)
87、css哪些样式可以继承?哪些不可以?
可继承属性:1.字体系列属性2.文本系列属性3.元素可见性
不可继承属性:width、heigth、padding、margin、float、position
88、vue中如何引入样式文件?
1.2全局引入
引入外部文件只需在main.js文件中,其中@代表src
import '@/style/reset.css'
1.3局部引入
<style scoped>
@import '@/assets/iconfont/iconfont.css';这个分号一定要写,要不会报错
</style>
2.组件内部引入样式的污染
@import引入样式文件,就算加scoped,其它没有引入的模块还是可以访问到你的样式,如果某个组件的类名一致,则就会被污染到。
解决办法:
修改引入样式:
<style src="@/style/reset.css" scoped></style>
3.同一个组件内新写样式
要是在写新的样式,要重新写一个新的style标签
<style src="@/style/reset.css" scoped></style>
<style scoped>
//新的css样式
</style>
4.@import和import的区别
1.@import
style中的@import是styles的语法,是在css中引用css文件
2.import
script中的import是js的语法, 是在js中去引用css文件
89、页面大量的参数如何传递?
params、query、vuex
90、solt一般的使用环境有哪些?
答案:
91、子组件里面mounted和主页面mounted?
答案:
92、插槽的使用场景有哪些?
vue的slot主要分三种,默认插槽,具名插槽,作用域插槽;使用插槽是在存在父子关系的组件中使用,我们可以在子组件中决定插槽的位置,同时子组件也可以给这些插槽的默认信息,当父组件中没有需要给子组件插槽插入信息时,显示的是子组件插槽定义的默认信息
93、vue虚拟dom实现的原理?
1、在内存中生成一颗虚拟dom树
2、将内存中的虚拟dom树初始化渲染成真实dom树
3、当我们修改data里面的数据时候
4、将之前的虚拟dom树结合新的数据生成一颗新的虚拟dom树
5、将此次生成好的新的虚拟dom树与上一次虚拟dom树结构进行对比,对比差异(diff 算法)
6、将对比出来的差异部分进行重新真实dom结构的渲染
94、vue组件通讯的几种方式?
95、vue有哪些优点?
组件化开发、数据和结构分离、安装插件、虚拟dom、轻量级框架
vue两大特点:响应式编程、组件化。
vue的优势:轻量级框架、简单易学、双向数据绑定、组件化、数据和结构的分离、虚拟DOM、运行速度快。
vue是单页面应用,使页面局部刷新,不用每次跳转页面都要请求所有数据和dom,这样大大加快了访问速度和提升用户体验。而且他的第三方ui库很多节省开发时间。
96、单页面应用和多页面应用的区别?
单页面应用(spa)
概念:只有一个html页面,所有跳转方式都是通过组件切换完成的。
优点:页面之间跳转流畅、组件化开发、组件可复用、开发便捷、易维护。
缺点:首屏加载较慢,加载整个项目中使用的css、js,SEO优化不好。
多页面应用(mpa)
概念:整个项目有多个html,所有跳转方式都是页面之间相互跳转的。
优点:首屏加载较快,只加载本页所使用的的css、js,SEO优化较好。
缺点:页面跳转较慢。
97、vue首屏加载过慢如何处理?
1.Vue-router懒加载、2.使用CDN加速
98、promise和async-await的区别?
答案:
相同点:
Promise和 async-await 都是优化异步编程体验的解决方案。
不同点:
Promise 是应用层的解决方案,它有一个规范,不同的语言也可以实现,它只能异步的处理错误,在js 里它本质上是一个对象。
async-await 是语言层的解决方案,它可以说是 Promise的补充,可以让用户像编写同步代码一样编写异步代码,通过try-catch 可以同步地处理错误。
Promise 更多应用在函数封装中,async用在函数的使用中。
Promise链式调用相当于一个新的回调地狱, 也不能统一处理异常。 Promise 本身是同步函数,多个不会等待。
async-await用同步的写法使得可读性更强,同时方便 try-catch 捕获异常, async-await 有明确的前后关系,可读性好
99、var和let还有const的区别
var 函数作用域 变量提升 值可以改 可以重复声明 可以不赋值
let 块级作用域 变量不提升 值可以改 同一块级下不可以重复声明 可以不赋值
const 块级作用域 变量不提升 值不可以改 同一块级下不可以重复声明 必须赋值
99、undefined和null的区别?
null和undefined的区别
1.首先是数据类型不一样
2.null和undefined 两者相等,但是当两者做全等比较时,两者又不等。(因为它们的数据类型不一样)
3.转化成数字的值不同
4.null代表"空",代表空指针;undefined是定义了没有赋值
3、null和undefined的运用场景
undefined
1、变量被声明时,但没有赋值时,就等于undefined
2、调用函数时,应该提供的参数没有提供,该参数等于undefined
3、对象没有赋值的属性,该属性的值为undefined
4、函数没有返回值时,默认返回undefined
null
1、作为函数的参数,表示该函数的参数不是对象(不想传递参数)
2、作为对象原型链的终点
3、如果定义的变量准备在将来用于保存对象,此时可以将该变量初始化为null
100、检测数据类型的几种方法?
Typeof、instanceof、constructor、Object.prototype.toString.call()(最好)