VUE 常见面试题

文章目录

v-show和v-if的区别

v-show操作的是元素的display属性
v-if操作的是元素的创建和插入
v-if有更高的切换开销,而v-show有更高的初始渲染开销,如果需要频繁的切换则使用v-show比较好,如果在运行时很少条件改变,则使用v-if较好

methods、computed、watch三者的区别

三者之间的共同点:
都是以函数为基础的
computedwatch都是以vue的依赖为基础,当所依赖的数据发生变化的时候会触发相关的函数去实现数据的变动
methods里面是用来定义函数的,需要手动才能执行
三者之间的不同点:
computed:
computed是计算属性,computed所依赖的属性发生变化时,计算属性才会重新计算,并进行缓存,当其他数据发生变化的时候computed不会重新计算,从而提升性能
watch
watch类似事件监听,watch的方法默认不会执行,当依赖的属性发生变化才会执行,默认第一次不会执行,声明immediate为true可以立即执行一次handler,watch只能监听属性引用的变化,内部属性是监听不到的,设置deep为true可以深度简体,但性能开销会变大
wacth和computed的应用场景:
wacth:一个数据影响多个数据,例如网络请求,模糊查询,浏览器自适应,监控路由对象
computd:一个数据受多个数据影响,例如购物车的结算, 过滤某些商品数据

如何给一个响应式对象中添加一个属性

通过vue.set方法,vue.set(obj,'name','张三')

vue中组件通讯的方式有哪些

父传子:
1.通过绑定自定义属性,接受通过props进行接受
2.provideinject,父组件通过provide来提供变量,在子组件中通过inject来注入变量
子传父:
1,通过绑定自定义事件
2.通过插槽作用域
非父子组件传值:
1.创建公共的vue实例对象
2.使用eventBus
3.手动封装事件订阅
4.通过vuex

vue的生命周期

1.beforeCreate():组件实例刚刚被创建(el和data并未初始化),可以在这加个loading事件
2.created():组件创建完成,属性已绑定,但dom还未生成,$el属性还不存在(完成data的初始化),可以在这结束loading事件,也可以异步请求
3.beforeMount():模板编译/挂载之前(完成了$el和data初始化)
4.mounted():模板编译/挂载之后,获取dom节点
5.beforeUpdate():组件更新之前
6.updated():组件更新之后,对数据同意处理
7.beforeDestory():组件销毁之前,可以在做一个确认停止事件的确认框
8.destroyed():组件销毁之后

解释一下vue中单向数据流的理解

数据从父组件传给子组件只能单向绑定,子组件不能直接修改从父组件 传递过来的数据,只能从一个方向来修改状态,如果父组件给多个子组件传递数据,那么某一个子组件修改了这个数据,就会导致其他组件的数据也会发生变化,这样会防止从子组件意外改变父组件的状态,从而导致应用的数据流向难以理解,因此只能从一个方向来修改状态

Vue中使用key的使用及作用

key的作用主要是为了高效的更新虚拟DOM,其原理是vue在patch过程中通过key可以精准判断两 个节点是否是同一个,从而避免频繁更新不同元素,使得整个patch过程更加高效,减少DOM操作量,提高性能。
v-if中用key管理可复用的元素
vue中在使用相同标签名元素的过渡切换时,也会使用到key属性,其目的也是为了让vue可以区分它们,否则vue只会替换其内部属性而不会触发过渡效果。
v-for中的key
当 Vue.js 用 v-for 正在更新已渲染过的元素列表时,它默认用 “就地复用” 策略。如果数据项的顺序被改变,Vue将不是移动 DOM 元素来匹配数据项的顺序, 而是简单复用此处每个元素,并且确保它在特定索引下显示已被渲染过的每个元素

什么是动态组件,如何使用,以及keep-alive的作用

动态组件:
让多个组件使用同一个挂载点,并动态进行切换,这就是动态组件。通过保留<component></component>元素,动态绑定他的is特性,可以实现动态组件
keep-alive
包裹动态组件时会缓存不活动的组件实例,而不是销毁他们,组件切换调用的时候本身是会被销毁的,只要加上keep-alive进行包裹就不会被销毁,而是被缓存起来,下一次使用的时候自己从缓存中调用,keep-alive是一个抽象组件,他自身不会渲染一个dom元素
常用属性:
include:只有名称匹配的组件才会被缓存
exclude:任何名称匹配的都不会被缓存
max:最多可以缓存多少组件实例

使用keep-alive会增加哪两个生命周期

activated:当组件为活跃状态的时候触发(活跃状态:进入页面的时候)
deactivated:缓存状态的时候触发

vue中solt的使用方式,以及solt作用域插槽的用法

当组件当做标签使用的时候,如果需要在组件标签内部进行嵌套内容,需要通过template组件包裹嵌套的内容,在组件内部通过进行接收

为什么在组件内部data是一个函数而不是一个对象

因为每次调用组件的时候会生成一个新的对象,如果是一个对象的情况下,data数据会进行复用,二当data是一个函数的时候,每次调用就会返回一个新的对象

vue中动画如何实现

哪个元素需要就给哪个元素加transition标签,金如意是class的类型分为以下几种

<name>-enter
<name>-enter-active
<name>-enter-to

离开的时候class的类型分为以下几种

<name>-leave
<name>-leave-active
<name>-leave-to

如果需要一组元素发生动画需要用标签

浅谈对路由的理解

路由就是根据不同的url展示不同的页面或者数据
路由分为前端路由和后端路由
前端路由:
不向后台发送请求,前端利用hash或者htm5的historyApi来实现的,一般用于不同的内容展示和切换,前后端分离
优点:
用户体验好;根据不同路由展示不同页面,不需要向后端发送请求;内容切换速度快;可以在浏览器中输入指定想要访问的url路由地址;前后端分离,方便开发
缺点:
使用浏览器的前进后退按钮,会重新发送请求,没有合理的使用缓存;单页面无法记住之前滚动的位置
后端路由:
在浏览器输入不同的url地址时,每次都向后端发送请求,服务器根据不同的响应返回不同的数据,浏览器接收的数据在进行渲染,所以后端路由会刷新页面,如果网速慢的话会出现空白页面
优点:
分担了前端的压力,html和数据的拼接都由后端完成
缺点:
项目庞大时,加剧了服务器的压力;网速过慢会延迟加载页面

路由跳转方式有哪几种

1.a标签跳转。例如:<a href="#/home">首页</a>
2.router-link跳转。例如<router-link to="/home">首页<router-link>
3.编程式路由。例如this.$router.push('/home')

路由传值的方式有哪几种

1.动态路由传值。例如path:"/home/:id/name";通过this.$route.params进行接收
2.query传值。因为在url中?后面的参数不会被解析,因此可以使用query传值;通过this.$route.query进行接收
3.路由解耦。在配置路由的时候添加props属性为true,在需要接收参数的组件页面通过props进行接收

路由配置项常用属性及作用

配置参数:
path:跳转路径
component:路径相对于的组件
name:路由名称
meta:路由元信息
children:子路由
props:路由解耦
redirect:重定向

如何检测路由参数的变化

1.通过属性监听watch:{ '$route'(){} }
2.使用beforeRouterUpdate(to,from,next)

什么是路由守卫

路由跳转前后的一些验证

路由的钩子函数有哪些

beforeRouterEnter:当路由进入前,登录验证,热力图记录
beforeRouterUpdate:当路由更新时,如果当前路由发生了变化,但是不需要组件创建销毁的时候,就需要用到这个钩子函数
beforeRouteRLeave:当路由离开时,当用户没有进行支付离开的时候或当用户填写完信息没有保存的时候
beforeEach:全局守卫。验证用户是否登录

axios与ajax的区别

axios优点:
1.从nodejs中创建http请求
2.支持promiseApi
3.提供了一些并发请求的接口
4.自动转换json数据
5.客户端防止CSRF/XSRF
ajax缺点:
1.jquery项目庞大,如果单纯使用ajax却要引入整个jquery不合理
2.基于原生的XHR开发,但XHR架构并不清晰

简述vuex的数据传递流程

当组件数据需要修改的时候需要调用dispatch来触发actions里面的方法,actions里每个方法中又会有一个commit方法,执行方法的时候会通过commit方法来触发mutations里面的方法进行数据的修改,mutations里面的每个函数都会有一个state参数,这样就可以在mutations里面进行state的数据修改

双向数据绑定的原理

vuejs是采用数据劫持结合发布者和订阅者模式的方式,通过object.definProperty()来劫持各个属性的gettersetter,在数据变化时发布消息给订阅者,触发相应的监听回调
第一步:需要observe的数据对象进行递归遍历,包括子属性对象的属性,都加上gettersetter,这样给这个对象的某个值赋值就会触发setter,那么就监听到了数据变化
第二步:compile解析模板指令,将模板中的变量替换成数据,然后初始化渲染页面视图,并将每个指令对应的节点绑定更新函数,添加监听数据的订阅者,一旦数据有变动,收到通知,更新视图
第三步:watcher订阅者是observecompile之间的通信桥梁,主要做的事情是:
1.在自身实例化时往属性订阅器(dep)里面添加自己
2.自身必须有一个update()方法
3.待属性变动dep.notice()通知时,能调用自身的update()方法,并处罚compile中绑定的回调

使用vue的时候会一下子加载所有的东西使得初始化页面很卡,如何解决

1.路由懒加载
2.服务端渲染
3.骨架屏注入
像vue这种单页面应用,如果没有页面懒加载,运用webpack打包后的文件会异常大,造成进入首页时需要加载的内容过多,会出现长时间的白屏,即使做了loading也不利于用户体验,而运用懒加载可以将页面进行划分,需要的时候加载页面,可以有效的分担首页所承担的加载压力,减少首页加载用时

vue中常见跨域方式

1.Nginx
2.服务器代理(http-proxy-middleware)
3.cors

第一次加载页面会触发哪几个钩子

beforeCreate,created,beforeMount,mounted

vuex中常用属性有哪些

state:
vuex就是一个仓库,仓库里面存放了很多对象,其中state就是数据源存放地,对应于一般vue对象里的data;state存放的数据是响应式的,vue组件从store中读取数据,若store中数据发生变化,依赖这个数据的组件也会发生变化;它通过mapState、mapSetter吧全局的state和getters映射到组件的computed计算属性中
getter:
可以对state进行计算操作,它就是store的计算属性;虽然在居间内也可以做计算属性,但是getters可以在多组件之间复用;如果一个状态只在一个组件内使用,可以不用getters
mutation:
action类似于mutation,不同在于action提交的是mutation,而不是直接变更状态,action可以包含任意异步操作
action:
module:

父组件如何访问子组件内部的方法

1.通过this.$refs方法

//父组件中

<template>
    <div>
        <Button @click="handleClick">点击调用子组件方法</Button>
        <Child ref="child"/>
    </div>
</template>    

<script>
import Child from './child';

export default {
    methods: {
        handleClick() {
              this.$refs.child.sing();
        },
    },
}
</script>


//子组件中

<template>
  <div>我是子组件</div>
</template>
<script>
export default {
  methods: {
    sing() {
      console.log('我是子组件的方法');
    },
  },
};
</script>

2.通过$emit$on

//父组件中

<template>
    <div>
        <Button @click="handleClick">点击调用子组件方法</Button>
        <Child ref="child"/>
    </div>
</template>    

<script>
import Child from './child';

export default {
    methods: {
        handleClick() {
              this.$refs.child.sing();
        },
    },
}
</script>


//子组件中

<template>
  <div>我是子组件</div>
</template>
<script>
export default {
  methods: {
    sing() {
      console.log('我是子组件的方法');
    },
  },
};
</script>

子组件访问父组件的方法

1.通过this.$parent方法

//父组件

<template>
  <div>
    <child></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>
//子组件

<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$parent.fatherMethod();
      }
    }
  };

2.在子组件中用$emit像父组件触发一个事件,父组件监听这个事件

//父组件
 
<template>
  <div>
    <child @fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>
//子组件

<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    methods: {
      childMethod() {
        this.$emit('fatherMethod');
      }
    }
  };

3.父组件把方法传给子组件,在子组件中直接调用

//父组件

<template>
  <div>
    <child :fatherMethod="fatherMethod"></child>
  </div>
</template>
<script>
  import child from '~/components/dam/child';
  export default {
    components: {
      child
    },
    methods: {
      fatherMethod() {
        console.log('测试');
      }
    }
  };
</script>
//子组件
 

<template>
  <div>
    <button @click="childMethod()">点击</button>
  </div>
</template>
<script>
  export default {
    props: {
      fatherMethod: {
        type: Function,
        default: null
      }
    },
    methods: {
      childMethod() {
        if (this.fatherMethod) {
          this.fatherMethod();
        }
      }
    }
  };
</script>
 

对vue.extend的理解

使用Vue构造器,创建一个子类,参数是组件对象,注意data是一个函数,vue.extens()返回的是一个扩展实例构造器,简单的来说就是一个预设了部分选项的vue实例。只要用来服务Vue.component用来生成组件

对Vue.use的理解

安装Vue.js插件。如果插件是一个对象,必须提供install方法。如果插件是一个函数,它会被作为install方法。install方法调用时,会将vue作为参数传入。该方法需要在调用new Vue() 之前被调用

如何解决路由与跨域之间的冲突

统一规范为一个入口,在一定程度上会解决冲突或者在axios中配置baseUrl

vue响应式原理

工作原理是当我们把一个普通的JavaScript对象传给vue实例的data选项的时候,vue会遍历对象的所有属性 ,并使用object。definePropert把这些属性全部转化为getter/setter。(object.definepropert仅es5支持,且没有垫片脚本的特性,因此vue不支持IE8及更低版本),用户看不到getter/setter,但是在内部他们让Vue追踪 依赖,在属性被访问和修改时通知变化。每个组件实例都有相应的watcher实例对象,他会在组件渲染的过程中把属性记录为依赖,之后当依赖项的setter呗调用时,会通知watcher重新计算,从而使它关联的组件得以更新

vue-router实现的原理

原理核心就是更新视图但不重新请求页面。
实现路由跳转有两种方式:
改变hash值。(hash为浏览器url中#后面的内容,包含#)。改变#后面的部分,浏览器只会加载相应位置的内容,不会重新加载页面。
利用history对象新特性。在配置路由规则时加入“mode:history”,利用history.pushState API完成跳转。

对Vue.js的template编译的理解

先转化成AST树,在得到render函数返回VNode。首先,通过compile编译器吧template变异成AST语法树(abstract syntax tree即源代码的抽象语法结构的树状表现形式),compile是createCompiler的返回值,createCompiler是用以创建编译器的,另外compile还负责合并option。然后,AST会经过generate得到render函数,render的返回值是VNode,VNode是Vue的虚拟Dom节点,里面有标签名、子节点、文本等

谈谈你对Webpack的理解

Webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。
它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。
对于不同类型的依赖,Webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。

Webpack的基本功能有哪些?

代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等
代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。

Webpack构建过程?

从entry里配置的module开始递归解析entry依赖的所有module
每找到一个module,就会根据配置的loader去找对应的转换规则
对module进行转换后,再解析出当前module依赖的module
这些模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk
最后Webpack会把所有Chunk转换成文件输出在整个流程中Webpack会在恰当的时机执行plugin里定义的逻辑

Loader的作用?有哪些常见的Loader?

Loader 是webpack中提供了一种处理多种文件格式的机制,因为webpack只认识JS和JSON,所以Loader相当于翻译官,将其他类型资源进行预处理。
用于对模块的"源代码"进行转换。
loader支持链式调用,原型调用的顺序是从右往左。原型链中的每个loader会处理之前已处理过的资源,最终变为js代码。
可以通过 loader 的预处理函数,为 JavaScript 生态系统提供更多能力。
file-loader:把文件输出到一个文件夹中,在代码中通过相对 URL 去引用输出的文件 (处理图片和字体)
url-loader:与 file-loader 类似,区别是用户可以设置一个阈值,大于阈值会交给 file-loader 处理,小于阈值时返回文件 base64 形式编码 (处理图片和字体)
css-loader:加载 CSS,支持模块化、压缩、文件导入等特性
style-loader:把 CSS 代码注入到 JavaScript 中,通过 DOM 操作去加载 CSS
json-loader: 加载 JSON 文件(默认包含)
ts-loader: babel-loader:把 ES6 转换成 ES5
ts-loader: 将 TypeScript 转换成 JavaScript
less-loader:将less代码转换成CSS
eslint-loader:通过 ESLint 检查 JavaScript 代码
vue-loader:加载 Vue单文件组件

Plugin的作用?有哪些常见的Plugin?

Plugin功能更强大,主要目的就是解决loader 无法实现的事情,比如打包优化和代码压缩等。
Plugin加载后,在webpack构建的某个时间节点就会触发plugin定义的功能,帮助webpack做一些事情。实现对webpack的功能扩展。
html-webpack-plugin:自动创建一个html文件,并把打包好的js插入到html中
uglifyjs-webpack-plugin:不支持 ES6 压缩 ( Webpack4 以前)
mini-css-extract-plugin: 在每一次打包之前,删除整个输出文件夹下的内容;
clean-webpack-plugin: 抽离css代码放到一个单独的文件中;
copy-webpack-plugin: 拷贝文件
webpack-bundle-analyzer: 可视化 Webpack 输出文件的体积 (业务组件、依赖第三方模块)
optimize-css-assets-plugin:压缩css;

那你再说一说Loader和Plugin的区别?

Loader 本质就是一个函数,在该函数中对接收到的内容进行转换,返回转换后的结果。 因为 Webpack 只认识 JavaScript,所以 Loader 就成了翻译官,对其他类型的资源进行转译的预处理工作。
Plugin 就是插件,基于事件流框架 Tapable,插件可以扩展 Webpack 的功能,在 Webpack 运行的生命周期中会广播出许多事件,Plugin 可以监听这些事件,在合适的时机通过 Webpack 提供的 API 改变输出结果。
Loader 在 module.rules 中配置,作为模块的解析规则,类型为数组。每一项都是一个 Object,内部包含了 test(类型文件)、loader、options (参数)等属性。
Plugin 在 plugins 中单独配置,类型为数组,每一项是一个 Plugin 的实例,参数都通过构造函数传入。

如何优化 Webpack 的构建速度?

(1)使用高版本的 Webpack 和 Node.js
(2)压缩代码
通过 uglifyjs-webpack-plugin 压缩JS代码
通过 mini-css-extract-plugin 提取 chunk 中的 CSS 代码到单独文件,通过 css-loader 的 minimize 选项开启 cssnano 压缩 CSS。
(3)多线程/多进程构建:thread-loader, HappyPack
(4)压缩图片: image-webpack-loader
(5)缩小打包作用域
exclude/include (确定 loader 规则范围)
resolve.modules 指明第三方模块的绝对路径 (减少不必要的查找)
resolve.mainFields 只采用 main 字段作为入口文件描述字段 (减少搜索步骤,需要考虑到所有运行时依赖的第三方模块的入口文件描述字段)
resolve.extensions 尽可能减少后缀尝试的可能性
noParse 对完全不需要解析的库进行忽略 (不去解析但仍会打包到 bundle 中,注意被忽略掉的文件里不应该包含 import、require、define 等模块化语句)
ignorePlugin (完全排除模块)

说一下 Webpack 的热更新原理吧?

Webpack 的热更新又称热替换(Hot Module Replacement),缩写为 HMR。 这个机制可以做到不用刷新浏览器而将新变更的模块替换掉旧的模块。
HMR的核心就是客户端从服务端拉去更新后的文件,准确地说是 chunk diff (chunk 需要更新的部分),实际上 WDS 与浏览器之间维护了一个 Websocket,当本地资源发生变化时,WDS 会向浏览器推送更新,并带上构建时的 hash,让客户端与上一次资源进行对比。客户端对比出差异后会向 WDS 发起 Ajax 请求来获取更改内容(文件列表、hash),这样客户端就可以再借助这些信息继续向 WDS 发起 jsonp 请求获取该chunk的增量更新。
后续的部分(拿到增量更新之后如何处理?哪些状态该保留?哪些又需要更新?)由 HotModulePlugin 来完成,提供了相关 API 以供开发者针对自身场景进行处理,像react-hot-loader 和 vue-loader 都是借助这些 API 实现 HMR。

什么是bundel?什么是chunk?什么是model?

bundel:是webpack打包后的一个文件;
chunk:代码块,一个chunk 可能有很多的模块组成,用于合并和分割代码;
model:模块,在webpck中,一切都是模块,一个文件就是一个模块,她从入口开始查找webpck依赖的所有模块

webpack和grunt以及gulp有什么不同?

grunt和gulp是基于任务处理的工具,我们需要把我们要做的事分配成各种各样的任务,grunt和gulp会自动执行各种分配的任务,像流水线一样,把资源放上去通过不同的插件进行加工,他的插件非常丰富,能够为我们打造各种工作流;
webpack是模块化打包工具,把所有文件都当作模块进行处理,也就是说webpack和grunt和gulp是两种完全不一样的东西;

Vuex的理解及使用场景

Vuex 是一个专为 Vue 应用程序开发的状态管理模式。每一个 Vuex 应用的核心就是 store(仓库)。

Vuex 的状态存储是响应式的;当 Vue 组件从 store 中读取状态的时候,若 store 中的状态发生变化,那么相应的组件也会相应地得到高效更新 2. 改变 store 中的状态的唯一途径就是显式地提交 (commit) mutation, 这样使得我们可以方便地跟踪每一个状态的变化 Vuex主要包括以下几个核心模块:

1.State:定义了应用的状态数据

2.Getter:在 store 中定义“getter”(可以认为是 store 的计算属性),

就像计算属性一样,getter 的返回值会根据它的依赖被缓存起来, 且只有当它的依赖值发生了改变才会被重新计算

3. Mutation:是唯一更改 store 中状态的方法,且必须是同步函数

4. Action:用于提交 mutation,而不是直接变更状态,可以包含任意异步操作

5. Module:允许将单一的 Store 拆分为多个 store 且同时保存在单一的状态树中

Vue3带来了什么改变?

性能的提升
打包大小减少41%
初次渲染快55%, 更新渲染快133%
内存减少54%

源码的升级
使用Proxy代替defineProperty实现响应式
重写虚拟DOM的实现和Tree-Shaking

拥抱TypeScript
Vue3可以更好的支持TypeScript

新的特性
Composition API(组合API)

(1)setup配置
(2)ref与reactive
(3)watch与watchEffect
(4)provide与inject

新的内置组件

(1)Fragment
(2)Teleport
(3)Suspense

新的生命周期钩子
Vue3.0中可以继续使用Vue2.x中的生命周期钩子,但有有两个被更名:
beforeDestroy改名为 beforeUnmount
destroyed改名为 unmounted

Vue3.0也提供了 Composition API 形式的生命周期钩子,与Vue2.x中钩子对应关系如下:

  • beforeCreate===>setup()
  • created=======>setup()
  • beforeMount===>onBeforeMount
  • mounted=======>onMounted
  • beforeUpdate===>onBeforeUpdate
  • updated =======>onUpdated
  • beforeUnmount ==>onBeforeUnmount
  • unmounted =====>onUnmounted

data 选项应始终被声明为一个函数
移除keyCode支持作为 v-on 的修饰符

为什么 Vite 速度比 Webpack 快?

开发模式的差异
在开发环境中,Webpack 是先打包再启动开发服务器,而 Vite 则是直接启动,然后再按需编译依赖文件。(大家可以启动项目后检查源码 Sources 那里看到)
这意味着,当使用 Webpack 时,所有的模块都需要在开发前进行打包,这会增加启动时间和构建时间。
而 Vite 则采用了不同的策略,它会在请求模块时再进行实时编译,这种按需动态编译的模式极大地缩短了编译时间,特别是在大型项目中,文件数量众多,Vite 的优势更为明显。

对ES Modules的支持
现代浏览器本身就支持 ES Modules,会主动发起请求去获取所需文件。Vite充分利用了这一点,将开发环境下的模块文件直接作为浏览器要执行的文件,而不是像 Webpack 那样先打包,再交给浏览器执行。这种方式减少了中间环节,提高了效率。

底层语言的差异
Webpack 是基于 Node.js 构建的,而 Vite 则是基于 esbuild 进行预构建依赖。esbuild 是采用 Go 语言编写的,Go 语言是纳秒级别的,而 Node.js 是毫秒级别的。因此,Vite 在打包速度上相比Webpack 有 10-100 倍的提升。

热更新的处理
在 Webpack 中,当一个模块或其依赖的模块内容改变时,需要重新编译这些模块。
而在 Vite 中,当某个模块内容改变时,只需要让浏览器重新请求该模块即可,这大大减少了热更新的时间。

总的来说,Vite 之所以比 Webpack 快,主要是因为它采用了不同的开发模式、充分利用了现代浏览器的 ES Modules 支持、使用了更高效的底层语言,并优化了热更新的处理。这些特点使得 Vite在大型项目中具有显著的优势,能够快速启动和构建,提高开发效率。​

ref和reactive的区别

1、从定义数据角度对比:
ref用来定义基本数据类型,reactive用来定义对象或数组类型数据
注意ref也可以用来定义对象或数组类型数据,但是底层是自动通过reactive转为代理对象

2、从原理角度对比:
ref是通过object.defineProperty()中的get和set来实现响应式的,即数据劫持。
reactive是通过使用Proxy来实现响应式,并通过Reflect操作源对象内部的数据。

3、从使用角度对比:
ref定义的数据在操作的时候需要使用.value读取数据,读取数据时模板中直接读取不需要 .value
reactive定义的数据操作和读取数据都不用.value
总的来说,ref和reactive都是用于实现Vue.js组件的数据响应式更新,但是它们的使用方法、适用范围和设计理念等方面略有不同,需要根据具体的应用场景选择合适的API进行开发使用。

uniapp目录结构

pages.json
配置文件,全局页面路径配置,应用的状态栏、导航条、标题、窗口背景色设置等

main.js
入口文件,主要作用是初始化vue实例、定义全局组件、使用需要的插件如 vuex,注意uniapp无法使用vue-router,路由须在pages.json中进行配置。如果开发者坚持使用vue-router,可以在插件市场找到转换插件。

App.vue
是uni-app的主组件,所有页面都是在App.vue下进行切换的,是页面入口文件。但App.vue本身不是页面,这里不能编写视图元素。除此之外,应用生命周期仅可在App.vue中监听,在页面监听无效。

pages
页面管理部分用于存放页面或者组件

应用配置 manifest.json
文件是应用的配置文件,用于指定应用的名称、图标、权限等,HBuilderX 创建的工程此文件在根目录,CLI 创建的工程此文件在 src 目录。我们也可以在这里为Vue 为H5设置跨域拦截处理器

package.json
文件用来对 uni-app 进行全局配置,决定页面文件的路径、窗口样式、原生的导航栏、底部的原生tabbar 等。
pages数组中第一项表示应用启动页

uniApp中如何实现下拉刷新和上拉加载更多

可以使用uni.onPullDownRefresh方法实现下拉刷新,使用uni.onReachBottom方法实现上拉加载更多

// 在页面的onPullDownRefresh方法中实现下拉刷新
onPullDownRefresh() {
  // 执行刷新操作
  console.log('下拉刷新');
  // 刷新完成后调用uni.stopPullDownRefresh()方法停止刷新
  uni.stopPullDownRefresh();
}

// 在页面的onReachBottom方法中实现上拉加载更多
onReachBottom() {
  // 执行加载更多操作
  console.log('上拉加载更多');
}

移动端touch事件有穿透(点透)的问题,怎么解决?

1 阻止默认行为 : e.preventDefault();
2 fastclick.js

uniApp中如何实现页面的分享功能

可以使用uni.showShareMenu方法开启页面的分享功能,使用uni.onShareAppMessage方法设置分享的标题、路径等。

// 开启页面的分享功能
uni.showShareMenu();

// 设置分享的标题、路径等
uni.onShareAppMessage(() => {
  return {
    title: '分享标题',
    path: '/pages/index/index'
  };
});

### Vue.js 常见面试问题及答案 #### 1. MVVM 和 MVC 的区别? MVVM 和 MVC 都是软件架构模式,用于分离关注点并提高代码可维护性。在 MVC 中,控制器 (Controller) 负责处理业务逻辑并与模型 (Model) 和视图 (View) 进行交互;而在 MVVM 中,控制器被替换为 ViewModel[^1]。ViewModel 主要负责管理数据绑定和状态更新,减少了直接操作 DOM 的需求,从而提升了性能和用户体验。 #### 2. Vue.js 的模板编译过程是如何工作的? Vue.js 的模板编译分为三个阶段:解析 (parse)、优化 (optimize) 和生成 (generate)[^4]。 - **解析**: 将模板字符串转换成抽象语法树 (AST),表示 HTML 结构。 - **优化**: 对 AST 进行静态节点标记,以便后续渲染过程中跳过不必要的 diff 操作。 - **生成**: 将优化后的 AST 转换成可以执行的 JavaScript 渲染函数。 #### 3. Vue 动态组件的概念及其用途是什么? 动态组件是指通过 `<component>` 标签结合 `is` 属性来切换不同的组件实例。这种方式允许开发者根据条件或事件动态加载不同类型的组件,提升灵活性和复用性。例如: ```html <template> <div> <button @click="currentComponent = 'ComponentA'">Load A</button> <button @click="currentComponent = 'ComponentB'">Load B</button> <component :is="currentComponent"></component> </div> </template> <script> export default { data() { return { currentComponent: 'ComponentA' }; } }; </script> ``` 上述代码展示了如何基于按钮点击切换两个不同的组件[^2]。 #### 4. Vuex 已经被 Pinia 取代了吗?Pinia 如何使用? 虽然 Vuex 并未完全废弃,但在 Vue 3 中官方更推荐使用 Pinia 来替代 Vuex。Pinia 提供了一种更简单直观的状态管理模式,并且 API 更加现代化。以下是创建一个基本 Store 的示例: ```javascript import { defineStore } from 'pinia'; export const useCounterStore = defineStore('counter', { state: () => ({ count: 0, }), actions: { increment() { this.count++; }, }, }); ``` 此代码定义了一个名为 `counter` 的 Store,其中包含初始状态和方法以修改该状态。 #### 5. Axios 是什么?它有哪些特点? Axios 是一个基于 Promise 的 HTTP 客户端库,适用于浏览器和 Node.js 环境。其主要特性包括但不限于支持请求/响应拦截器、自动转换 JSON 数据以及取消请求等功能[^3]。下面是一段简单的 GET 请求例子: ```javascript axios.get('/api/data') .then(response => console.log(response.data)) .catch(error => console.error(error)); ``` #### 6. v-model 的工作原理是什么? v-model 实现了双向绑定功能,在表单输入元素中相当于同时绑定了 `value` 属性和监听了 `input` 事件。对于自定义组件而言,则是利用 props 接收父级传递的数据并通过 `$emit` 方法触发事件通知父级更改值。 --- ###
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值