优启通软件加载不出来中优省优惠的URL,是什么?

vue前端面试题2022_前端常见面试题然后现在也是找了一些在Vue方面经常出现的面试题,留给自己查看消化,也分享给有需要的小伙伴。如果文章中有出现纰漏、错误之处,还请看到的小伙伴留言指正,先行谢过。以下↓/

【正版授权,激活自己账号】:

【官方授权 正版激活】:

1、星型模型、雪花模型

 1:星型模型、雪花模型的优缺点?

查询性能:雪花模型维度表、事实表之间的联接很多,性能比较低;星型模型数据冗余存储所以很多统计查询不需要做外部的连接。
模型复杂度:星型架构更简单。雪花模型数据模型的业务层级是由一个不同维度表主键-外键的关系来代表的。而在星形模型中,所有必要的维度表在事实表中都只拥有外键。
层次概念:雪花型架构更加贴近OLTP系统的结构,比较符合业务逻辑,层次比较清晰。
存储空间:雪花模型使用的是规范化数据,不会产生冗余数据,能够减少数据量,而相比之下星型架构会产生数据冗余。
ETL处理:雪花模型由于附属模型的限制,ETL相对复杂,不能并行化。星形模型加载维度表,不需要再维度之间添加附属模型,因此ETL就相对简单,而且可以实现高度的并行化。
适用场景:雪花模型更加适合维度分析的场景,星型模型更加适合指标分析的场景。

雪花模型适用场景:根据我们的项目经验,一般建议使用星型架构。因为我们在实际项目中,往往最关注的是查询性能问题,至于磁盘空间一般都不是问题。当然,在维度表数据量极大,需要节省存储空间的情况下,或者是业务逻辑比较复杂、必须要体现清晰的层次概念情况下,可以使用雪花型维度。

1、一个用户维度表且数据量较大。其中,80%的事实度量表是匿名访问者,仅包含少数详细信息。20%的是可靠的注册用户,且这些注册用户有较为详细的信息,与多个维度表中的数据相连。

2、例如一个金融产品维度表,且这些金融产品有银行类的,保险类等等区别。因此不同种类的产品有自己一系列的特殊属性,且这些属性并非是所有产品共享的。

3、多个企业共用的日历维度表。但每个企业的财政周期不同,节假日不同等等。在数据仓库的环境中用雪花模型,降低储存的空间,到了具体某个主题的数据集市再用星型模型。

雪花模型使得维度分析更加容易,比如“针对特定的广告主,有哪些客户或者公司是在线的?”,星形模型用来做指标分析更适合,比如“给定的一个客户他们的收入是多少?”

1.没有对应的维度表的维度。2.存储在事实表中

不可能将所有与业务相关的维度分类到一个紧凑的表集合中。类似这样的情况,将一个或者多个维度存储到事实表中是合适的选择。采用这种方法,存储事实表中的维度列被称为退化维度,退化维度的过程称为维度退化。这种退化维度一般都是事务的编号,如订单编号、发票编号等。这类编号需要保存到事实表中,但是不需要对应的维度表,所以称为退化维度。

规范化定义:当一个维度没有数据仓库需要的任何数据的时候就可以退化此维度,需要把退化的相关数据迁移到事实表中,然后删除退化的维度。与其他存储在维表中的维度一样 ,退化维度也可以用来进行事实表的过滤查询、实现聚合操作等。

退化维度常见于事务和累积快照事实表中。

退化维度通常被保留作为操作型事务的标识符。实际上可以将订单号作为一个属性加入到事实表中。这样订单维度就没有数据仓库需要的任何数据, 此时就可以退化订单维度。需要把退化维度的相关数据迁移到事实表中, 然后删除退化的维度。

核心理解:退化维度没有对应对应的维表,没有修饰它的属性,但是呢,通过它你可以获取一些内容,一些事实,比如说订单编号,你可以通过它获得这个订单里面包含哪些商品,对应的付款人是谁等。注意,对于不变维度,可以进行退化,对于缓慢变化维度,视具体情况而定,如果忽略缓慢变化维度的影响可以退化,否则不建议退化。优点:
维度退化在事实表中有利于使用,一般一个维度键都有对应的维表,如果退化在事实表中,
可以减少关联次数,并且退化维可以用于group by操作,进行分组统计

弊端:灵活度下降、耦合增多、冗余存储

一些维度表的数据不是静态的,而是会随着时间而缓慢地变化(这里的缓慢是相对事实表而言,事实表数据变化的速度比维度表快)。这种随着时间发生变化的维度称之为缓慢变化维把处理维度表数据历史变化的问题,称为缓慢变化维问题,简称SCD问题

对于某些维度属性,值不会发生变化,因此可以保留初始值,此方法什么也不做。例如日期维度的大多数属性,值都不会发生变化,如月份、季度、是否节假日等属性。

该类型和业务系统保持一致,直接update,将维度属性修改为最新值,直接覆盖原有的值,不保留历史信息。该类型总是反映最近的情况,会破坏历史情况,因此适合业务只关心最新属性值、不关心历史信息的情况。

在维度表中增加新的一行,新行中采用新的属性值。此方式及其变种是处理缓慢变化维的主要技术。

该方法在维度表中增加新的一列以保存原来的属性值。

当某维表是一个大型维度表,采用方式3时,如果某些维度属性变化相对较快,这将导致维度表中的数据量增长过快,带来过多的数据冗余存储,该维表变得越来越大,导致存储压力和性能压力,严重影响对历史数据的查询、分析效率。

此种方式比较暴力,每天保留全量维度属性的快照数据,自然键及日期键作为事实表的外键。此方式依托的是当前存储成本远低于计算成本,以空间换时间的理念。

7.拉链表是方式3的变形,对于有变化频率不太高的维度属性,相较于方式6,大大降低了存储;对于变化频率很高的维度属性,不适用此方法,可考虑垂直拆分。

不止上面7种,还有三种组合方式(微型维度与方式2支架、方式2属性增加到方式3维度、双重外键并且方式2与方式3的结合)不常用。

方式2适合不关心历史信息的业务场景;

方式3最为常用,但不适合处理变化十分迅速的维度属性;

方式4不太常用,适合维度变化次数很少(如不超过两次)的场景;

大数据时代,方式6、7比较常见。

方式6简单粗暴、易于理解和使用,但是存储成本高,造成了很大的存储空间的浪费;

方式7相对存储空间小,但是使用成本高,对于BI及其他下游使用人员来讲,不易于理解,另外该方法可以很方便的找到某一时间有效的数据(生效日期<= 选择的时间<=失效日期),但是对于某一段时间生效的数据则不太好关联,需要做技术改造。

Hash shuffle一种是普通运行机制,另一种是合并的运行机制。

每个分区是一个task
磁盘小文件多,I/O增多,产生的GC会增多。
这种shuffle产生的磁盘小文件,容易导致OOM

这种模式不单单产生的磁盘小文件比较多,而且占用内存也比较多。
我们应该降低这种磁盘之间的接触。

如果 Reducer 端的并行任务或者是数据分片过多的话则 Core * Reducer Task 依旧过大,也会产生很多小文件。

最终溢写的小的磁盘小文件合并成为了一个大的磁盘小文件
当不需要排序的时候,默认使用Bypass机制

spark容错重试机制

在大作业(处理的数据量比较大)的情况下,建议可以设置为8次

额外增加程序鲁棒性的机制

默认参数是3次。shuffle拉取数据的时候,有可能连接的那台机器正在gc,响应不了,所以拉取shuffle-io有重试,还可以设置重试的间隔等等,这里就不列出来了

spark中,相互通信,基本上都是rpc发送,举个例子,一个task处理完了,通过spark内置的RPC框架往endpoint发送处理完了的消息,RPC的服务端,拿到这个消息做一个后续的处理,这之间的通信也需要有重试等机制,如果处理的数据量比较大,应该适当增加上述参数的时间

其实我一直不太爱用推测执行,原因是这样的,当某个task执行很慢的时候,排除机器的问题,那基本上是数据倾斜,既然是数据倾斜,那我再启动另一个task来跑,同样是很慢,没什么太大区别,所以推测执行的适用场景,应该是:

1、部分机器性能不行,相同数据量的task分发到这些机器上运行会比其他机器慢很多

2、由于数据本地化策略,把大部分任务扔到了相同的几台机器上运行,其他机器围观

3、部分task由于一些奇怪的原因卡住了

类似以上的情况,可以尝试开启推测执行来解决问题,但是推测执行势必会影响spark任务的运行速度

黑名单机制的配置参数越来越多,证明spark是有在这上面花功夫的。本质上来讲,其实就是大数据集群的部分机器可能因为某些原因(比如坏盘,cpu/io爆满),导致分发到该机器上的task并不能完成,但是由于数据本地化策略,有可能task失败重试的时候又分发到这台机器上,这就很不合理。所以可以设置,当一个task在某台机器上失败多少次,该台机器就会被加入黑名单

其他相关参数请看spark官网,因为不同版本配置不一样!

我没有截全,还是不少的

cache机制算是代码和数据层面的容错机制

cache机制会保留数据在内存或者磁盘上,并且保留RDD的上下游依赖关系

他的大致的原理是这样的,数据流入spark,会根据用户写的代码构建DAG图,会生成不同的RDD,并且他们之间有上下游的依赖关系。

checkpoint有点像快照,像spark和flink这种提供流式的数据处理框架,基本上都会提供这种机制。

checkpoint机制,像是cache的一个递进的解决方案,当我们cache数据的时候,数据可能会存在内存中或者某部分机器的磁盘上,如果这些机器挂掉了,那cache失效,结果还是要从最原始的地方拉取数据

checkpoint机制可以帮助你,把数据的结果写入分布式存储系统里,比如HDFS,通过HDFS来保证数据的不丢失,这样就算spark任务挂掉了,下次启动spark任务的时候还能够重新读到上一次checkpoint的数据,这个机制,一般用于流式的数据处理,记录偏移量等操作

整理vue常见基础面试题

    • 计算属性,依赖其他属性值,且值具备缓存的特性。只有它依赖的属性值发生改变,下一次获取的值才会重新计算。
    • 当一个属性受多个属性影响的时候就需要用到computed
    • 适用于数值计算,并且依赖于其他属性时。因为可以利用缓存特性,避免每次获取值,都需要重新计算。购物车商品结算的时候
    • 当一条数据影响多条数据的时候就需要用watch
    • 观察属性,监听属性值变动。每当属性值发生变化,都会执行相应的回调。
    • 适用于数据变化时执行异步或开销比较大的操作。搜索数据

9.vue组件中data为什么必须是一个函数,key的作用

组建中的data写成一个函数,数据以函数返回值的形式定义,这样每次复用组件的时候,都会返回一份新的data,相当于每个组件实例都有自己私有的数据空间,它们只负责各自维护的数据,不会造成混乱。而单纯的写成对象形式,就是所有的组件实例共用了一个data,这样改一个全都改了。

  • 因为JavaScript的特性所导致,在component中,data必须以函数的形式存在,不可以是对象。
  • 需要使用key来给每个节点做一个唯一标识,Diff算法就可以正确的识别此节点。作用主要是为了高效的更新虚拟DOM。

当你修改了data的值然后马上获取这个dom元素的值,是不能获取到更新后的值,
你需要使用$nextTick这个回调,让修改后的data值渲染更新到dom元素之后在获取,才能成功。

10.单页面应用(SPA)和多页面应用(MPA)区别及优缺点

  • SPA:通俗一点说就是指只有一个主页面的应用,浏览器一开始要加载所有必须的 html, js, css。所有的页面内容都包含在这个所谓的主页面中。但在写的时候,还是会分开写(页面片段),然后在交互的时候由路由程序动态载入,单页面的页面跳转,仅刷新局部资源。多应用于pc端。
  • MPA:就是指一个应用中有多个页面,页面跳转时是整页刷新

单页面的优点:用户体验好,快,内容的改变不需要重新加载整个页面,基于这一点spa对服务器压力较小;前后端分离;页面效果会比较炫酷(比如切换页面内容时的专场动画)。

单页面缺点:不利于seo;导航不可用,如果一定要导航需要自行实现前进、后退。(由于是单页面不能用浏览器的前进后退功能,所以需要自己建立堆栈管理);初次加载时耗时多;页面复杂度提高很多。

.prevent:等同于JavaScript中的event.preventDefault(),防止执行预设的行为(如果事件可取消,则取消该事件,而不停止事件的进一步传播);
.capture:与事件冒泡的方向相反,事件捕获由外到内;
.self:只会触发自己范围内的事件,不包含子元素;
.once:只会触发一次。

数据驱动:ViewModel,保证数据和视图的一致性。
组件系统:应用类UI可以看作全部是由组件树构成的。

  • beforeCreate:在new一个vue实例后,只有一些默认的生命周期钩子和默认事件,其他的东西都还没创建。在beforeCreate生命周期执行的时候,data和methods中的数据都还没有初始化。不能在这个阶段使用data中的数据和methods中的方法
  • create:data 和 methods都已经被初始化好了,如果要调用 methods 中的方法,或者操作 data 中的数据,最早可以在这个阶段中操作
  • beforeMount:执行到这个钩子的时候,在内存中已经编译好了模板了,但是还没有挂载到页面中,此时,页面还是旧的
  • mounted:执行到这个钩子的时候,就表示Vue实例已经初始化完成了。此时组件脱离了创建阶段,进入到了运行阶段。 如果我们想要通过插件操作页面上的DOM节点,最早可以在和这个阶段中进行
  • beforeUpdate: 当执行这个钩子时,页面中的显示的数据还是旧的,data中的数据是更新后的, 页面还没有和最新的数据保持同步
  • updated:页面显示的数据和data中的数据已经保持同步了,都是最新的
  • beforeDestory:Vue实例从运行阶段进入到了销毁阶段,这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于可用状态。还没有真正被销毁
  • destroyed: 这个时候上所有的 data 和 methods , 指令, 过滤器 ……都是处于不可用状态。组件已经被销毁了。
  • created:在模板渲染成html前调用,即通常初始化某些属性值,然后再渲染成视图。
  • mounted:在模板渲染成html后调用,通常是初始化页面完成后,再对html的dom节点进行一些需要的操作。
  • 全局前置守卫:在路由跳转前触发,可在执行 next 方法前做一些身份登录验证的逻辑。
// 必须执行 next 方法来触发路由跳转
  • 全局解析守卫:与 beforeEach 类似,也是路由跳转前触发,区别是还需在所有组件内守卫和异步路由组件被解析之后,也就是在组件内 beforeRouteEnter 之后被调用。
// 必须执行 next 方法来触发路由跳转
  • 全局后置钩子:和守卫不同的是,这些钩子不会接受 next 函数也不会改变导航本身。
  • 路由独享守卫:可在路由配置上直接定义 beforeEnter
  • 组件内的守卫:组件内可直接定义如下路由导航守卫
// 当守卫执行前,组件实例还没被创建 // 当前路由改变,但是组件被复用时调用 // 导航离开组件时被调用
  • URL 虽然不显示我们的传参,但是是可以在子组件获取参数的。当然也有问题:会存在刷新丢失参数。若想不丢失,需和方案一路由配置一样。原因是第二种方式传参是上一个页面 push 函数中携带的,刷新没有 push 的动作。
  1. hash:监听的hashchange事件,即地址栏 URL 中的 # 符号;hash 虽然出现在 URL 中,但不会被包括在 HTTP 请求中,对后端完全没有影响,因此改变 hash 不会重新加载页面。兼容性好,支持低版本浏览器和 IE 浏览器。

  2. history:history模式监听pushstate和popstate,(需要特定浏览器支持)这两个方法应用于浏览器的历史记录栈,在当前已有的 back、forward、go 的基础之上,它们提供了对历史记录进行修改的功能。只是当它们执行修改时,虽然改变了当前的 URL,但浏览器不会立即向后端发送请求。

  3. abstract:支持所有 JS 运行模式,Vue-Router 自身会对环境做校验,如果发现没有浏览器 API,路由会自动强制进入 abstract 模式。在移动端原生环境也是使用 abstract 模式。

  • 一般场景下,hash 和 history 都可以,除非你更在意颜值,# 符号夹杂在 URL 里看起来确实有些不太美丽。
  • pushState() 设置的新 URL 可以与当前 URL 一模一样,这样也会把记录添加到栈中;而 hash 设置的新值必须与原来不一样才会触发动作将记录添加到栈中;
  • 跳转后刷新或者回跳,会报一个404的错误,找不到指定的路由,最后后端去指向正确的路由 加了/hd/xxx 去匹配是否有这个/hd/{:path} 才得以解决
  1. 环境能力检测,选择可选中效率最高的(宏任务/微任务)进行包装执行,保证是在同步代码都执行完成后再去执行修改 DOM 等操作。
  • 基于依赖收集的响应式原理
  • 首先需要diff的原因是操作dom的代价是昂贵的,我们要减少操作dom所以需要对比出新老虚拟dom的最小差异点,尽可能复用原有dom

  • 因为我们很少跨层级的去移动dom,所以diff算法只会对比同一父节点下的子节点,使算法的时间复杂度是O(n)

  • 深度优先,比较新vnode找到对应的老vnode,这时会先执行patchChildren进入子节点的比较,所以是深度优先

  • 首尾两端对比法,依次把旧vnode数组的首尾分别和新vnode数组的首尾进行对比,能匹配上就进入他们子节点的对比,都匹配不上就通过key索引找新vnode数组第一个节点对应的在旧vnode数组里的index,还是找不到的话就新建一个vnode。当旧vnode数组里还有节点,而新vnode数组已经遍历完了时就remove掉对应的多出来的真实dom

slot 插槽,可以理解为slot在组件模板中提前占据了位置。当复用组件时,使用相关的slot标签时,标签里的内容就会自动替换组件模板中对应slot标签的位置,作为承载分发内容的出口。
主要作用是复用和扩展组件,做一些定制化组件的处理。

  • 具名插槽:slot 标签没有name属性,则为默认插槽。具备name属性,则为具名插槽
  • 作用域插槽:子组件在作用域上绑定的属性来将组件的信息传给父组件使用,这些属性会被挂在父组件接受的对象上

指令定义函数提供如下钩子函数

  1. bind:指令第一次绑定到元素时调用(只调用一次)
  2. inserted: 被绑定元素插入父节点时使用(父节点存在即可调用)
  3. update:被绑定元素所在模板更新时调用,不论绑定值是否变化。通过比较更新前后的绑定值。
  4. componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
  5. unbind: 只调用一次,指令与元素解绑时调用。

项目中有涉及 一键copy、权限控制 都可以用指令的方式控制,目的就是简化我们的工作量。

Vue 过滤器可用在两个地方:双花括号插值和 v-bind 表达式。
Vue3 中已经废弃这个特点。

// 可基于源值做一些处理
 // 可基于源值做一些处理

过滤器可串联,执行顺序从左到右,第二个过滤器输入值是第一个过滤器的输出值。

  • Proxy 可以直接监听对象而非属性;
  • Proxy 可以直接监听数组的变化;
  • Proxy 返回的是一个新对象,我们可以只操作新的对象达到目的,而 Object.defineProperty 只能遍历对象属性直接修改;
  • Proxy 作为新标准将受到浏览器厂商重点持续的性能优化,也就是传说中的新标准的性能红利;
  • 兼容性好,支持 IE9,而 Proxy 的存在浏览器兼容性问题,而且无法用 polyfill 磨平,因此 Vue
    的作者才声明需要等到下个大版本( 3.0 )才能用 Proxy 重写。

先转化成AST树,再得到的render函数返回VNode(Vue的虚拟DOM节点)

  • Vue 项目的编译优化

3.基础web技术优化

    • 只能监测属性,不能监测对象
    • 检测属性的添加和删除;
    • 检测数组索引和长度的变更;
  • 用于创建 observable 的公开 API。这为中小规模场景提供了简单轻量级的跨组件状态管理解决方案。
    • 默认采用惰性观察。在 2.x 中,不管反应式数据有多大,都会在启动时被观察到。如果你的数据集很大,这可能会在应用启动时带来明显的开销。在 3.x 中,只观察用于渲染应用程序最初可见部分的数据。
    • 更精确的变更通知。在 2.x 中,通过 Vue.set 强制添加新属性将导致依赖于该对象的 watcher 收到变更通知。在 3.x 中,只有依赖于特定属性的 watcher 才会收到通知。
    • 不可变的 observable:我们可以创建值的“不可变”版本(即使是嵌套属性),除非系统在内部暂时将其“解禁”。这个机制可用于冻结 prop 传递或 Vuex 状态树以外的变化。
    • 更好的调试功能:我们可以使用新的 renderTracked 和 renderTriggered 钩子精确地跟踪组件在什么时候以及为什么重新渲染
    模板方面没有大的变更,只改了作用域插槽,2.x 的机制导致作用域插槽变了,父组件会重新渲染,而 3.0 把作用域插槽改成了函数的方式,这样只会影响子组件的重新渲染,提升了渲染的性能。同时,对于 render 函数的方面,vue3.0 也会进行一系列更改来方便习惯直接使用 api 来生成 vdom 。 vue2.x 中的组件是通过声明的方式传入一系列 option,和 TypeScript 的结合需要通过一些装饰器的方式来做,虽然能实现功能,但是比较麻烦。3.0 修改了组件的声明方式,改成了类式的写法,这样使得和 TypeScript 的结合变得很容易。此外,vue 的源码也改用了 TypeScript 来写。其实当代码的功能复杂之后,必须有一个静态类型系统来做一些辅助管理。现在 vue3.0 也全面改用 TypeScript 来重写了,更是使得对外暴露的 api 更容易结合 TypeScript。静态类型系统对于复杂代码的维护确实很有必要。

vue3.0 的改变是全面的,上面只涉及到主要的 3 个方面,还有一些其他的更改:

  • 支持自定义渲染器,从而使得 weex 可以通过自定义渲染器的方式来扩展,而不是直接 fork 源码来改的方式。
  • 支持 Fragment(多个根节点)和 Protal(在 dom 其他部分渲染组建内容)组件,针对一些特殊的场景做了处理。
  • 基于 treeshaking 优化,提供了更多的内置功能。

我要回帖

更多关于 优启通软件加载不出来 的文章

 

随机推荐