毫无准备的腾讯一面,最近都在忙比赛去了,突然收到腾讯一面的邮件,直接没准备。。。
总结,除了Vue其他的都挺好,但是腾讯hr为啥Vue面我四个问题,不是面的后端开发吗,好难呀,都只能随便说一点。。。
预期结果肯定没了,打完比赛再来面,以下是面经。。。
文章目录
- 1、Vue中v-if 和v-show区别
- 那什么时候需要用v-if,什么时候适合用v-show呢?
- 2、computed和watch区别
- 3、Vue生命周期理解
- 4、Vue单页面(SPA)和多页面(MPA)的理解
- 什么是SPA:
- SPA的优点
- SPA的缺点
- 什么是MPA
- 对比
- 5、TCP三次握手
- 6、Java中多态的理解
- 实现多态的条件:
- 7、Java中的内存溢出和内存泄漏
- 1、内存泄漏memory leak :
- 2、内存溢出 out of memory :
- 3、二者的关系:
- 8、Linux常用命令
- 9、Redis数据结构有哪些
- 10、字符串翻转
- 方式一:栈
- 方式二:ArrayList
- 11、查找循环链表入环节点
1、Vue中v-if 和v-show区别
它们的作用都是控制元素的显示和隐藏
区别在于:v-if是创建和删除元素,而v-show只是改变元素中的display样式属性。
那什么时候需要用v-if,什么时候适合用v-show呢?
如果我们不会频繁的让元素在显示和隐藏之间切换,那我们比较适合使用v-if,这样可以提高我们的页面渲染速度,因为使用v-if指令的元素只有当v-if指定的值为true时,这个元素才会被创建,而不是当页面渲染时就创建。如果我们需要让元素在显示和隐藏之间频繁的切换,那这时我们就比较适合用v-show,因为这样只是改变元素的样式属性,而不用频繁的创建和删除元素,消耗性能。
2、computed和watch区别
1、computed是计算属性;watch是监听,监听data中的数据变化。
2、computed支持缓存,当其依赖的属性的值发生变化时,计算属性会重新计算,反之,则使用缓存中的属性值;watch不支持缓存,当对应属性发生变化的时候,响应执行。
3、computed不支持异步,有异步操作时无法监听数据变化;watch支持异步操作。
4、computed第一次加载时就监听;watch默认第一次加载时不监听。
3、Vue生命周期理解
Vue的生命周期就是vue实例从创建到销毁的全过程,也就是new Vue() 开始就是vue生命周期的开始。Vue 实例有⼀个完整的⽣命周期,也就是从开始创建、初始化数据、编译模版、挂载Dom -> 渲染、更新 -> 渲染、卸载 等⼀系列过程,称这是Vue的⽣命周期。钩子函数是Vue生命周期中每个阶段对外开放让程序员操作Vue的接口。Vue有8个钩子函数。
创建前:
beforeCreate 组件实例被创建之初,data 和 methods 中的数据还没有初始化
创建后:
created 组件实例已经完全创建,data 和 methods 都已经初始化好了
挂载前:
beforeMount 指令已经解析完毕,内存中已经生成dom树,但是尚未挂载到页面中去
挂载后:
mounted dom渲染完毕页面和内存的数据已经同步
更新前:
beforeUpdate 组件数据更新之前调用, 此时页面中显示的数据还是旧的,但 data 是最新的,页面尚未和最新的数据保持同步
更新后:
update 组件数据更新之后,页面和 data 数据已经保持同步,都是最新的
销毁前:
beforeDestory 组件销毁前调用,vue 实例从运行阶段进入到销毁阶段,这时 vue 实例身上所有都可用,还没有真正执行销毁
销毁后:
destoryed 组件销毁后调用,vue 实例上的所有都不可以用了
4、Vue单页面(SPA)和多页面(MPA)的理解
什么是SPA:
客户端渲染。它所需的资源,如 HTML、CSS 和 JS 等,在一次请求中就加载完成,也就是不需刷新地动态加载。浏览器(Client)渲染顾名思义就是所有的页面渲染、逻辑处理、页面路由、接口请求均是在浏览器中发生。对于 SPA 来说,页面的切换就是组件或视图之间的切换。
简单来说,SPA应用程序只有一个html文件,在vue中可以通过vue-router
来局部切换组件,而非刷新整个页面,来实现无刷新切换页面的技术。
SPA的优点
- 1.页面切换快
页面每次切换跳转时,并不需要做html
文件的请求,这样就节约了很多http
发送时延,我们在切换页面的时候速度很快。
- 2.用户体验好
页面片段间的切换快,包括移动设备, 尤其是在网络环境差的时候, 因为组件已经预先加载好了, 并不需要发送网络请求, 所以用户体验好
SPA的缺点
- 1.首屏加载速度慢
首屏时需要请求一次html
,同时还要发送一次js
请求,两次请求回来了,首屏才会展示出来。相对于多页应用,首屏时间慢。
- 2.不易于SEO
SEO效果差,因为搜索引擎只认识html
里的内容,不认识js
的内容,而单页应用的内容都是靠js
渲染生成出来的,搜索引擎不识别这部分内容,也就不会给一个好的排名,会导致SPA应用做出来的网页在百度和谷歌上的排名差。
什么是MPA
MPA
多页面应用 MultiPage Application
,指有多个独立页面的应用(多个html页面),每个页面必须重复加载js、css等相关资源。多页应用跳转,需要整页资源刷新。
与 SPA
对比最大的不同即是页面路由切换由原生浏览器文档跳转(navigating across documents
)控制。 页面跳转,是返回 HTML 的。
对比
5、TCP三次握手
1、服务端新建套接字,绑定地址信息后开始监听,进入LISTEN状态。
2、客户端新建套接字绑定地址信息后调用connect,发送连接请求SYN,并进入SYN_SENT状态,等待服务器的确认。
3、服务端一旦监听到连接请求,就会将连接放入内核等待队列中,并向客户端发送SYN和确认报文段ACK,进入SYN_RECD状态。
4、客户端收到SYN+ACK报文后向服务端发送确认报文段ACK,并进入ESTABLISHED状态,开始读写数据。
5、服务端一旦收到客户端的确认报文,就进入ESTABLISHED状态,就可以进行读写数据了
6、Java中多态的理解
通俗点讲,多态就是不同对象对同一物体或事件发出不同的反应或响应。比如stuendt是一个父类,那么在操场上上体育课的学生和在教室里面的学生就是它的子类。这时上课铃声响了,上体育课的学生去操场,在教室里面上课的学生则是回教室,不同的学生有着不同的反应,这就是多态。
实现多态的条件:
1.继承:必须要有子类继承父类的继承关系。
2.重写:子类需要对父类中的一些方法进行重写,然后调用方法时就会调用子类重写的方法而不是原本父类的方法。
3.向上转型:在多态中需要将子类的引用赋给父类对象,只有这样该引用才能够具备既能调用父类的方法和子类的方法。
如:List l =new ArrayList();
7、Java中的内存溢出和内存泄漏
1、内存泄漏memory leak :
是指程序在申请内存后,无法释放已申请的内存空间,一次内存泄漏似乎不会有大的影响,但内存泄漏堆积后的后果就是内存溢出。
2、内存溢出 out of memory :
指程序申请内存时,没有足够的内存供申请者使用,或者说,给了你一块存储int类型数据的存储空间,但是你却存储long类型的数据,那么结果就是内存不够用,此时就会报错OOM,即所谓的内存溢出。
3、二者的关系:
内存泄漏的堆积最终会导致内存溢出
内存溢出就是你要的内存空间超过了系统实际分配给你的空间,此时系统相当于没法满足你的需求,就会报内存溢出的错误。
内存泄漏: 是指你向系统申请分配内存进行使用(new),可是使用完了以后却不归还(delete),结果你申请到的那块内存你自己也不能再访问(也许你把它的地址给弄丢了),而系统也不能再次将它分配给需要的程序。就相当于你租了个带钥匙的柜子,你存完东西之后把柜子锁上之后,把钥匙丢了或者没有将钥匙还回去,那么结果就是这个柜子将无法供给任何人使用,也无法被垃圾回收器回收,因为找不到他的任何信息。
内存溢出:一个盘子用尽各种方法只能装4个果子,你装了5个,结果掉倒地上不能吃了。这就是溢出。比方说栈,栈满时再做进栈必定产生空间溢出,叫上溢,栈空时再做退栈也产生空间溢出,称为下溢。就是分配的内存不足以放下数据项序列,称为内存溢出。说白了就是我承受不了那么多,那我就报错。
8、Linux常用命令
推荐这个博主的博客:https://blog.csdn.net/luansj/article/details/97272672
9、Redis数据结构有哪些
Redis支持五种数据类型:string(字符串),hash(哈希),list(列表),set(无序集合)及zset(有序集合)。
还有三个特殊类型。。
细节这里不叙述了。。
10、字符串翻转
方式一:栈
package src.com.wz.leetcode.test;
import java.util.Stack;
/**使用栈
* @author lenovo
*/
public class Test10 {
public static void main(String[] args) {
String str = "hello!";
char[] chars = str.toCharArray();
Stack<Character> stack = new Stack<>();
for (int i = 0; i < chars.length; i++) {
stack.push(chars[i]);
}
StringBuilder stringBuilder = new StringBuilder();
while (stack.size()>0){
stringBuilder.append(stack.pop());
}
System.out.println(stringBuilder.toString());
}
}
方式二:ArrayList
package src.com.wz.leetcode.test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
* @author lenovo
*/
public class Test12 {
public static void main(String[] args) {
String str ="hello!";
String[] split = str.split("");
List<String> list =new ArrayList<>();
list = Arrays.asList(split);
Collections.reverse(list);
for (String s : list) {
System.out.print(s);
}
}
}
11、查找循环链表入环节点
package src.com.wz.leetcode.test;
import java.util.Objects;
/**
* @author lenovo
*/
public class Test11 {
public static void main(String[] args) {
// 链表赋值
int[] arr ={1,2,3,4,5,6};
MyListNode list =new MyListNode(1);
MyListNode cur = list;
MyListNode cur1 = new MyListNode();
for (int i = 1; i < arr.length; i++) {
MyListNode node = new MyListNode(arr[i]);
cur.next= node;
cur = cur.next;
if (i==3){
cur1 = cur;
}
}
System.out.println(list.toString());
// 成环
cur.next = cur1;
int node = getNode(list);
System.out.println(node);
}
/**
* 快慢指针查找入环节点
* @param myListNode 有环链表
* @return 入环结点value
*/
public static int getNode(MyListNode myListNode){
MyListNode cur1 = myListNode;
MyListNode cur2 = myListNode;
cur1=cur1.next;
cur2=cur2.next.next;
while (!cur1.equals(cur2)){
cur1=cur1.next;
cur2=cur2.next.next;
}
// 第一次相遇,快指针变成慢指针
cur2 = myListNode;
while (!cur1.equals(cur2)){
cur1=cur1.next;
cur2=cur2.next;
}
// 第二次相遇返回入环结点
return cur1.value;
}
}
/**
* 链表类
*/
class MyListNode{
public int value;
public MyListNode next;
public MyListNode(){}
public MyListNode(int value) {
this.value = value;
}
@Override
public String toString() {
return "MyListNode{" +
"value=" + value +
", next=" + next +
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
MyListNode that = (MyListNode) o;
return value == that.value && Objects.equals(next, that.next);
}
@Override
public int hashCode() {
return Objects.hash(value, next);
}
}