浅谈java相关知识

Spring问题

1、 spring有哪几部分组成

a) Spring Core:
Core封装包是框架的最基础部分,提供了spring 的核心功能,提供IOC和依赖注入特性。这里的基础概念是BeanFactory,它提供对Factory模式的经典实现来消除对程序性单例模式的需要,并真正地允许你从程序逻辑中分离出依赖关系和配置。
b) Spring Context:
构建于Core封装包基础上的 Context封装包,提供了一种框架式的对象访问方法,有些象JNDI注册器。Context封装包的特性得自于Beans封装包,并添加了对国际化(I18N)的支持(例如资源绑定),事件传播,资源装载的方式和Context的透明创建,比如说通过Servlet容器。
c) Spring DAO:
DAO (Data Access Object)提供了JDBC的抽象层,它可消除冗长的JDBC编码和解析数据库厂商特有的错误代码。 并且,JDBC封装包还提供了一种比编程性更好的声明性事务管理方法,不仅仅是实现了特定接口,而且对所有的POJOs(plain old Java objects)都适用。
d) 4.Spring ORM:
ORM 封装包提供了常用的“对象/关系”映射APIs的集成层。 其中包括JPA、JDO、Hibernate 和 iBatis 。利用ORM封装包,可以混合使用所有Spring提供的特性进行“对象/关系”映射,如前边提到的简单声明性事务管理。
e) Spring AOP:
Spring的 AOP 封装包提供了符合AOP Alliance规范的面向方面的编程实现,让你可以定义,例如方法拦截器(method-interceptors)和切点(pointcuts),从逻辑上讲,从而减弱代码的功能耦合,清晰的被分离开。而且,利用source-level的元数据功能,还可以将各种行为信息合并到你的代码中。
f) Spring Web:
Spring中的 Web 包提供了基础的针对Web开发的集成特性,例如多方文件上传,利用Servlet listeners进行IOC容器初始化和针对Web的ApplicationContext。当与WebWork或Struts一起使用Spring时,这个包使Spring可与其他框架结合。
g) Spring Web MVC:
Spring中的MVC封装包提供了Web应用的Model-View-Controller(MVC)实现。Spring的MVC框架并不是仅仅提供一种传统的实现,它提供了一种清晰的分离模型,在领域模型代码和Web Form之间。并且,还可以借助Spring框架的其他特性。

2、 Springcloud 几大核心组件

五大核心组件如下:
a) 服务发现——Netflix Eureka客服端
由两个组件组成:Eureka服务端和Eureka客户端。
Eureka服务端用作服务注册中心。支持集群部署。
Eureka客户端是一个java客户端,用来处理服务注册与发现。
在应用启动时,Eureka客户端向服务端注册自己的服务信息,同时将服务端的服务信息缓存到本地。客户端会和服务端周期性的进行心跳交互,以更新服务租约和服务信息。
b) 负载均衡——Netflix Ribbon
作用:主要提供客户侧的软件负载均衡算法。
简介:Spring Cloud Ribbon是一个基于HTTP和TCP的客户端负载均衡工具,它基于Netflix Ribbon实现。通过Spring Cloud的封装,可以让我们轻松地将面向服务的REST模版请求自动转换成客户端负载均衡的服务调用。
Ribbon客户端组件提供一系列完善的配置选项,比如连接超时、重试、重试算法等。Ribbon内置可插拔、可定制的负载均衡组件。下面是用到的一些负载均衡策略:
简单轮询负载均衡
加权响应时间负载均衡
区域感知轮询负载均衡
随机负载均衡
c) 断路器——Netflix Hystrix
当微服务系统的一个服务出现故障时,故障会沿着服务的调用链路在系统中疯狂蔓延,最终导致整个微服务系统的瘫痪,这就是“雪崩效应”。为了防止此类事件的发生,微服务架构引入了“熔断器”的一系列服务容错和保护机制。
在微服务系统中,Hystrix 能够帮助我们实现以下目标:
保护线程资源:防止单个服务的故障耗尽系统中的所有线程资源。
快速失败机制:当某个服务发生了故障,不让服务调用方一直等待,而是直接返回请求失败。
提供降级(FallBack)方案:在请求失败后,提供一个设计好的降级方案,通常是一个兜底方法,当请求失败后即调用该方法。
防止故障扩散:使用熔断机制,防止故障扩散到其他服务。
监控功能:提供熔断器故障监控组件 Hystrix Dashboard,随时监控熔断器的状态。
d) 服务网关——Netflix Zuul(gateway)
客户端发送请求,会到达网关的DispatcherHandler处理,匹配到RoutePredicateHandlerMapping。
根据RoutePredicateHandlerMapping匹配到具体的路由策略。
FilteringWebHandler获取的路由的GatewayFilter数组,创建 GatewayFilterChain 处理过滤请求
执行我们的代理业务逻辑访问。
e) 分布式配置——Spring Cloud Config
Spring Cloud Config 为微服务架构中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。
//so.csdn.net/so/search?q=架构&spm=1001.2101.3001.7020)中的微服务提供集中化的外部配置支持,配置服务器为各个不同微服务应用的所有环境提供了一个中心化的外部配置。
config动态刷新,解决每次配置更新都要重启服务才能

3、 Java多线程

a) Thread的构造方法参数可以传入Runnable接口和FutureTask对象
Runnable缺少的一项功能是,当线程终止时(即run()完成时),我们无法使线程返回结果。为了支持此功能,Java中提供了Callable接口。
继承Thread类
(1)定义Thread类的子类,并重写该类的run方法,该run方法的方法体就代表了线程要完成的任务。因此把run()方法称为执行体。
(2)创建Thread子类的实例,即创建了线程对象。
(3)调用线程对象的start()方法来启动该线程。
b) 实现runable接口
(1)定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
(2)创建 Runnable实现类的实例,并依此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
(3)调用线程对象的start()方法来启动该线程
c) 实现Callable接口(创建FutureTask(Callable)对象)
Callable接口中就一个抽象方法call(),有返回值
Future接口中定义了关于线程状态的方法,比如打断线程执行的cancel方法,判断该线程是否被取消的isCancelled()方法,返回线程是否执行完的isDone方法,以及重要的get方法获取返回值
FutureTask实现类实现了Future接口,并且有构造函数,参数是传入一个Callable接口,
以此获得返回值
其中Future接口的get方法是阻塞方法,没有得到get的值会阻塞主线程
d) 什么是Callable和Future
Callable 接口类似于 Runnable,从名字就可以看出来了,但是 Runnable 不会返 回结果,并且无法抛出返回结果的异常,而 Callable 功能更强大一些,被线程执 行后,可以返回值,这个返回值可以被 Future 拿到,也就是说,Future 可以拿到 异步执行任务的返回值。可以认为是带有回调的 Runnable。Future 接口表示异步任务,是还没有完成的任务给出的未来结果。所以说 Callable用于产生结果,Future 用于获取结果
e) 什么是线程的上下文切换?
多线程的上下文切换是指 CPU 控制权由一个已经正在运行的线程切换到另外一个就绪并等待获取 CPU 执行权的线程的过程。
可能有以下原因:
线程的 cpu 时间片用完(每个线程轮流执行,看前面并发的概念)
垃圾回收
有更高优先级的线程需要运行
线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法
当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态
f) 如何停止一个正在运行的线程?
(1)使用stop()来停止线程:stop()方法让线程立即停止运行, 这种暴力停止可能会破坏线程业务的原子性,不推荐使用
(2)使用interrupt产生打断标志位来停止线程
g) sleep,yield为什么是静态方法
Thread 类的 sleep()和 yield()方法将在当前正在执行的线程上运行。其他线程上调用这些方法是没有意义的。也就是说只有本线程才能执行休眠操作,如果sleep是成员方法,其他线程可以获得该线程的实例化对象,从而让此线程强制休眠(释放CPU的资源),这样会带来不可预估的后果。

4、 mybatis

a) mybatis核心处理类叫什么
mybatis核心处理累叫 sqlSession
b) # 和 $ 的区别

获取变量的值,$ 获取原变量

c) 如何手动创建应SqlSession对象
用DefaultSqlSessionFactorych

5、 Redis

a) Redis基本数据结构类型,应用场景
String(字符串)
应用场景:共享session、分布式锁,计数器、限流。
Hash(哈希)
应用场景:缓存用户信息等。
List(列表)
应用场景:消息队列,文章列表
Set(集合)
应用场景:用户标签,生成随机数抽奖、社交需求。
zset(有序集合)
它还有三种特殊的数据结构类型
Geospatial
地理位置定位,用于存储地理位置信息,并对存储的信息进行操作。
Hyperloglog
用来做基数统计算法的数据结构,如统计网站的UV。
Bitmap
用一个比特位来映射某个元素的状态,在Redis中,它的底层是基于字符串类型实现的,可以把bitmaps成作一个以比特位为单位的数组
b) Redis 为什么这么快
i. 基于内存存储实现
我们都知道内存读写是比在磁盘快很多的,Redis基于内存存储实现的数据库,相对于数据存在磁盘的MySQL数据库,省去磁盘I/O的消耗。

ii. 高效的数据结构
我们知道,Mysql索引为了提高效率,选择了B+树的数据结构。其实合理的数据结构,就是可以让你的应用/程序更快。
iii. 合理的数据编码
Redis 支持多种数据数据类型,每种基本类型,可能对多种数据结构。什么时候,使用什么样数据结构,使用什么样编码,是redis设计者总结优化的结果。

iv. 合理的线程模型
Redis是单线程模型的,而单线程避免了CPU不必要的上下文切换和竞争锁的消耗。也正因为是单线程,如果某个命令执行过长(如hgetall命令),会造成阻塞。Redis是面向快速执行场景的数据库。,所以要慎用如smembers和lrange、hgetall等命令。Redis 6.0 引入了多线程提速,它的执行命令操作内存的仍然是个单线程。
v. 虚拟内存机制
Redis直接自己构建了VM机制 ,不会像一般的系统会调用系统函数处理,会浪费一定的时间去移动和请求。
vi. 什么是缓存击穿、缓存穿透、缓存雪崩?
缓存穿透:指查询一个一定不存在的数据,由于缓存是不命中时需要从数据库查询,查不到数据则不写入缓存,这将导致这个不存在的数据每次请求都要到数据库去查询,进而给数据库带来压力。
如何避免缓存穿透呢? 一般有三种方法。
1.如果是非法请求,我们在API入口,对参数进行校验,过滤非法值。
2.如果查询数据库为空,我们可以给缓存设置个空值,或者默认值。但是如有写请求进来的话,需要更新缓存,以保证缓存一致性,同时,最后给缓存设置适当的过期时间。(业务上比较常用,简单有效)
3.使用布隆过滤器快速判断数据是否存在。即一个查询请求过来时,先通过布隆过滤器判断值是否存在,存在才继续往下查。
缓存雪奔: 指缓存中数据大批量到过期时间,而查询数据量巨大,请求都直接访问数据库,引起数据库压力过大甚至down机。
缓存击穿: 指热点key在某个时间点过期的时候,而恰好在这个时间点对这个Key有大量的并发请求过来,从而大量的请求打到db。
解决方案就有两种:
1.使用互斥锁方案。缓存失效时,不是立即去加载db数据,而是先使用某些带成功返回的原子操作命令,如(Redis的setnx)去操作,成功的时候,再去加载db数据库数据和设置缓存。否则就去重试获取缓存。
2. “永不过期”,是指没有设置过期时间,但是热点数据快要过期时,异步线程去更新和设置过期时间。
c) 说说Redis的常用应用场景
缓存、排行榜、计数器应用、共享Session、分布式锁、社交网络、消息队列、位操作

i. 缓存
我们一提到redis,自然而然就想到缓存,国内外中大型的网站都离不开缓存。合理的利用缓存,比如缓存热点数据,不仅可以提升网站的访问速度,还可以降低数据库DB的压力。并且,Redis相比于memcached,还提供了丰富的数据结构,并且提供RDB和AOF等持久化机制,强的一批。
ii. 排行榜
当今互联网应用,有各种各样的排行榜,如电商网站的月度销量排行榜、社交APP的礼物排行榜、小程序的投票排行榜等等。Redis提供的zset数据类型能够实现这些复杂的排行榜。
计数器应用
各大网站、APP应用经常需要计数器的功能,如短视频的播放数、电商网站的浏览数。这些播放数、浏览数一般要求实时的,每一次播放和浏览都要做加1的操作,如果并发量很大对于传统关系型数据的性能是一种挑战。Redis天然支持计数功能而且计数的性能也非常好,可以说是计数器系统的重要选择。
iii. 共享Session
如果一个分布式Web服务将用户的Session信息保存在各自服务器,用户刷新一次可能就需要重新登录了,这样显然有问题。实际上,可以使用Redis将用户的Session进行集中管理,每次用户更新或者查询登录信息都直接从Redis中集中获取。
iv. 分布式锁
几乎每个互联网公司中都使用了分布式部署,分布式服务下,就会遇到对同一个资源的并发访问的技术难题,如秒杀、下单减库存等场景。
用synchronize或者reentrantlock本地锁肯定是不行的。
如果是并发量不大话,使用数据库的悲观锁、乐观锁来实现没啥问题。
但是在并发量高的场合中,利用数据库锁来控制资源的并发访问,会影响数据库的性能。
实际上,可以用Redis的setnx来实现分布式的锁。
v. 社交网络
赞/踩、粉丝、共同好友/喜好、推送、下拉刷新等是社交网站的必备功能,由于社交网站访问量通常比较大,而且传统的关系型数据不太适保存 这种类型的数据,Redis提供的数据结构可以相对比较容易地实现这些功能。
vi. 消息队列
消息队列是大型网站必用中间件,如ActiveMQ、RabbitMQ、Kafka等流行的消息队列中间件,主要用于业务解耦、流量削峰及异步处理实时性低的业务。Redis提供了发布/订阅及阻塞队列功能,能实现一个简单的消息队列系统。另外,这个不能和专业的消息中间件相比。
vii. 位操作
用于数据量上亿的场景下,例如几亿用户系统的签到,去重登录次数统计,某用户是否在线状态等等。腾讯10亿用户,要几个毫秒内查询到某个用户是否在线,能怎么做?千万别说给每个用户建立一个key,然后挨个记(你可以算一下需要的内存会很恐怖,而且这种类似的需求很多。这里要用到位操作——使用setbit、getbit、bitcount命令。原理是:redis内构建一个足够长的数组,每个数组元素只能是0和1两个值,然后这个数组的下标index用来表示用户id(必须是数字),那么很显然,这个几亿长的大数组就能通过下标和元素值(0和1)来构建一个记忆系统。
d) 使用过Redis分布式锁嘛?有哪些注意点呢?
分布式锁,是控制分布式系统不同进程共同访问共享资源的一种锁的实现。秒杀下单、抢红包等等业务场景,都需要用到分布式锁,我们项目中经常使用Redis作为分布式锁。
选了Redis分布式锁的几种实现方法,大家来讨论下,看有没有啥问题哈。
命令setnx + expire分开写
if(jedis.setnx(key,lock_value) == 1){ //加锁 expire(key,100); //设置过期时间 try { do something //业务请求 }catch(){ } finally { jedis.del(key); //释放锁 } }
如果执行完setnx加锁,正要执行expire设置过期时间时,进程crash掉或者要重启维护了,那这个锁就“长生不老”了,别的线程永远获取不到锁啦,所以分布式锁不能这么实现。
setnx + value值是过期时间
long expires = System.currentTimeMillis() + expireTime; //系统时间+设置的过期时间 String expiresStr = String.valueOf(expires); // 如果当前锁不存在,返回加锁成功 if (jedis.setnx(key, expiresStr) == 1) { return true; } // 如果锁已经存在,获取锁的过期时间 String currentValueStr = jedis.get(key); // 如果获取到的过期时间,小于系统当前时间,表示已经过期 if (currentValueStr != null && Long.parseLong(currentValueStr) < System.currentTimeMillis()) { // 锁已过期,获取上一个锁的过期时间,并设置现在锁的过期时间(不了解redis的getSet命令的小伙伴,可以去官网看下哈) String oldValueStr = jedis.getSet(key_resource_id, expiresStr); if (oldValueStr != null && oldValueStr.equals(currentValueStr)) { // 考虑多线程并发的情况,只有一个线程的设置值和当前值相同,它才可以加锁 return true; } } //其他情况,均返回加锁失败 return false; }
笔者看过有开发小伙伴是这么实现分布式锁的,但是这种方案也有这些缺点:
过期时间是客户端自己生成的,分布式环境下,每个客户端的时间必须同步。
没有保存持有者的唯一标识,可能被别的客户端释放/解锁。
锁过期的时候,并发多个客户端同时请求过来,都执行了jedis.getSet(),最终只能有一个客户端加锁成功,但是该客户端锁的过期时间,可能被别的客户端覆盖。
set的扩展命令(set ex px nx)
if(jedis.set(key, lock_value, “NX”, “EX”, 100s) == 1){ //加锁 try { do something //业务处理 }catch(){ } finally { jedis.del(key); //释放锁 } }
这个方案可能存在这样的问题:
锁过期释放了,业务还没执行完。
锁被别的线程误删。
set ex px nx + 校验唯一随机值,再删除
if(jedis.set(key, uni_request_id, “NX”, “EX”, 100s) == 1){ //加锁 try { do something //业务处理 }catch(){ } finally { //判断是不是当前线程加的锁,是才释放 if (uni_request_id.equals(jedis.get(key))) { jedis.del(key); //释放锁 } } }
在这里,判断当前线程加的锁和释放锁是不是一个原子操作。如果调用jedis.del()释放锁的时候,可能这把锁已经不属于当前客户端,会解除他人加的锁。
e) MySQL与Redis 如何保证双写一致性
缓存延时双删
先删除缓存
再更新数据库
休眠一会(比如1秒),再次删除缓存。
删除缓存重试机制
写请求更新数据库
缓存因为某些原因,删除失败
把删除失败的key放到消息队列
消费消息队列的消息,获取要删除的key
重试删除缓存操作
读取binlog异步删除缓存
以mysql为例吧
可以使用阿里的canal将binlog日志采集发送到MQ队列里面
然后通过ACK机制确认处理这条更新消息,删除缓存,保证数据缓存一致性
f) Redis 事务机制
Redis通过MULTI、EXEC、WATCH等一组命令集合,来实现事务机制。事务支持一次执行多个命令,一个事务中所有命令都会被序列化。在事务执行过程,会按照顺序串行化执行队列中的命令,其他客户端提交的命令请求不会插入到事务执行命令序列中。
简言之,Redis事务就是顺序性、一次性、排他性的执行一个队列中的一系列命令。
Redis执行事务的流程如下:
开始事务(MULTI)
命令入队
执行事务(EXEC)、撤销事务(DISCARD )
g) Redis底层,使用的什么协议?
RESP,英文全称是Redis Serialization Protocol,它是专门为redis设计的一套序列化协议. 这个协议其实在redis的1.2版本时就已经出现了,但是到了redis2.0才最终成为redis通讯协议的标准。RESP主要有实现简单、解析速度快、可读性好等优点。

6、 数据库

a) 索引的数据结构
索引的数据结构主要有B+树和哈希表,对应的索引分别为B+树索引和哈希索引。InnoDB引擎的索引类型有B+树索引和哈希索引,默认的索引类型为B+树索引。
B+树索引
B+ 树是基于B 树和叶子节点顺序访问指针进行实现,它具有B树的平衡性,并且通过顺序访问指针来提高区间查询的性能。
在 B+ 树中,节点中的 key 从左到右递增排列,如果某个指针的左右相邻 key 分别是 keyi 和 keyi+1,则该指针指向节点的所有 key 大于等于 keyi 且小于等于 keyi+1。

进行查找操作时,首先在根节点进行二分查找,找到key所在的指针,然后递归地在指针所指向的节点进行查找。直到查找到叶子节点,然后在叶子节点上进行二分查找,找出key所对应的数据项。
MySQL 数据库使用最多的索引类型是BTREE索引,底层基于B+树数据结构来实现。
哈希索引
哈希索引是基于哈希表实现的,对于每一行数据,存储引擎会对索引列进行哈希计算得到哈希码,并且哈希算法要尽量保证不同的列值计算出的哈希码值是不同的,将哈希码的值作为哈希表的key值,将指向数据行的指针作为哈希表的value值。这样查找一个数据的时间复杂度就是O(1),一般多用于精确查找。

b) 常见的存储引擎有哪些?
MySQL中常用的四种存储引擎分别是: MyISAM、InnoDB、MEMORY、ARCHIVE。MySQL 5.5版本后默认的存储引擎为InnoDB。
InnoDB存储引擎
InnoDB是MySQL默认的事务型存储引擎,使用最广泛,基于聚簇索引建立的。InnoDB内部做了很多优化,如能够自动在内存中创建自适应hash索引,以加速读操作。
优点:支持事务和崩溃修复能力;引入了行级锁和外键约束。
缺点:占用的数据空间相对较大。
适用场景:需要事务支持,并且有较高的并发读写频率。
c) 乐观锁和悲观锁是什么?
数据库中的并发控制是确保在多个事务同时存取数据库中同一数据时不破坏事务的隔离性和统一性以及数据库的统一性。乐观锁和悲观锁是并发控制主要采用的技术手段。
悲观锁:假定会发生并发冲突,在查询完数据的时候就把事务锁起来,直到提交事务。实现方式:使用数据库中的锁机制。
乐观锁:假设不会发生并发冲突,只在提交操作时检查是否数据是否被修改过。给表增加version字段,在修改提交之前检查version与原来取到的version值是否相等,若相等,表示数据没有被修改,可以更新,否则,数据为脏数据,不能更新。实现方式:乐观锁一般使用版本号机制或CAS算法实现。

7、 Elasticsearch

a) elasticsearch的倒排索引是什么
通俗解释一下就可以。
传统的我们的检索是通过文章,逐个遍历找到对应关键词的位置。
而倒排索引,是通过分词策略,形成了词和文章的映射关系表,这种词典+映射表即为倒排索引。
有了倒排索引,就能实现o(1)时间复杂度的效率检索文章了,极大的提高了检索效率。
b) 详细描述一下Elasticsearch索引文档的过程
第一步:客户写集群某节点写入数据,发送请求。(如果没有指定路由/协调节点,请求的节点扮演路由节点的角色。)
第二步:节点1接受到请求后,使用文档_id来确定文档属于分片0。请求会被转到另外的节点,假定节点3。因此分片0的主分片分配到节点3上。
第三步:节点3在主分片上执行写操作,如果成功,则将请求并行转发到节点1和节点2的副本分片上,等待结果返回。所有的副本分片都报告成功,节点3将向协调节点(节点1)报告成功,节点1向请求客户端报告写入成功。
如果面试官再问:第二步中的文档获取分片的过程?
回借助路由算法获取,路由算法就是根据路由和文档id计算目标的分片id的过程。

8、 Vue

a) vue生命周期

beforeCreate created beforeMount mounted beforeUpdate updated
beforeDestroy destroyed
在这里插入图片描述

b) VUE双向数据绑定原理和实现
1.vue 双向数据绑定是通过 数据劫持 结合 发布订阅模式的方式来实现的, 也就是说数据和视图同步,数据发生变化,视图跟着变化,视图变化,数据也随之发生改变;
2.核心:关于VUE双向数据绑定,其核心是 Object.defineProperty()方法;
3.介绍一下Object.defineProperty()方法
(1)Object.defineProperty(obj, prop, descriptor) ,这个语法内有三个参数,分别为 obj (要定义其上属性的对象) prop (要定义或修改的属性) descriptor (具体的改变方法)
(2)简单地说,就是用这个方法来定义一个值。当调用时我们使用了它里面的get方法,当我们给这个属性赋值时,又用到了它里面的set方法;

9、 VUEX

a) vuex是什么?怎么使用?哪种功能场景使用它?
Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。简单来说就是:应用遇到多个组件共享状态时,使用vuex。
场景:多个组件共享数据或者是跨组件传递数据时
vuex的流程
页面通过mapAction异步提交事件到action。action通过commit把对应参数同步提交到mutation,mutation会修改state中对应的值。最后通过getter把对应值跑出去,在页面的计算属性中,通过,mapGetter来动态获取state中的值
b) vuex得五个属性
有五种,分别是State , Getter , Mutation , Action , Module (就是mapAction)

state:vuex的基本数据,用来存储变量
getter:从基本数据(state)派生的数据,相当于state的计算属性
mutation:提交更新数据的方法,必须是同步的(如果需要异步使用action)。每个mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数,提交载荷作为第二个参数。
action:和mutation的功能大致相同,不同之处在于 ==》1. Action 提交的是 mutation,而不是直接变更状态。 2. Action 可以包含任意异步操作。
modules:模块化vuex,可以让每一个模块拥有自己的state、mutation、action、getters,使得结构非常清晰,方便管理。
c) 不用 Vuex 会带来什么问题
1.可维护性会下降,你要修改数据,你得维护 3 个地方
2.可读性下降,因为一个组件里的数据,你根本就看不出来是从哪里来的
3.增加耦合,大量的上传派发,会让耦合性大大的增加,本来 Vue 用 Component 就是为了减少耦合,现在这么用,和组件化的初衷相背
d) Vuex中actions和mutations的区别
Mutation 更改 Vuex 的 store 中的状态的唯一方法是提交 mutation。Vuex 中的 mutation 非常类似于事件:每个 mutation 都有一个字符串的 事件类型 (type) 和 一个 回调函数 (handler)。这个回调函数就是我们实际进行状态更改的地方,并且它会接受 state 作为第一个参数
Action Action 类似于 mutation,不同在于:
Action 提交的是 mutation,而不是直接变更状态。
Action 可以包含任意异步操作。

10、 vue-router

a) 怎么定义 vue-router 的动态路由? 怎么获取传过来的值
可以通过query ,param两种方式
区别: query通过url传参,刷新页面还在 params刷新页面不在了
params的类型:
配置路由格式:/router/:id
传递的方式:在path后面跟上对应的值
传递后形成的路径:/router/123

query的类类型
配置路由格式:/router,也就是普通配置
传递的方式:对象中使用query的key作为传递方式
传递后形成的路径:/route?id=123
b) vue-router 有哪几种导航钩子
1、全局守卫:router.beforeEach
2、全局解析守卫:router.beforeResolve
3、全局后置钩子:router.afterEach
4、路由独享的守卫:beforeEnter
5、组件内的守卫:beforeRouteEnter、beforeRouteUpdate (2.2 新增)、beforeRouteLeave
c) route和router 的区别
1.router是VueRouter的一个对象
2.route是一个跳转的路由对象

11、 JS

a) let、var 和 const 的区别
let/const 声明并不会被提升到当前代码块的顶部,因此你需要手动将 let/const 声明放置到顶部,
以便让变量在整个代码块内部可用。
块级作用域:1、在一个函数内部;2、在一个代码块(由一对花括号包裹)内部
禁止重复声明
var定义的变量,没有块的概念,可以跨块访问, 不能跨函数访问。
let定义的变量,只能在块作用域里访问,不能跨块访问,也不能跨函数访问。
const用来定义常量,使用时必须初始化(即必须赋值),只能在块作用域里访问,而且不能修改。
b) this 指向
1.在浏览器中,在全局范围内this 指向window对象
2.在函数中,this永远指向最后调用他的那个对象;
3.构造函数中,this指向new出来的那个新的对象;
4.call、apply、bind中的this被强绑定在指定的那个对象上;
==>js给函数内置的一些API,调用他们可以为函数指定this的执行,同时也可以传参。
5.箭头函数中this比较特殊,箭头函数this为父作用域的this,不是调用时的this.要知道前四种方式,都是调用时确定,也就是动态的,而箭头函数的this指向是静态的,声明的时候就确定了下来;

12、 plugins

a) webpack核心概念
Entry:入口起点(entry point)指示 webpack 应该使用哪个模块,来作为构建其内部依赖图的开始。
进入入口起点后,webpack 会找出有哪些模块和库是入口起点(直接和间接)依赖的。
每个依赖项随即被处理,最后输出到称之为 bundles 的文件中。
Output:output 属性告诉 webpack 在哪里输出它所创建的 bundles,以及如何命名这些文件,默认值为 ./dist。
基本上,整个应用程序结构,都会被编译到你指定的输出路径的文件夹中。
Module:模块,在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
Chunk:代码块,一个 Chunk 由多个模块组合而成,用于代码合并与分割。
Loader:loader 可以将所有类型的文件转换为 webpack 能够处理的有效模块,然后你就可以利用 webpack 的打包能力,对它们进行处理。 本质上,webpack loader 将所有类型的文件,转换为应用程序的依赖图(和最终的 bundle)可以直接引用的模块。
Plugins: loader 被用于转换某些类型的模块,而plugins(插件)则可以用于执行范围更广的任务。 插件的范围包括,从打包优化和压缩,一直到重新定义环境中的变量。插件接口功能极其强大,可以用来处理各种各样的任务。
b) Loader工作原理
loader是用来加载处理各种形式的资源的机制,本质上是一个函数, 接受文件作为参数,返回转化后的结构。
loader是运行在NodeJS中的。因为webpack不认识一些外来模块,所以要使用一些加载器,比如识别css/react/vue/png等。
loader虽然是扩展了 webpack ,但是它只专注于转化文件(transform)这一个领域,完成压缩,打包,语言翻译。
例如:css-loader和style-loader模块是为了打包css的
babel-loader和babel-core模块时为了把ES6的代码转成ES5 url-loader和file-loader是把图片进行打包的。
c) plugin工作原理
plugin是一个具有apply方法的 js对象。 apply方法会被 webpack的compiler(编译器)对象调用,并且compiler 对象可在整个compilation(编译)生命周期内访问。
plugins是作用于webpack本身上的。webpack提供了很多开箱即用的插件 插件可以携带参数,所以可以在plugins属性传入new实例:
1)CommonChunkPlugin主要用于提取第三方库和公共模块,避免首屏加载的bundle文件,或者按需加载的bundle文件体积过大,导致加载时间过长,是一把优化的利器。而在多页面应用中,更是能够为每个页面间的应用程序共享代码创建bundle。
2)针对html文件打包和拷贝(还有很多设置)的插件:html-webpack-plugin其不但完成了html文件的拷贝,打包,还给html中自动增加了引入打包后的js文件的代码(),还能指明把js文 件引入到html文件的底部等等。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码农界的老油条

你的支持是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值