八股文(四)

目录

一、 Vue2的双向数据绑定原理

二、 vue2数据绑定缺点是什么?vue3是怎么解决的?

(1)因为vue2.0 object.defineProperty只能劫持对象属性

(2)Proxy是直接代理对象

(3)proxy不仅可以代理对象,还可以代理数组,也可以代理动态添加的属性

三、 vue的keep-alive组件

四、 vue父子组件通信,兄弟组件通信

(1)父子组件通信有3种方式

(2)兄弟组件通信常用方式

五、 webpack原理

扫描二维码关注公众号,回复: 16326661 查看本文章

六、 常见的webpack plugin和loader

七、 回流和重绘

(1)重排(回流)

(2)重绘

(3) 重绘不一定导致重排,重排一定导致重绘

八、 盒模型

(1)介绍下css的盒模型

(2)标准盒模型和怪异盒模型是什么

(3)ie 盒模型和 w3c 盒模型的区别(都不包括margin)

九、 有哪些CSS选择器

十、 css居中

(1)水平居中

(2)垂直居中

十一、 block、inline和inline-block的元素有什么差别

(1)block

(2)inline

(3)display的属性值

一、 Vue2的双向数据绑定原理

(1)利用订阅-开发者模式,vue初始化时会用Object.defineProperty()给data中的每一个属性添加getter和setter,同时创建dep和watcher进行依赖收集与派发更新,最后通过diff算法对比新老vnode的差异,通过patch即时更新

(2)使用Object.defineProperty对象以及对象属性的劫持+发布订阅模式。

语法:

Object.defineproperty( object,‘ propName ’ ,descriptor);

object:要监听的目标对象

propName :要定义或修改的属性的名称。

descriptor:要定义或修改的属性描述符,操作详情。

// 基本使用
const obj={
   name: 'zhangsan',
}
Object.defineProperty(obj, 'name', {
    get() {
        console.log('触发get')
        return value
    },
    set(newValue) {
        if (newValue !== value) {
            console.log('触发set')
            value = newValue
            //updateView()
        }
    }
})
obj.name  // 触发get
obj.name='小小'  // 触发set

二、 vue2数据绑定缺点是什么?vue3是怎么解决的?

在Vue2.0中,使用Object.defineProperty()方法来进行数据代理,但是这种方法无法代理数组类型的数据属性,Vue2.0中通过改写数组方法的方式来监听数组的改变。在Vue3.0时候改用ES6的新特性Proxy来进行数据代理,就可以方便地监听数组变化了。

问题1:Object.defineproperty能监听到对象的新增删除属性吗?
​
不能,需要开发者主动调用相应的方法去更新 :Vue.set(),Vue.delete,由于 Object.defineProperty 劫持的是对象的属性,所以新增属性时,需要重新遍历对象,对其新增属性再使用 Object.defineProperty 进行劫持。
​
问题2:Object.defineproperty能监听到数组的添加删除操作吗?
​
不能,依然可以Vue.set(),Vue.delete更新数据,看到这里,可能有些同学就会有疑问,那为啥我在项目中给数据使用push给数组添加一个数据,不需要调用set,页面能够更新响应呢,那是因为vue2.0使用数组重写的方法实现了数组的响应,7个方法分别为 'push', 'pop', 'shift', 'unshift', 'splice', 'sort', 'reverse'。
​
问题3:如果我只是改变数组的索引的值,例如:vm.items[indexOfItem] = newValue真的不能被监听么?
​
答案是:能,Object.defineProperty能监听到,那为啥vue不给添加监听呢,因为性能对于对象而言,每一次的数据变更都会对对象的属性进行一次枚举,一般对象本身的属性数量有限,所以对于遍历枚举等方式产生的性能损耗可以忽略不计,但是对于数组而言呢?数组包含的元素量是可能达到成千上万,假设对于每一次数组元素的更新都触发了枚举/遍历,其带来的性能损耗将与获得的用户体验不成正比,故vue无法检测数组的变动。
​
再者注意:Object.defineProperty()是深度监听,需要递归到底。一次性计算量很大。

(1)因为vue2.0 object.defineProperty只能劫持对象属性

 最大的缺点就是不能实时的检测数组发发生的变化 ,无法监控数组下标的变化,导致通过数据下标添加的元素不能实时响应的弊端。为了解决这个问题,经vue内部处理后,可以使用push()、pop() 、shift()、unshift()、splice()、sort()、reverse()进行hack处理,所以其他数组属性也是监测不到,具有一定的局限性。

(2)Proxy是直接代理对象

因为object.defineProperty只能劫持对象属性,从而需要对每个对象的每个属性进行遍历。vue2.0里是通过递归+遍历data对象来实现对数据的监控的,如果属性值是对象的话,还需要深度遍历。 与Object.defineProperty不同 的是Object.defineProperty只能劫持对象的属性,而Proxy是直接代理对象。因为proxy是对整个对象进行代理,所以可以监听对象某个属性值的变化,还可以监听对象属性的新增和删除,而且还可以监听数组

(3)proxy不仅可以代理对象,还可以代理数组,也可以代理动态添加的属性

而Vue3.0中的proxy不仅可以代理对象,还可以代理数组,也可以代理动态添加的属性,有13种劫持操作: get 获取某个key值 (接收2个参数,目标值和目标值key值) set 设置某个key值 (目标值、目标的key值、要改变的值、改变前的原始值) apply 使用in 操作符判断某个key是否存在 deleteProperty 删除一个property defineProperty 定义一个新的property …

三、 vue的keep-alive组件

keep-alive是一个内置组件,它所包裹的组件会在不同的渲染中缓存状态。用在需要让自定义组件在不同的渲染中保持状态不变的场景。例如一些表单组件,如果已经填写好一些内容,然后切到其他组件,再切换回表单时候,应该保持已经填写好的内容,这时候可以选择使用keep-alive

四、 vue父子组件通信,兄弟组件通信

(1)父子组件通信有3种方式

a:父组件通过ref调用/获取子组件内参数/方法

b:子组件通过emit调用父组件方法

c:子组件通过prop获取父组件变量

(2)兄弟组件通信常用方式

eventBus就是一个vue实例,使用它提供的$on和$emit就能够很容易地实现发布订阅模式,从而实现兄弟组件间的通信。

具体内容可以看这篇文章:vue父子组件通信,兄弟组件通信_七小山的博客-CSDN博客

五、 webpack原理

webpack读取配置,根据入口开始遍历文件,解析依赖,使用loader处理各模块,然后将文件打包成bundle后输出到output指定的目录中。

webpack的工作流程是:

  • Webpack CLI 启动打包流程,解析配置项参数。

  • 载入 Webpack 核心模块,创建 Compiler 对象。

  • 注册plugins。

  • 使用 Compiler 对象开始编译整个项目。

  • 从入口文件开始,解析模块为AST,分析模块依赖,形成依赖关系树。

  • 递归依赖树,将每个模块交给对应的 Loader 处理。

  • 合并 Loader 处理完的结果,将打包结果输出到 dist 目录

六、 常见的webpack plugin和loader

loader( 用于转换某些类型 )

1、babel-loader // 处理js

2、file-loader、url-loader // 处理图片、字体图标

3、less-loader、sass-loader、stylus-loader // 处理各种css预处理器

4、css-loader // 解析css模块

5、style-loader // 将样式插入到dom中

plugin( 插件则可以用于执行范围更广的任务 )

1、html-webpack-plugin // 生成html文件并自动将js bundle引入到html

2、clean-webpack-plugin // 每次打包时候清空上次打包结果

3、copy-webpack-plugin // 执行拷贝操作

4、mini-css-extract-plugin // 提取css文件

七、 回流和重绘

(1)重排(回流)

如果JavaScript做了修改DOM元素的几何属性(位置、尺寸)等操作,将会重新计算style,并且需要更新布局树,然后执行后面的渲染操作,即从1~9的步骤需要重新执行一遍。这个过程叫“重排”。 页面中元素发生位置和尺寸的变化,导致部分页面回整个页面重新加载的现象称为回流(重排)

(2)重绘

如果JavaScript修改了DOM的非几何属性,如修改了元素的背景颜色,不需要更新布局树和重新构建分层树,只需要重新绘制。

在页面运行中,应该尽量避免重排和重绘,以提升渲染性能。

(3) 重绘不一定导致重排,重排一定导致重绘

八、 盒模型

(1)介绍下css的盒模型

CSS把每个元素视为一个盒子,每个盒子包括分为内容(content)、填充(padding)、边界(margin)、边框(border)四个部分。这种对界面元素的抽象,称为盒模型。盒模型是CSS布局的基本单元

(2)标准盒模型和怪异盒模型是什么

有两种盒模型:IE盒模型(也称怪异盒模型)(border-box)、W3C标准盒模型(content-box)

(3)ie 盒模型和 w3c 盒模型的区别(都不包括margin)

W3C标准盒模型:属性width,height只包含内容content,不包含border和padding。

IE盒模型:属性width,height包含content、border和padding,指的是content +padding+border

九、 有哪些CSS选择器

id选择器 (#myid)

类选择器 (.my-classname)

标签选择器 (div,h1,p)

兄弟选择器 (li~a)

伪元素选择器 (::before、 ::after)

伪类选择器 (a:hover,li:nth-child)

十、 css居中

(1)水平居中

  • 行内元素的居中:父元素text-align: center;

  • 块级元素居中:指定宽度后,设置margin: auto

width: 100px; margin: 0 auto;

(2)垂直居中

  • 行内元素居中:设置line-heightheight相等。

  • 块级元素居中

    • flex

    • 未知高度:用margin-top: 50%; + translate: -50%实现

    • 已知高度

用CSS3的新属性calc,计算top,top: calc(50% - 50px);

用top + margin-top实现

position: relative;
height: 100px;
margin-top: 50%;
top: -50px;

十一、 block、inline和inline-block的元素有什么差别

(1)block

块元素:独占一行;元素的宽高、以及内外边距都可设置;元素宽度在不设置的情况下,是它本身父容器的100%。

(2)inline

行元素(行内元素):在水平方向上修改水平尺寸(padding,margin,border),能产生相应的效果,垂直方向上对行元素的高度是毫无影响的。

因此,行内元素直接定义width和height是没有意义的,行元素的宽高是靠内容撑起来的。

但是,可以通过设置line-height,来规定行元素的高度。可以通过对行元素设置display属性,转化为块元素,display:block

(3)display的属性值

  • block 块类型。默认宽度为父元素宽度,可设置宽高,换行显示。

  • none 元素不显示,并从文档流中移除。

  • inline 行内元素类型。默认宽度为内容宽度,不可设置宽高,同行显示。

  • inline-block默认宽度为内容宽度,可以设置宽高,同行显示。

猜你喜欢

转载自blog.csdn.net/qq_55928824/article/details/129359356
今日推荐