八股文(四)

目录

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

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

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

(2)Proxy是直接代理对象

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

三、 vue的keep-alive组件

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

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

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

五、 webpack原理

六、 常见的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