MOOC 1299 front-end interview-VUE3 related arrangement

VUE3 module

1. What are the advantages of VUE3 over VUE2?

insert image description here

2. VUE3 life cycle

insert image description here

insert image description here

insert image description here

3. Examples of ref, toRef, reactive, toRefs

ref example

insert image description here

<template>
  <p>ref demo {
    
    {
    
     ageRef }}{
    
    {
    
     state.name }}</p>
</template>
<script>
import {
    
     reactive, ref } from 'vue'
export default {
    
    
  name: 'Ref',
  setup() {
    
    
    const ageRef = ref(20) // 值类型 响应式
    const nameRef = ref('ref的使用')

    const state = reactive({
    
    
      name: nameRef,
    })

    setTimeout(() => {
    
    
      console.log('ageRef', ageRef.value) // 1.5s后 ageRef 25

      ageRef.value = 25 // .value 修改值
      nameRef.value = '除template模版和reactive中,其他地方都使用.value'
    }, 1500)
    return {
    
    
      ageRef,
      state,
    }
  },
}
</script>

toRef example

insert image description here

<template>
  <p>toRef demo --- {
    
    {
    
     ageRef }} -- {
    
    {
    
     state.name }} {
    
    {
    
     state.age }}</p>
</template>

<script>
import {
    
     toRef } from 'vue'

export default {
    
    
  name: 'toRef',
  setup() {
    
    
    const state = reactive({
    
    
      // 普通对象想实现响应式用 reactive
      age: 20,
      name: 'toRef的使用',
    })

    // toRef 如果用于普通对象(非响应式对象),产出的结果不具备响应式
    // const state = {
    
    
    //   age: 20,
    //   name: '普通对象,不具备响应式',
    // }

    // reactive 中的某一个属性想要 单独拿出来 实现响应式 使用 toRef
    const ageRef = toRef(state, 'age') // 引用 state 中的 age属性

    setTimeout(() => {
    
    
      state.age = 25
    }, 1500)

    setTimeout(() => {
    
    
      ageRef.value = 30 // .value 修改值
    }, 3000)

    return {
    
    
      ageRef,
      state,
    }
  }
}
</script>

toRefs example

insert image description here

<template>
  <p>toRefs demo {
    
    {
    
     age }}{
    
    {
    
     name }}</p>
</template>

<script>
import {
    
     toRefs ,reactive} from 'vue'

export default {
    
    
  name: 'toRefs',
  setup() {
    
    
    const state = reactive({
    
    
      age: 20,
      name: 'toRefs示例',
    })

    const stateAsRefs = toRefs(state) // 将响应式对象,变成普通对象

    // 每个属性,都是 ref对象。 因此取出 age 要使用 Ref 结尾命名
    // const { age: ageRef, name: nameRef } = stateAsRefs
    // return {
    
    
    //   然后 return 上面命名的 ageRef, 模版中使用 {
    
    {ageRef}}
    //   ageRef,
    //   nameRef,
    // }
    //  此时一旦 state中的属性多了,需要给每一个都命名,不利用维护.

    setTimeout(() => {
    
    
      console.log('如果直接...state,会失去响应式。而使用toRefs没事')
      state.age = 25
    }, 1500)
    // 因此这样 更加方便直观
    return {
    
    
      // ...state | 如果直接使用 ...state ,模版中 {
    
    {name}} 会丢失响应式
      // state | 如果这样使用 state,模版中 需要{
    
    {state.name}} 不会丢失响应式,但是很繁琐
      ...stateAsRefs, // = return stateAsRefs 这种写法
    }
  },
}
</script>
  • toRef 是针对 state中的 某一个属性
  • toRefs 是针对 state 中的 所有属性

insert image description here

insert image description here

4. Advanced, in-depth understanding of ref

insert image description here

Why is ref needed?

insert image description here
Not responsive - example

<template>
  <p>
    why ref demo {
    
    {
    
     age1 }}-[...state会丢失响应式]|
    {
    
    {
    
     state.age }}-[具备响应式]
  </p>
</template>

<script>
import {
    
     reactive } from 'vue'

export default {
    
    
  name: 'WhyRef',
  setup() {
    
    
    // Proxy 对象(针对对象才具备响应式)
    const state = reactive({
    
    
      age: '20',
      name: 'reactive针对对象,ref针对普通类型',
    })

    let age1 = 20 // 普通值类型,不具备响应式

    setTimeout(() => {
    
    
      console.log('普通值类型数据,并不具备响应式')
      age1 = 25 // 普通值类型 不具备响应式
      state.age = 25 // = let age = 25 不具备响应式
    }, 1500)

    return {
    
    
      age1, // 普通值类型 不具备响应式
      ...state, // 如果直接使用 ...state ,模版中 {
    
    {age}} 会丢失响应式
    }
  },
}
</script>

Responsive - Example

<template>
  <p>
    why ref demo
    {
    
    {
    
     state.age }}-[具备响应式] ,| {
    
    {
    
     age1 }}-[具备响应式]
  </p>
</template>

<script>
import {
    
     reactive } from 'vue'

export default {
    
    
  name: 'WhyRef',
  setup() {
    
    
    // Proxy 对象(针对对象才具备响应式)
    const state = reactive({
    
    
      age: '20',
      name: 'reactive针对对象,ref针对普通类型',
    })

    const age1 = computed(() => {
    
    
      return state.age + 1
    })
    // computed 返回的也是一个类似 ref的值,类似ref的机制
    // 也可以通过 .value来获取值,但是不要修改,computed的值不太适合修改
    console.log('age1.value', age1.value)

    setTimeout(() => {
    
    
      state.age = 25 // = let age = 25 不具备响应式
    }, 1500)

    return {
    
    
      state, // 模版使用 state.age具备响应式
      age1, // 具备响应式
    }
  },
}
</script>
<template>
  <p>{
    
    {
    
     x }}{
    
    {
    
     y }} -- 此时具备响应式</p>
</template>

<script>
import {
    
     reactive, toRefs } from 'vue'

function useFeatureX() {
    
    
  const state = reactive({
    
    
    x: 1,
    y: 2,
  })
  return toRefs(state)
  // return state  模版中{
    
    { state1.y }} - 不进行结构需要这种方式写
}

export default {
    
    
  name: 'WhyRef',
  setup() {
    
    
    const {
    
     x, y } = useFeatureX()
    // const state1 = useFeatureX() 不进行结构
    return {
    
    
      // state1, // 不进行结构
    }
  },
}
</script>

5. Why is .value needed?

insert image description here

insert image description here
insert image description here

insert image description here
insert image description here

6. What important functions have been upgraded in VUE3?

insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

insert image description here
insert image description here

7. How to use Composition API to implement logic reuse?

insert image description here

insert image description here
insert image description here
insert image description here
insert image description here

8. How does VUE3 implement responsiveness?

insert image description here
insert image description here
insert image description here
Please add a picture description

insert image description here
insert image description here
insert image description here
insert image description here
insert image description here
insert image description here

9. In-depth proxy, see the packaged proxy below

// 创建响应式
function reactive(target = {
     
     }) {
    
    
  if (typeof target !== 'object' || target == null) {
    
    
    // 不是对象或数组,则返回
    return target
  }

  // 代理配置
  const proxyConf = {
    
    
    get(target, key, receiver) {
    
    
      // 只处理本身(非原型的) 属性
      const ownKeys = Reflect.ownKeys(target)
      if (ownKeys.includes(key)) {
    
    
        console.log('get 获取', key) // 监听
      }

      const result = Reflect.get(target, key, receiver)
      //深度监听
      // 如果直接返回 retun result , data中的info 会被上面 if判断返回

      return reactive(result)// 返回结果
    },
    set(target, key, val, receiver) {
    
    
      // 重复的数据,不处理
      if (val === target[key]) {
    
    
        return true
      }

      // 只处理本身(非原型的) 属性
      const ownKeys = Reflect.ownKeys(target)
      if (ownKeys.includes(key)) {
    
    
        console.log('已有的 key', key) // 监听
      } else {
    
    
        console.log('新增的 key', key);
      }

      const result = Reflect.set(target, key, val, receiver)
      console.log('set 设置', key, val);
      // console.log('result 是否设置成功',result); // true
      return result // 返回结果
    },
    deleteProperty(target, key) {
    
    
      const result = Reflect.defineProperty(target, key)
      console.log('delete property', key);
      // console.log('result 是否设置成功',result) // true
      return result // 返回结果
    }
  }

  //  生成代理对象
  const observed = new Proxy(target, proxyConf)
  return observed
}
// 测试数据
const data = {
    
    
  name: 'proxy实现响应式', // proxyData.name | 会 get name 获取到name名
  age: 20,
  info: {
    
     // proxyData.info.city | get info 并没有 get到city
    city: '北京,需要深度监听', // 在get 时返回 reactive(result) 可以get 到 city
    a: {
    
     // 如果访问 a , a具有响应式
      b: 100 // b未被访问,b不具备响应式
    }
  }
}

// 将要实现响应式的 data对象 传入 reactive函数中
const proxyData = reactive(data)

insert image description here

  • How is the performance improved?
  • Oject.defineProperty is recursive from the beginning, recursively to the end
  • When does the Proxy get and when does it recurse, and if it doesn’t get, it doesn’t recurse

insert image description here
insert image description here
insert image description here
insert image description here

10. V3 removes the .sync attribute and replaces it with v-model

insert image description here
The following is a sample code, which includes a parent component and a child component, which realize the two-way binding of parent-child data through v-bind and $emit:

<!-- 父组件 TextDocument.vue -->
<template>
  <div>
    <h1>{
    
    {
    
     doc.title }}</h1>
    <title-editor v-bind:title="doc.title" v-on:update:title="updateTitle"></title-editor>
  </div>
</template>

<script>
import TitleEditor from './TitleEditor.vue'

export default {
    
    
  components: {
    
    
    TitleEditor
  },
  data() {
    
    
    return {
    
    
      doc: {
    
    
        title: "默认标题"
      }
    }
  },
  methods: {
    
    
    updateTitle(newTitle) {
    
    
      this.doc.title = newTitle;
    }
  }
};
</script>


<!-- 子组件 TitleEditor.vue -->
<template>
  <div>
    <input type="text" v-bind:value="title" v-on:input="updateTitle($event.target.value)">
  </div>
</template>

<script>
export default {
    
    
  props: ['title'],
  methods: {
    
    
    updateTitle(newTitle) {
    
    
      this.$emit('update:title', newTitle);
    }
  }
}
</script>

insert image description here
insert image description here
insert image description here

insert image description here
insert image description here

11. What is the difference between watch and watchEffect?

insert image description here

watch monitors ref changes

<!-- 先看watch 监听 ref-->
<template>
  <p>watch vs watchEffect</p>
  <p>{
    
    {
    
     numberRef }}</p>
  <p>{
    
    {
    
     name }}{
    
    {
    
     age }}</p>
</template>

<script>
import {
    
     reactive, ref, toRefs, watch, watchEffect } from 'vue'

export default {
    
    
  name: 'watch',
  setup() {
    
    
    const numberRef = ref(100) // watch监听
    watch(
      numberRef,
      (newNumber, oldNumber) => {
    
    
        // watch 不需要使用.value
        console.log('ref watch', newNumber, oldNumber)
        // 调用setTimeout 打印结果 200 100
      },
      {
    
    
        immediate: true, // 初始化之前就监听,可选
        // 打印结果 ref watch 100 undefined
        // 为什么是undefined,因为没有修改值,监听初始化就是undefined
      }
    )

    // setTimeout(() => {
    
    
    //   numberRef.value = 200
    // }, 1500)

    return {
    
    
      numberRef
    }
  },
}
</script>

insert image description here

insert image description here

watch monitors reactive changes

<template>
  <p>watch vs watchEffect</p>
  <p>{
    
    {
    
     numberRef }}</p>
  <p>{
    
    {
    
     name }}{
    
    {
    
     age }}</p>
</template>
<script>
import {
    
     reactive, ref, toRefs, watch } from 'vue'
export default {
    
    
  name: 'watch',
  setup() {
    
    
    const numberRef = ref(100) // watch监听
    const state = reactive({
    
    
      name: 'watch 监听 reactive',
      age: 20,
    })

    watch(
      () => state.age,
      // 第二个参数,回调函数
      (newAge, oldAge) => {
    
    
        console.log('state watch', newAge, oldAge)
      },
      // 第三个参数,配置项
      {
    
    
        immediate: true, // 初始化之前就监听,可选
        deep: true, // 深度监听,
        // 如果age是一个对象或数组,就可以深度监听 其中的变化
      }
    )
    setTimeout(() => {
    
    
      state.age = 25
    }, 1500)
    setTimeout(() => {
    
    
      state.name = '是否会监听到'
    }, 3000)

    return {
    
    
      numberRef,
      ...toRefs(state),
    }
  },
}
</script>

insert image description here

watchEffect monitors ref and reactive

The state data in setup is the same as the watch monitoring code above
insert image description here
insert image description here

insert image description here

12. How to get component instance in setup

insert image description here
insert image description here
insert image description here
const instance = getCurrentInstance() is the instance of the component
insert image description here
insert image description here
insert image description here

insert image description here

13. Why is VUE3 faster than VUE2? The compilation optimization is as follows

insert image description here

PatchFlag static flag

insert image description here

template template

<div>
  <span>hello vue3</span>
  <span>{
    
    {
    
    msg}} 使用TEXT标记</span>
  <span :id="name">使用ClASS标记</span>
  <span :id="name">{
    
    {
    
    msg}} 使用TEXTPROPS标记</span>
  <span :id="name" :msg="msg">使用PROPS 放入数组中标记多个</span>
</div>

After the patchFlag tag

import {
    
     createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createElementBlock("div", null, [
    _createElementVNode("span", null, "hello vue3"),
    _createElementVNode("span", null, _toDisplayString(_ctx.msg) + " 使用TEXT标记", 1 /* TEXT */),
    _createElementVNode("span", {
    
     id: _ctx.name }, "使用ClASS标记", 8 /* PROPS */, ["id"]),
    _createElementVNode("span", {
    
     id: _ctx.name }, _toDisplayString(_ctx.msg) + " 使用TEXT 和 PROPS标记", 9 /* TEXT, PROPS */, ["id"]),
    _createElementVNode("span", {
    
    
      id: _ctx.name,
      msg: _ctx.msg
    }, "使用PROPS 放入数组中标记多个", 8 /* PROPS */, ["id", "msg"])
  ]))
}

// Check the console for the AST

insert image description here
1 is TEXT, indicating that the text content of VNode has changed, and the view needs to be updated
insert image description here

insert image description here

insert image description here

hostStatic cache merge

insert image description here
template template

<div>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>{
    
    {
    
    msg}}</span>
</div>

insert image description here

hoistStatic uses -1 /* HOISTED */ is caching and promotion

import {
    
     createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

const _hoisted_1 = /*#__PURE__*/_createElementVNode("span", null, "hello vue3", -1 /* HOISTED */)
const _hoisted_2 = /*#__PURE__*/_createElementVNode("span", null, "hello vue3", -1 /* HOISTED */)
const _hoisted_3 = /*#__PURE__*/_createElementVNode("span", null, "hello vue3", -1 /* HOISTED */)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createElementBlock("div", null, [
    _hoisted_1,
    _hoisted_2,
    _hoisted_3,
    _createElementVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

// Check the console for the AST

If adjacent nodes >= 10, they will be merged into one node

import {
    
     createElementVNode as _createElementVNode, toDisplayString as _toDisplayString, createStaticVNode as _createStaticVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

const _hoisted_1 = /*#__PURE__*/_createStaticVNode("<span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span>", 10)

export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createElementBlock("div", null, [
    _hoisted_1,
    _createElementVNode("span", null, _toDisplayString(_ctx.msg), 1 /* TEXT */)
  ]))
}

// Check the console for the AST

insert image description here

cacheHandler cache event

insert image description here

import {
    
     createElementVNode as _createElementVNode, openBlock as _openBlock, createElementBlock as _createElementBlock } from "vue"

export function render(_ctx, _cache, $props, $setup, $data, $options) {
    
    
  return (_openBlock(), _createElementBlock("div", null, [
    _createElementVNode("span", {
    
    
      onClick: _cache[0] || (_cache[0] = (...args) => (_ctx.clickHandler && _ctx.clickHandler(...args)))
    }, "hello vue3")
  ]))
}

// Check the console for the AST

SSR optimization

insert image description here
insert image description here

After checking SSR, when it renders, it renders a string, and it can be done without vdom conversion

<div>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>hello vue3</span>
  <span>{
    
    {
    
     msg }}</span>
</div> 
import {
    
     mergeProps as _mergeProps } from "vue"
import {
    
     ssrRenderAttrs as _ssrRenderAttrs, ssrInterpolate as _ssrInterpolate } from "vue/server-renderer"

export function ssrRender(_ctx, _push, _parent, _attrs, $props, $setup, $data, $options) {
    
    
  const _cssVars = {
    
     style: {
    
     color: _ctx.color }}
  _push(`<div${
      
      
    _ssrRenderAttrs(_mergeProps(_attrs, _cssVars))
  }><span>hello vue3</span><span>hello vue3</span><span>hello vue3</span><span>${
      
      
    _ssrInterpolate(_ctx.msg)
  }</span></div>`)
}

// Check the console for the AST

tree shaking

When compiling, different APIs are introduced according to different situations. It doesn't pull in all of them, but on demand.
insert image description here

  • According to the SSR code above, import whatever you need
  • Dynamically go to import to introduce, don't import if you don't need it

insert image description here
insert image description here

Summarize

insert image description here
insert image description here

Guess you like

Origin blog.csdn.net/weixin_46426412/article/details/130857239