总结
- 对于框架原理只能说个大概,真的深入某一部分具体的代码和实现方式就只能写出一个框架,许多细节注意不到。
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
-
算法方面还是很薄弱,好在面试官都很和蔼可亲,擅长发现人的美哈哈哈…(最好多刷一刷,不然影响你的工资和成功率???)
-
在投递简历之前,最好通过各种渠道找到公司内部的人,先提前了解业务,也可以帮助后期优秀 offer 的决策。
-
要勇于说不,对于某些 offer 待遇不满意、业务不喜欢,应该相信自己,不要因为当下没有更好的 offer 而投降,一份工作短则一年长则 N 年,为了幸福生活要慎重选择!!!
第一次跳槽十分忐忑不安,和没毕业的时候开始找工作是一样的感受,真的要相信自己,有条不紊的进行。如果有我能帮忙的地方欢迎随时找我,比如简历修改、内推、最起码,可以把烦心事说一说,人嘛都会有苦恼的~
祝大家都有美好的未来,拿下满意的 offer。
如果传入 ref 的是一个对象,将调用 reactive
方法进行深层响应转换
陷阱
setup 中return返回会自动解套【在模板中不需要.value】
ref 作为 reactive 对象的 property 被访问或修改时,也将自动解套 .value
const count = ref(0)
/当做reactive的对象属性----解套/
const state = reactive({
count,
})
/* 不需要.value*/
console.log(state.count) // 0
/修改reactive的值/
state.count = 1
/修改了ref的值/
console.log(count.value) // 1
注意如果将一个新的 ref 分配给现有的 ref, 将替换旧的 ref
/创建一个新的ref/
const otherCount = ref(2)
/赋值给reactive的旧的ref,旧的会被替换掉/
state.count = otherCount
/修改reactive会修改otherCount/
console.log(state.count) // 2
/*修改reactive会count没有被修改 */
console.log(count.value) // 1
嵌套在 reactive Object 中时,ref 才会解套。从 Array 或者 Map 等原生集合类中访问 ref 时,不会自动解套【自由数据类型是Object才会解套,array map set weakmap weakset集合类 访问 ref 时,不会自动解套】
const arr = reactive([ref(0)])
// 这里需要 .value
console.log(arr[0].value)
const map = reactive(new Map([[‘foo’, ref(0)]]))
// 这里需要 .value
console.log(map.get(‘foo’).value)
心智负担上 ref vs reactive
-
在普通 JavaScript 中区别声明基础类型变量与对象变量时一样区别使用 ref 和 reactive
-
所有的地方都用 reactive,然后记得在组合函数返回响应式对象时使用 toRefs。这降低了一些关于 ref 的心智负担
readonly
传入一个对象(响应式或普通)或 ref,返回一个原始对象的只读代理。一个只读的代理是“深层的”,对象内部任何嵌套的属性也都是只读的【返回一个永远不会变的只读代理】【场景可以参数比对等】
const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {
// 依赖追踪
console.log(copy.count)
})
// original 上的修改会触发 copy 上的侦听
original.count++
// 无法修改 copy 并会被警告
copy.count++ // warning!
reactive响应式系统工具集
isProxy
检查一个对象是否是由 reactive 或者 readonly 方法创建的代理
isReactive
检查一个对象是否是由 reactive 创建的响应式代理
import { reactive, isReactive } from ‘vue’
const state = reactive({
name: ‘John’
})
console.log(isReactive(state)) // -> true
如果这个代理是由 readonly 创建的,但是又被 reactive 创建的另一个代理包裹了一层,那么同样也会返回 true
import { reactive, isReactive, readonly } from ‘vue’
const state = reactive({
name: ‘John’
})
// 用readonly创建一个只读响应式对象plain
const plain = readonly({
name: ‘Mary’
})
//readonly创建的,所以isReactive为false
console.log(isReactive(plain)) // -> false
// reactive创建的响应式代理对象包裹一层readonly,isReactive也是true,isReadonly也是true
const stateCopy = readonly(state)
console.log(isReactive(stateCopy)) // -> true
isReadonly
检查一个对象是否是由 readonly 创建的只读代理
reactive高级响应式系统API
toRaw
返回由 reactive 或 readonly 方法转换成响应式代理的普通对象。这是一个还原方法,可用于临时读取,访问不会被代理/跟踪,写入时也不会触发更改。不建议一直持有原始对象的引用【不建议赋值给任何变量】。请谨慎使用
被toRaw之后的对象是没有被代理/跟踪的的普通对象
const foo = {}
const reactiveFoo = reactive(foo)
console.log(toRaw(reactiveFoo) === foo) // true
console.log(toRaw(reactiveFoo) !== reactiveFoo) // true
markRaw
显式标记一个对象为“永远不会转为响应式代理”,函数返回这个对象本身。被 markRaw 标记了,即使在响应式对象中作属性,也依然不是响应式的
const foo = markRaw({
name: ‘Mary’
})
console.log(isReactive(reactive(foo))) // false
markRaw
注意点
-
markRaw和 shallowXXX 一族的 API允许选择性的覆盖reactive或者readonly 默认创建的 “深层的” 特性【响应式】/或者使用无代理的普通对象
-
设计这种「浅层读取」有很多原因
-
- 一些值的实际上的用法非常简单,并没有必要转为响应式【例如三方库的实例/省市区json/Vue组件对象】
-
当渲染一个元素数量庞大,但是数据是不可变的,跳过 Proxy 的转换可以带来性能提升
-
这些 API 被认为是高级的,是因为这种特性仅停留在根级别,所以如果你将一个嵌套的,没有 markRaw 的对象设置为 reactive 对象的属性,在重新访问时,你又会得到一个 Proxy 的版本,在使用中最终会导致标识混淆的严重问题:执行某个操作同时依赖于某个对象的原始版本和代理版本(标识混淆在一般使用当中应该是非常罕见的,但是要想完全避免这样的问题,必须要对整个响应式系统的工作原理有一个相当清晰的认知)。
const foo = markRaw({
nested: {},
})
const bar = reactive({
// 尽管 foo
己经被标记为 raw 了, 但 foo.nested 并没有
nested: foo.nested,
})
console.log(foo.nested === bar.nested) // false
- foo.nested没有被标记为(永远不会转为响应式代理),导致最后的值一个reactive
shallowReactive
只为某个对象的私有(第一层)属性创建浅层的响应式代理,不会对“属性的属性”做深层次、递归地响应式代理,而只是保留原样【第一层是响应式代理,深层次只保留原样(不具备响应式代理)】
const state = shallowReactive({
foo: 1,
nested: {
bar: 2,
},
})
// 变更 state 的自有属性是响应式的【第一层次响应式】
state.foo++
// …但不会深层代理【深层次不是响应式】(渲染性能)
isReactive(state.nested) // false
state.nested.bar++ // 非响应式
shallowReadonly
类似于shallowReactive
,区别是:
-
第一层将会是响应式代理【第一层修改属性会失败】,属性为响应式
-
深层次的对象属性可以修改,属性不是响应式
const state = shallowReadonly({
foo: 1,
nested: {
bar: 2,
},
})
// 变更 state 的自有属性会失败
state.foo++
// …但是嵌套的对象是可以变更的
isReadonly(state.nested) // false
state.nested.bar++ // 嵌套属性依然可修改
ref 响应式系统工具集
customRef
用于自定义一个 ref,可以显式地控制依赖追踪和触发响应,接受一个工厂函数,两个参数分别是用于追踪的 track 与用于触发响应的 trigger,并返回一个一个带有 get 和 set 属性的对象【实际上就是手动 track追踪 和 trigger触发响应】
- 以下代码可以使得v-model防抖
function useDebouncedRef(value, delay = 200) {
let timeout
return customRef((track, trigger) => {
return {
get() {
/初始化手动追踪依赖讲究什么时候去触发依赖收集/
track()
return value
},
set(newValue) {
/修改数据的时候会把上一次的定时器清除【防抖】/
clearTimeout(timeout)
timeout = setTimeout(() => {
/把新设置的数据给到ref数据源/
value = newValue
/再有依赖追踪的前提下触发响应式/
trigger()
}, delay)
},
}
})
}
setup() {
return {
/暴露返回的数据加防抖/
text: useDebouncedRef(‘hello’),
}
}
shallowRef
创建一个 ref ,将会追踪它的 .value 更改操作,但是并不会对变更后的 .value 做响应式代理转换(即变更不会调用 reactive)
前面我们说过如果传入 ref 的是一个对象,将调用 reactive 方法进行深层响应转换,通过shallowRef创建的ref,将不会调用reactive【对象不会是响应式的】
const refOne = shallowRef({});
refOne.value = { id: 1 };
refOne.id == 20;
console.log(isReactive(refOne.value),refOne.value);//false { id: 1 }
triggerRef 【与shallowRef配合】
手动执行与shallowRef
相关的任何效果
const shallow = shallowRef({
greet: ‘Hello, world’
})
// 第一次运行打印 “Hello, world”
watchEffect(() => {
console.log(shallow.value.greet)
})
// 这不会触发效果,因为ref是shallow
shallow.value.greet = ‘Hello, universe’
// 打印 “Hello, universe”
triggerRef(shallow)
Computed and watch【监控变化】
computed
-
传入一个 getter 函数,返回一个默认不可手动修改的 ref 对象【默认传入的是get函数的对象】
-
传入一个拥有 get 和 set 函数的对象,创建一个可手动修改的计算状态
const count = ref(1)
/*不支持修改【只读的】 */
const plusOne = computed(() => count.value + 1)
plusOne.value++ // 错误!
/*【可更改的】 */
const plusOne = computed({
get: () => count.value + 1,
set: (val) => {
count.value = val - 1
},
})
plusOne.value = 1
console.log(count.value) // 0
watchEffect
立即执行传入的一个函数,并响应式追踪其依赖,并在其依赖变更时重新运行该函数
computed与watchEffect区别:
-
computed 计算属性可通过setup return,再模板中使用,watchEffect不能;
-
computed可以使用多个,并且对多个属性进行不同的响应计算,watchEffect会存在副作用
const count = ref(0)
watchEffect(() => console.log(count.value))
// -> 打印出 0
setTimeout(() => {
count.value++
// -> 打印出 1
}, 100)
当在组件的setup()函数或生命周期钩子期间调用watchEffect时,监视程序会链接到组件的生命周期,并在卸载组件时自动停止,一般情况下watchEffect返回可以stop 操作,停止监听程序
const stop = watchEffect(() => {
/* … */
})
// 停止监听程序
stop()
副作用(函数式编程)
一个带有副作用的函数不仅只是简单的返回一个值,还干了一些其他的事情,比如:
-
修改一个变量
-
直接修改数据结构
-
设置一个对象的成员
-
抛出一个异常或以一个错误终止
-
打印到终端或读取用户的输入
-
读取或写入一个文件
-
在屏幕上绘画
如果一个函数内外有依赖于外部变量或者环境时,常常我们称之为其有副作用,如果我们仅通过函数签名不打开内部代码检查并不能知道该函数在干什么,作为一个独立函数我们期望有明确的输入和输出,副作用是bug的发源地,作为程序员开发者应尽量少的开发有副作用的函数或方法,副作用也使得方法通用性下降不适合扩展和可重用性
清除副作用
在一些时候监听函数将执行异步副作用【一个响应式依赖被修改了,会做其他事情】,这些响应需要在其失效时清除(例如在效果完成前状态改变)。effect函数接收一个onInvalidate 函数作入参, 用来注册清理失效时的回调。这个 invalidation函数 在什么时候会被调用:
-
监听函数重新被执行的时候【响应式依赖的数据被修改】
-
监听停止的时候(如果watchEffect在setup()或者生命周期函数中被使用的时候组件会被卸载)【停止观察】
watchEffect(onInvalidate => {
/这是个异步操作/
const token = performAsyncOperation(id.value)//id依赖
onInvalidate(() => {
// id被修改了或者监听停止了会触发token.cancel()事件【这块区域的代码】.
// 这里是异步事件的话,前面的peding的异步操作无效【这里的异步事件只执行一次】
token.cancel()/异步操作/
console.log(‘onInvalidate’)
})
})
从上面看:我们之所以是通过传入一个函数去注册失效回调,而不是从回调返回它(如 React useEffect
中的方式),是因为返回值对于异步错误处理很重要
const data = ref(null)
watchEffect(async onInvalidate => {
onInvalidate(() => {…}) // 我们在Promise的resolves之前注册清理函数(cleanup function)
data.value = await fetchData(props.id)
})
我们知道异步函数都会隐式地返回一个 Promise,但是清理副作用的函数必须要在 Promise 被 resolve 之前被注册。另外,Vue 依赖这个返回的 Promise 来自动处理 Promise 链上的潜在错误
副作用刷新时机
Vue 的响应式系统会缓存副作用函数,并异步地刷新它们,这样可以避免同一个 tick 中多个状态改变导致的不必要的重复调用。在核心的具体实现中, 组件的更新函数也是一个被侦听的副作用。当一个用户定义的副作用函数进入队列时, 会在所有的组件更新后执行
-
count 会在初始运行时同步打印出来
-
更改 count 时,将在组件更新后执行副作用
初始化运行是在组件 mounted 之前执行的【你希望在编写副作用函数时访问 DOM(或模板 ref),请在 onMounted 钩子中进行】
onMounted(() => {
watchEffect(() => {
// 在这里可以访问到 DOM 或者 template refs
})
})
如果副作用需要同步或在组件更新之前重新运行,我们可以传递一个拥有 flush 属性的对象作为选项(默认为 ‘post’)
// 同步运行
watchEffect(
() => {
/* … */
},
{
flush: ‘sync’,
}
)
// 组件更新前执行
watchEffect(
() => {
/* … */
},
{
flush: ‘pre’,
}
)
侦听器调试【响应式调试用的】
onTrack 和 onTrigger 选项可用于调试一个侦听器的行为。
-
当一个 reactive 对象属性或一个 ref 作为依赖被追踪时,将调用 onTrack【调用次数为被追踪的数量】
-
依赖项变更会导致重新追踪依赖,从而onTrack被调用【调用次数为被追踪的数量】
-
的数量】 依赖项变更会导致重新追踪依赖,从而onTrack被调用【调用次数为被追踪的数量】 依赖项变更导致副作用被触发时,将调用 onTrigger
这两个回调都将接收到一个包含有关所依赖项信息的调试器事件。建议在以下回调中编写 debugger 语句来检查依赖关系:【onTrack 和 onTrigger 仅在开发模式下生效】
watchEffect(
() => {
/* 副作用的内容 */
},
{
onTrigger(e) {
/副作用依赖修改/
debugger
},
onTrack(e) {
/副作用依赖修改/
debugger
},
}
)
watch
watch API 完全等效于 2.x watch 中相应的选项。watch 需要侦听特定的数据源,并在回调函数中执行副作用【默认情况是懒执行的,也就是说仅在侦听的源变更时才执行回调】
watch允许我们:
-
懒执行副作用
-
更明确哪些状态的改变会触发侦听器重新运行副作用
-
访问侦听状态变化前后的值
侦听单个数据源
侦听器的数据源可以是一个拥有返回值的 getter 函数,也可以是 ref:
// 侦听一个 getter
const state = reactive({ count: 0 })
watch(
() => state.count,
(count, prevCount) => {
/* … */
}
)
// 直接侦听一个 ref
const count = ref(0)
watch(count, (count, prevCount) => {
/* … */
})
侦听多个数据源
watcher 也可以使用数组来同时侦听多个源
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar]) => {
/* … */
})
与 watchEffect 共享的行为
watch 和 watchEffect 在停止侦听, 清除副作用 (相应地 onInvalidate 会作为回调的第三个参数传入),副作用刷新时机 和 侦听器调试 等方面行为一致:
watch([fooRef, barRef], ([foo, bar], [prevFoo, prevBar],onInvalidate) => {
/* … */
onInvalidate(() => {…})
},
{
onTrigger(e) {
/副作用依赖修改/
debugger
},
onTrack(e) {
/副作用依赖修改/
debugger
},
})
生命周期钩子函数
与 2.x 版本生命周期相对应的组合式 API
-
beforeCreate -> 使用 setup()
-
created -> 使用 setup()
-
beforeMount -> onBeforeMount
-
mounted -> onMounted
-
beforeUpdate -> onBeforeUpdate
-
updated -> onUpdated
-
beforeDestroy -> onBeforeUnmount
-
destroyed -> onUnmounted
-
errorCaptured -> onErrorCaptured
import { onMounted, onUpdated, onUnmounted } from ‘vue’
setup() {
onMounted(() => {
console.log(‘mounted!’)
})
onUpdated(() => {
console.log(‘updated!’)
})
onUnmounted(() => {
console.log(‘unmounted!’)
})
}
这些生命周期钩子注册函数只能在 setup() 期间同步使用, 因为它们依赖于内部的全局状态来定位当前组件实例(正在调用 setup() 的组件实例), 不在当前组件下调用这些函数会抛出一个错误。
组件实例上下文也是在生命周期钩子同步执行期间设置的,因此,在卸载组件时,在生命周期钩子内部同步创建的侦听器和计算状态也将自动删除。
新增的钩子函数
除了和 2.x 生命周期等效项之外,组合式 API 还提供了以下调试钩子函数:
-
onRenderTracked
-
onRenderTriggered
两个钩子函数都接收一个 DebuggerEvent,与 watchEffect 参数选项中的 onTrack 和 onTrigger 类似:
export default {
onRenderTracked(e){
debugger
// 检查有响应和追踪的依赖性
},
onRenderTriggered(e) {
debugger
// 检查哪个依赖性导致组件重新渲染
},
}
Vue提供的内置组件
component 与Vue2.x一致
渲染一个“元组件”为动态组件。依 is 的值,来决定哪个组件被渲染。
transition 与 Vue2.x 【基本】 一致有差异
Props新增
-
persisted - boolean 如果为true,则表示这是一个转换,实际上不会插入/删除元素,而是切换显示/隐藏状态。transition 过渡挂钩被注入,但会被渲染器跳过。相反,自定义指令可以通过调用注入的钩子(例如v-show)来控制过渡
-
enter-class----->enter-from-class
-
~~leave-class----->leave-from-class
事件
- before-appear
transition-group 与 Vue2.x 一致
**slot 与 Vue2.x 一致 **
teleport 【新增组件】
Props
to - string 必填属性,必须是一个有效的query选择器,或者是元素(如果在浏览器环境中使用)。中的内容将会被放置到指定的目标元素中
/元素/
disabled - boolean 这是一个可选项 ,做一个是可以用来禁用的功能,这意味着它的插槽内容不会移动到任何地方,而是按没有teleport组件一般来呈现【默认为false】
999999
注意,这将移动实际的DOM节点,而不是销毁和重新创建,并且还将保持任何组件实例是活动的。所有有状态HTML元素(比如一个正在播放的视频)将保持它们的状态。【控制displayVideoInline并不是销毁重建,它保持实例是存在的,不会被注销】
关于Teleport 其他内容
Vue 鼓励我们通过将UI和相关行为封装到组件中来构建UI。我们可以将它们彼此嵌套在一起,以构建构成应用程序UI的树
但是,有时组件模板的一部分逻辑上属于这个组件,而从技术角度来看,最好将这一部分模板移到DOM中的其他地方,放到Vue应用程序之外
一个常见的场景是创建一个包含全屏模态的组件。在大多数情况下,您希望模态的逻辑驻留在组件中,但是模态框的定位问题很快就很难通过CSS解决,或者需要更改组件的组成
考虑下面的HTML结构:
Tooltips with Vue 3 Teleport
让我们看看 mode -button
该组件将有一个button元素来触发模态的打开,还有一个div元素,其类为.modal,它将包含模态的内容和一个自关闭按钮
const app = Vue.createApp({});
app.component(‘modal-button’, {
template: `
<button @click=“modalOpen = true”>
Open full screen modal!
I’m a modal!
<button @click=“modalOpen = false”>
Close
`,
data() {
return {
modalOpen: false
}
}
})
当在初始HTML结构中使用这个组件时,我们可以看到一个问题——模态被呈现在深嵌套的div中,模态的绝对位置以父div相对位置作为参考。
Teleport提供了一种干净的方式,允许我们控制DOM中希望在哪个父节点下呈现HTML片段,而不必诉诸全局状态或将其拆分为两个组件。
让我们修改我们的modal-button来使用并告诉Vue "teleport this HTML to the “body"标签”。
app.component(‘modal-button’, {
template: `
<button @click=“modalOpen = true”>
Open full screen modal! (With teleport!)
I’m a teleported modal!
(My parent is “body”)
<button @click=“modalOpen = false”>
Close
`,
data() {
return {
modalOpen: false
}
}
})
与Vue组件一起使用
如果包含一个Vue组件,它将仍然是的父组件的逻辑子组件
const app = Vue.createApp({
template: `
Root instance
`
})
app.component(‘parent-component’, {
template: `
This is a parent component
`
})
app.component(‘child-component’, {
props: [‘name’],
template: `
`
})
在这种情况下,即使在不同的地方呈现child-component,它仍将是parent-componen的子组件【而不是爷爷组件】,并将从其父组件接收一个name 的props
这也意味着来自父组件的注入如预期的那样工作,并且子组件将嵌套在Vue Devtools的父组件之下,而不是放在实际内容移动到的地方
对同一目标使用多次teleports
一个常见的用例场景是一个可重用的组件,该组件可能同时有多个活动实例。对于这种场景,多个组件可以将它们的内容挂载到相同的目标元素。这个顺序将是一个简单的附加—稍后的挂载将位于目标元素中较早的挂载之后。
依赖注入Provide / Inject
provide 和 inject 提供依赖注入,功能类似 2.x 的 provide/inject。两者都只能在当前活动组件实例的 setup() 中调用。
例如,如果我们想在根组件上提供一个book name,并将其inject到子组件上
import { provide, inject } from ‘vue’
const RootComponent = {
setup() {
provide(‘book’, ‘Vue 3 guide’)
}
}
const MyBook = {
setup() {
const book = inject(
‘book’,
‘Eloquent Javascript’ /* 选项的默认值,假如父组件不提供值就返回默认 */
)
return {
book
}
}
}
inject 接受一个可选的的默认值作为第二个参数。如果未提供默认值,并且在 provide 上下文中未找到该属性,则 inject 返回 undefined。
如果我们需要提供或注入多个值,我们可以通过随后分别调用provide或inject来实现【多次调用】
import { provide, inject } from ‘vue’
const RootComponent = {
setup() {
provide(‘book’, ‘Vue 3 guide’)
provide(‘year’, ‘2020’)
}
}
const MyBook = {
setup() {
const book = inject(
‘book’,
‘Eloquent Javascript’ /* 选项的默认值,假如父组件不提供值就返回默认 */
)
const year = inject(‘year’)
return {
book,
year
}
}
}
注入的响应性
可以使用 ref 或 reactive 来保证 provided 和 injected 之间值的响应
import { ref, reactive } from ‘vue’
// 提供者
setup() {
const book = reactive({
title: ‘Vue 3 Guide’,
author: ‘Vue Team’
})
const year = ref(‘2020’)
/提供reactive响应式/
provide(‘book’, book)
/提供ref响应式/
provide(‘year’, year)
}
// 消费者
setup() {
const book = inject(‘book’)
const year = inject(‘year’)
/响应式/
return { book, year }
}
现在,当提供者组件上的book或year发生变化时,我们可以观察到它们在注入的组件上的变化。
警告:我们不建议改变一个被注入的反应性属性【子组件去修改数据流】,因为它会破坏Vue的单向数据流。相反,尝试在提供值【父组件去修改】的地方改变值,或者提供一个方法来改变值
import { ref, reactive } from ‘vue’
// in provider
setup() {
const book = reactive({
title: ‘Vue 3 Guide’,
author: ‘Vue Team’
})
function changeBookName() {
book.title = ‘Vue 3 Advanced Guide’
}
provide(‘book’, book)
provide(‘changeBookName’, changeBookName)
}
// in consumer
setup() {
const book = inject(‘book’)
const changeBookName = inject(‘changeBookName’)
return { book, changeBookName }
}
指令
–
v-text 【Vue2.x一致】
v-html【Vue2.x一致】
v-show【Vue2.x一致】
v-if【Vue2.x一致】
v-else【Vue2.x一致】
v-else-if【Vue2.x一致】
v-for【Vue2.x一致】
v-on【Vue2.x一致】
v-bind 【Vue2.x 修饰符差异】
修饰符
.prop 去除.sync 去除.camel 将 kebab-case attribute 名转换为 camelCase
v-model【Vue2.x一致】
v-slot【Vue2.x一致】
v-cloak【Vue2.x一致】
v-once 【Vue2.x一致】
v-pre【Vue2.x一致】
v-is【新增】
注意:本节只影响在页面的HTML中直接编写Vue模板的情况
全局API
createApp
返回一个应用程序实例,提供了一个应用程序上下文。应用程序实例挂载的整个组件树共享相同的上下文。
const app = Vue.createApp({})
参数:该函数接收一个根组件选项对象作为第一个参数
const app = Vue.createApp({
data() {
return {
…
}
},
methods: {…},
computed: {…}
setup(){…}
…
})
最后
开源分享:【大厂前端面试题解析+核心总结学习笔记+真实项目实战+最新讲解视频】
就答题情况而言,第一问100%都可以回答正确,第二问大概只有50%正确率,第三问能回答正确的就不多了,第四问再正确就非常非常少了。其实此题并没有太多刁钻匪夷所思的用法,都是一些可能会遇到的场景,而大多数人但凡有1年到2年的工作经验都应该完全正确才对。
只能说有一些人太急躁太轻视了,希望大家通过此文了解js一些特性。
并祝愿大家在新的一年找工作面试中胆大心细,发挥出最好的水平,找到一份理想的工作。