JavaScript 基础
js 类型判断的方法
typeof, instanceof
介绍 promise
JavaScript 的 Promise 是一种用于异步编程的重要机制,它使得处理异步操作更加容易和可读。Promise 是 ES6(ECMAScript 2015)引入的,用于处理可能尚未完成的操作,如网络请求、文件读取、数据库查询等。
介绍 async await
async/await 是 ECMAScript 2017 (ES8) 引入的一种用于处理异步操作的语法糖,它建立在 Promise 基础之上,旨在让异步代码更加清晰和易于理解。async 声明一个函数为异步函数,而 await 用于等待 Promise 对象的解决(resolve)或拒绝(reject)。
深拷贝
1 | // 经典深拷贝 |
按照 绿 黄 红 的顺序打印,打印 “绿” 10s 后打印 “黄”,3s 后打印 “红” ,15s 后从绿开始从头继续执行
实现一个方法,生成随机数字验证码(如果要求生成 100 个不能重复,怎么实现)
TypeScript
项目为什么使用 TypeScript?用 Interface 写一个简单的对象和方法
了解 TS 文件具体是怎么编译运行的吗
1 | tsc main.ts |
Vue
v-if 和 v-show 的区别
v-if
和 v-show
是 Vue 中用于控制元素显示与隐藏的两个常用指令,它们有一些重要的区别:
- 编译时机:
v-if
:元素是否被编译和渲染取决于表达式的值。如果条件为false
,元素将不会被渲染到 DOM 中。v-show
:元素会被编译和渲染到 DOM 中,只是通过 CSS 的display
属性来控制是否显示或隐藏。
- 性能:
v-if
:当条件为false
时,元素的整个渲染和销毁过程都会触发,这可以在需要时节省性能,但会增加切换开销。v-show
:元素总是会被渲染,只是通过 CSS 控制是否显示或隐藏。这意味着在频繁切换显示/隐藏时,v-show
通常具有更好的性能,因为元素不会被重新渲染和销毁。
- 用例:
v-if
:适用于需要在条件满足时完全渲染和销毁元素的情况,例如切换不同的路由视图。v-show
:适用于需要频繁切换显示/隐藏的元素,例如折叠面板或模态框。
- 初始化开销:
v-if
:如果初始条件为false
,元素不会被渲染,因此不会有初始渲染开销。v-show
:元素始终会被渲染,因此无论初始条件如何,都会有初始渲染开销。
- DOM 结构:
v-if
:元素在条件为true
时才会真正渲染到 DOM 中,因此不会占用 DOM 结构。v-show
:元素总是存在于 DOM 结构中,只是通过 CSS 控制是否可见。
- 使用场景示例:
- 使用
v-if
:
1 | <template> |
- 使用
v-show
:
1 | <template> |
总之,选择使用 v-if
还是 v-show
取决于你的具体需求和性能考虑。如果元素的显示/隐藏频率很低,或者元素在初始化时通常不会显示,那么使用 v-if
可能更合适。如果需要频繁切换元素的可见性,并且元素通常会显示,那么使用 v-show
可能更有效率。
watch 和 computed 的区别
watch
和 computed
是 Vue 中用于处理响应式数据的两种不同方式,它们在不同的场景下使用。
watch
:
watch
用于监听一个数据的变化,并在数据变化时执行自定义的函数。使用
watch
通常是为了在数据变化时执行一些副作用操作,如发起网络请求、操作 DOM 元素、或者在数据变化时执行一些复杂的计算和逻辑。watch
是一种声明式的响应式,你需要明确告诉 Vue 哪个数据需要监听以及在变化时要执行的操作。
1 | watch: { someData(newValue, oldValue) { // 当 someData 改变时执行的操作 } } |
computed
:
computed
用于创建一个计算属性,这个计算属性的值是根据其他响应式数据计算而来的。使用
computed
通常是为了将数据的计算逻辑封装到一个属性中,以便在模板中使用,而且computed
属性会根据依赖的数据自动更新。computed
是一种声明式的响应式,它允许你在模板中像访问普通属性一样访问计算属性。
1 | computed: { computedValue() { // 基于其他响应式数据计算出的值 return |
在选择使用 watch
还是 computed
时,可以考虑以下几点:
如果你需要监听一个数据的变化并执行一些操作(如日志记录、网络请求、动画效果等),使用
watch
。如果你需要基于一个或多个响应式数据的计算结果,并且希望该计算结果能在模板中使用,使用
computed
。computed
是惰性求值的,只有在它所依赖的数据发生变化时才会重新计算,而watch
则是即时触发的。
底层实现:
watch
使用了 Vue 内部的侦听器机制来监听数据的变化,当数据变化时,执行用户定义的回调函数。computed
也使用了侦听器机制,但它会缓存计算结果,只有依赖的数据发生变化时才会重新计算,从而提高性能。
关于监听深层对象属性的改变,Vue 默认情况下是不会深层递归监听对象属性的。如果需要监听深层对象属性的改变,你可以使用 deep
选项来实现:
1 | watch: { 'someObject.deepProperty': { handler(newVal, oldVal) { // |
这样,当 someObject
对象的 deepProperty
属性发生变化时,handler
方法就会被触发。但需要注意,深层对象属性的监听会带来性能开销,因此应该谨慎使用。如果需要深度监听多个属性,可能需要考虑使用专门的状态管理工具,如 Vuex。
Vue 3 跟 Vue 2 的不同
- 性能提升:
Vue 3 使用了新的响应式系统(Proxy),相对于 Vue 2 的响应式系统(Object.defineProperty)来说,性能更好。
Vue 3 的虚拟 DOM 比 Vue 2 更快,渲染性能更高。
静态树提升(Static Tree Hoisting)可以减少渲染的开销,进一步提升性能。
- Composition API:
Vue 3 引入了 Composition API,允许组件逻辑更好地组织和复用。这是一种基于函数的 API,允许开发者根据功能来组织代码,而不是根据选项(如
data
、methods
)。Composition API 提供了更灵活的组件复用方式,提高了代码的可维护性和可读性。
- TypeScript 支持:
- Vue 3 提供了更好的 TypeScript 支持,包括完整的类型定义,使得在 TypeScript 项目中使用 Vue 更容易。
- 更小的体积:
- Vue 3 的核心库相对于 Vue 2 更小,减少了包的体积。
- 生命周期:
vue2 | vue3 |
---|---|
beforeCreate | setup |
Created | setup |
beforeMount | onBeforeMount |
mounted | onMounted |
beforeUpdate | onBeforeUpdate |
updated | onUpdated |
beforeDestroyed | onBeforeUnmount |
destroyed | onUnmounted |
activated | onActivated |
deactivated | onDeactivated |
Vue 组件通信方式
1.⽗传⼦
在⼦组件的标签上定义属性 ⼦组件通过 props 来进⾏接收,可以通过数组或者对象的⽅式接收,如果⽗组件没有传递属性,⼦组件可以 default 来设置默认值 父传子的使用场景 封装列表的时候 把数据传到子组件渲染
2.⼦传⽗
⼦组件通过 this.$emit(“⾃定义的事件的名字”,要传给⽗组件的数据), ⽗组件通过⼦组件的标签监听⾃定义的时间,最后在父组件接收使用就可以了 子传父的使用场景:在子组件中有删除等方法的时候要在子组件把下标传到父组件操作数据
3.兄弟组件通信
通过中央事件总线,我们也称之为 eventBus,
在 main.js 定义一个空的 vue 实例并且挂载在原型上,通过$emit传数据,在要接收的子组件的created钩子函数下通过$on 接收
4.vuex
把公共数据存在 vuex 里这样就能实现组件通信
5.本地存储
把要传递的数据存在本地存储里,再要接收的组件接收,也能实现组件通信
6.v-model
v-model 是一个语法糖 是:value 和@input 的合写 所以说能实现组件通信
7.$attr和$listener
主要是祖孙之间传值 父组件下面有子组件 a 子组件 a 下面又有 子组件 b 在父组件里还是用自定义属性和自定义事件传 在子组件 a 下面绑定 v-bind=”$attrs” v-on=”$listeners” 在子组件 b 下面通过$attrs 拿数据 通过 $emit 调用方法
8.provide 和 inject
不管嵌套了几层都能拿到数据 把数据定义在 provide 里 在子组件通过 inject 拿到数据 缺点是不响应
9.children 和 parent
在子组件里通过$parent 拿到父组件的数据和方法 在父组件里通过$children 拿到子组件的数据和方法
Vue 组件通信方式
1.⽗传⼦
在⼦组件的标签上定义属性 ⼦组件通过 props 来进⾏接收,可以通过数组或者对象的⽅式接收,如果⽗组件没有传递属性,⼦组件可以 default 来设置默认值 父传子的使用场景 封装列表的时候 把数据传到子组件渲染
2.⼦传⽗
⼦组件通过 this.$emit(“⾃定义的事件的名字”,要传给⽗组件的数据), ⽗组件通过⼦组件的标签监听⾃定义的时间,最后在父组件接收使用就可以了 子传父的使用场景:在子组件中有删除等方法的时候要在子组件把下标传到父组件操作数据
3.兄弟组件通信
通过中央事件总线,我们也称之为 eventBus,
在 main.js 定义一个空的 vue 实例并且挂载在原型上,通过$emit传数据,在要接收的子组件的created钩子函数下通过$on 接收
4.vuex
把公共数据存在 vuex 里这样就能实现组件通信
5.本地存储
把要传递的数据存在本地存储里,再要接收的组件接收,也能实现组件通信
6.v-model
v-model 是一个语法糖 是:value 和@input 的合写 所以说能实现组件通信
7.$attr和$listener
主要是祖孙之间传值 父组件下面有子组件 a 子组件 a 下面又有 子组件 b 在父组件里还是用自定义属性和自定义事件传 在子组件 a 下面绑定 v-bind=”$attrs” v-on=”$listeners” 在子组件 b 下面通过$attrs 拿数据 通过 $emit 调用方法
8.provide 和 inject
不管嵌套了几层都能拿到数据 把数据定义在 provide 里 在子组件通过 inject 拿到数据 缺点是不响应
9.children 和 parent
在子组件里通过$parent 拿到父组件的数据和方法 在父组件里通过$children 拿到子组件的数据和方法
项目为什么使用 Vue 3
Vue 自己写组件你会怎么写?怎么考虑?比如实现一个 button,有 loading 效果啥的
防抖、节流
是的,防抖和节流是两种常用的前端性能优化技巧,用于控制函数的执行频率,以提高页面性能和用户体验。
防抖: https://www.lodashjs.com/docs/lodash.debounce
节流: https://www.lodashjs.com/docs/lodash.throttle
防抖(Debounce):
防抖的主要思想是,在某个连续触发的事件(比如用户输入)结束一段时间后,才执行相应的操作。防抖的目标是减少不必要的函数调用,尤其是对于频繁触发的事件。
防抖的基本原理是设置一个定时器,在每次触发事件时,都会清除之前的定时器,然后重新设置一个新的定时器。只有当事件一段时间内不再触发(定时器计时结束),才会执行相应的操作。
应用场景:
用户输入搜索关键词时,等待用户输入完毕后再执行搜索操作,以减少请求次数。
窗口大小调整事件,等待用户停止调整窗口大小后再执行布局调整操作。
节流(Throttle):
节流的主要思想是控制函数的执行频率,确保函数在一定时间间隔内只执行一次。节流可以用来减少函数的执行次数,以降低资源消耗。
节流的基本原理是使用一个定时器,在每次触发事件时,首先判断是否已经存在定时器。如果没有定时器,就设置一个新的定时器,并在一定时间间隔后执行相应的操作。如果已经存在定时器,则不执行任何操作。
应用场景:
滚动事件,限制滚动事件的触发频率,以降低处理滚动事件时的计算量。
鼠标移动事件,限制鼠标移动事件的触发频率,以减少事件处理的工作量。
总结:
防抖和节流都是用于控制函数执行频率的工具,但它们的应用场景和原理略有不同。
防抖适用于需要等待事件停止触发后再执行操作的场景,而节流适用于需要限制事件触发频率的场景。
使用防抖和节流可以有效提高页面性能,减少不必要的函数执行,特别是在处理频繁触发的事件时。
CSS
常用CSS属性
颜色相关属性:
color
: 文本颜色,可接受十六进制、RGB、RGBA、颜色名等值。background-color
: 背景颜色,可接受同上的值。border-color
: 边框颜色,可接受同上的值。
文本相关属性:
font-size
: 字体大小,可接受像素(px)、百分比(%)、em等值。font-family
: 字体系列,通常接受字体名称或字体堆栈。font-weight
: 字体粗细,通常接受数值(如400、700)或关键字(如normal、bold)。text-align
: 文本对齐方式,可接受值为left、right、center、justify等。line-height
: 行高,通常接受像素、百分比或无单位的数字。
盒模型属性:
width
: 元素宽度,可接受像素、百分比等值。height
: 元素高度,可接受像素、百分比等值。margin
: 外边距,可接受像素、百分比等值。padding
: 内边距,可接受像素、百分比等值。border
: 边框,可接受边框宽度、边框样式、边框颜色等值。
背景属性:
background-image
: 背景图像的URL。background-repeat
: 背景图像的重复方式(如repeat、no-repeat)。background-position
: 背景图像的位置。background-size
: 背景图像的尺寸。
定位属性:
position
: 定位方式,可接受值为static、relative、absolute、fixed等。top
,right
,bottom
,left
: 用于绝对定位元素的位置属性。
显示和隐藏属性:
display
: 元素的显示方式,可接受值为block、inline、none等。visibility
: 元素的可见性,可接受值为visible、hidden。
浮动和清除属性:
float
: 元素浮动方式,可接受值为left、right、none等。clear
: 清除浮动,可接受值为left、right、both、none等。
动画和过渡属性:
animation
: 设置动画,包括动画名称、持续时间、延迟、重复次数等。transition
: 设置过渡效果,包括属性、持续时间、延迟、过渡方式等。
这些是CSS中的一些常用属性以及它们的可选值。CSS属性的使用方式和可选值取决于具体的设计需求和样式目标。不同属性可以组合使用,以实现复杂的样式效果。
flex 实现三栏布局
Flex 布局(弹性盒子布局)是一种用于页面布局的强大工具,可以轻松实现三栏布局。在三栏布局中,通常有一个固定宽度的侧栏,一个固定宽度的主内容区域,以及一个自适应宽度的侧栏。下面是使用 Flex 布局实现三栏布局的示例:
HTML 结构:
1 | <div class="container"> |
CSS 样式:
1 | .container { |
在上述示例中,我们使用 display: flex;
将 .container
设置为 Flex 容器。然后,通过 justify-content: space-between;
将三个子元素平均分布在容器内,左右侧栏的固定宽度为 200px
,而主内容区域使用 flex-grow: 1;
来占据剩余的空间,实现了三栏布局。
这种方式可以让主内容区域自适应,而左右侧栏保持固定宽度,是实现三栏布局的一种常见方法。你可以根据具体需求调整宽度和样式。
Electron
electron通信
模式 1:渲染器进程到主进程(单向)
模式 2:渲染器进程到主进程(双向)
模式 3:主进程到渲染器进程
模式 4:渲染器进程到渲染器进程
Hybrid 开发是怎么实现的
混合开发(Hybrid Development)是一种结合了原生应用和Web技术的移动应用开发方法,通常用于开发跨平台的移动应用。混合应用通常包括两部分:原生容器(Native Container)和Web视图(Web View)。下面是混合开发的基本原理和实现方式:
基本原理:
原生容器:混合应用通常使用原生开发语言(如Java或Swift)创建一个原生容器,这个容器就是一个原生应用,例如一个Android应用或iOS应用。这个原生容器负责提供应用的基本结构、交互和访问设备硬件功能(如相机、GPS等)的能力。
Web视图:在原生容器中,通常会嵌入一个Web视图(Web View),Web视图是一个内嵌的浏览器控件,用于加载和显示Web内容。这个Web视图是通过WebView控件来实现的,不同平台有不同的WebView控件,例如Android上使用的是WebView,iOS上使用的是UIWebView或WKWebView。
Web技术:混合应用的UI和业务逻辑通常使用Web技术来实现,主要是HTML、CSS和JavaScript。开发者可以使用Web技术来构建应用的界面和功能,然后通过Web视图在原生容器中呈现这些Web内容。
通信桥梁:原生容器和Web视图之间通常需要建立一种通信机制,以便它们能够相互交互。这通常通过JavaScript与原生代码的交互接口来实现。原生代码可以暴露一些原生API供JavaScript调用,而JavaScript可以通过回调函数或事件触发来与原生代码进行通信。
实现方式:
混合开发可以使用不同的框架和工具来实现,以下是一些常见的实现方式:
Apache Cordova(旧称PhoneGap):Cordova是一个开源的移动应用开发框架,允许开发者使用HTML、CSS和JavaScript来构建混合应用,并提供了访问设备功能的插件。Cordova应用使用Web视图来显示内容,并通过JavaScript访问原生API。
Ionic Framework:Ionic是一个基于Angular的混合应用开发框架,它提供了一组UI组件和工具,用于构建跨平台的混合应用。Ionic应用使用Web视图来呈现内容,与Cordova集成,可以访问设备功能。
React Native:虽然React Native更加注重原生开发,但它也支持混合开发方式。开发者可以使用React和React Native的技术栈来构建UI,并使用WebView组件来嵌入Web内容。
其他框架:还有其他许多混合开发框架和工具,如Sencha Touch、Framework7等,它们提供了不同的开发体验和功能。
混合开发的优点在于跨平台能力强,可以在多个平台上共享相同的代码和技能,加速开发周期。然而,它也有一些限制,例如性能可能不如纯原生应用,因为Web视图需要一定的渲染时间,还可能受限于原生API的可用性。因此,选择混合开发还是原生开发应根据具体项目需求和性能要求进行权衡。