Vue3.0——面试题、常用的Composition API(setup、ref函数、reactive函数、Vue3.0中的响应式原理、Vue3.0中组件的使用、计算属性 )

目录

一、常用的Composition API(组合API)

1.setup

2.ref函数

3.reactive函数

4.Vue3.0中的响应式原理 (面试题)

1)vue2.0的响应式

2)vue3.0的响应式

5.Vue3.0中组件的使用

6.计算属性 

二、面试题

1、什么是组合式和选项式?

2、什么是hook?

3、hook的代码写在哪里?

4、Vue3.0中的setup函数的理解

6、Vue3.0 和 Vue2.0响应式原理


一、常用的Composition API(组合API)

1.setup      2.ref函数    3.reactive函数     4.Vue3.0中的响应式原理 (面试题)

5.Vue3.0中组件的使用    6.计算属性    7.监听属性    8.Vue3.0生命周期

9.Teleport     10.自定义事件    11.状态驱动的动态css    12.Suspense

2.0和3.0的代码混用了,那3.0优先级更高

比如2.0的data里面写了msg,setup返回了msg,两者同名,那setup优先级更高

1.setup

- 理解:Vue3.0中一个新的配置向,值为一个函数

- setup是所有Composition API(组合API) ”表演的舞台“

- 组件中所有用到的:数据、方法等等,均要配置在setup中

- setup函数的两种返回值:

  - 若返回一个对象,则对象中的数据、方法、在模板中均可直接使用(重点)

 1、setup() 这个函数内部的变量/函数是局部的

2、这个函数的返回值,可以被当前组件的任意地方使用

3、这个函数内部不要使用this来操作组件数据

4、setup在组件加载期间只有运行一次,从创建到销毁只运行一次

setup 函数的语法糖

setup属性,会让打包工具打包时,直接帮我们把setup函数内部声明的变量/函数 return,然后组件就可以用了

<script setup>  </script>

<template>
  <div class="home">
    <h1>显示vue3.0的数据和方法</h1>
    <h2>姓名:{
   
   {name}}</h2>
    <h2>年龄:{
   
   {age}}</h2>
    <button @click="sayName()">点击测试vue3.0的方法</button>
  </div>
</template>

<script>

export default {
  setup() {
    // 现在暂时还不考虑响应式数据的问题
    // 数据 
    let name = "李国栋";
    let age = 18;

    // 方法
    let sayName = function () {
      console.log(`我的名字是${name},我的年龄是${age}`);
    }

    return {
      name, age, sayName
    }
  }

}
</script>

若返回一个渲染函数,则可以自定义渲染内容(了解)

//页面中会显示一个h1标签,标签的内容是"vue3返回渲染函数"
<script>
import {h} from 'vue'
export default {
  setup() {
    // 返回一个渲染函数
    // h相当于document.CreateElement()
    return ()=>{return h("h1","vue3返回渲染函数")}
  }
}
</script>

注意点

- 尽量不要和Vue2.x配置混用
- Vue2.x配置(data,methods,computed......)中可以访问setup中的属性,方法
- 但在setup中不能访问到Vue2.x配置(data,methods,computed......)
- 如有重名,setup优先
- setup不能是一个async函数,因为返回值不再是return的对象,而是Promise,模板看不到return对象中的属性

2.ref函数

- 作用:定义一个响应式的数据  ()
- 语法:const xxx = ref("value")

             import { ref } from "vue" 

             name.value = "名字";

存值和取值都是用  点value  ,但是页面使用就不用点value,直接写{ {name}}

ref的返回值是一个对象,然后有个属性是value


  - 创建一个包含响应式的数据的引用对象(reference对象)
  - js中操作数据:xxx.value
  - 模板中读取数据不需要.value,直接<div>{ {xxx}}</div>

可以用箭头函数,因为这里面用不到this

- 注意
  - 接收的数据类型 :可以是基本数据类型   也可以是 引用数据类型
  - 基本类型的数据:响应式依然是靠Object.defineProperty()的get和set完成的
  - 对象类型的数据:内部“求助”了Vue3.0的一个新的函数------reactive函数

ref这个响应式是怎么设计的?

就是监听了value的改变,劫持value属性的setter、getter

因此ref一般用在基本数据,或者是引用数据的嵌套层级不深的数据上

reactive也是响应式的设计,怎么设计的呢?

跟ref一样,但是底层采用的是ES6的proxy代理了整个引用数据。比起ref,它的性能更好

<template>
  <div class="home">
    <h1>显示vue3.0的数据和方法</h1>
    <h2>姓名:{
   
   {name}}</h2>
    <h2>年龄:{
   
   {age}}</h2>
    <h2>工作:{
   
   {more.job}}</h2>
    <h2>薪资:{
   
   {more.salary}}</h2>
    <button @click="changeMsg()">点击测试vue3.0的基本数据</button>
    <button @click="changeMore()">点击测试vue3.0的引用数据</button>
  </div>
</template>
<script>
import { ref } from "vue"  //3.0才有这个
export default {
  setup() {
    // 1.基本数据类型
    let name = ref("李国栋");
    let age = ref(18);
      
    let more = ref({
      job: "前端开发工程师",
      salary: "10k"
    })
    // 方法
    let changeMsg = function () {
      name.value = "余梦佳";  //点击它,就可以改变name,同时页面的{
   
   {name}}也改变了,这就是因为ref的作用,响应式
      age.value = 19;
      console.log(name, age);
    }
    let changeMore = function () {
      more.value.salary = "20K";
      console.log(more.value);
    }
    let look=()=>{console.log(name.value)}  //可以用箭头函数,因为这里面用不到this
    return {
      name, age, changeMsg, more, changeMore
    }
  }

}
</script>

3.reactive函数

- 作用:定义一个对象类型的响应式数据   (基本数据类型别用它,用ref函数)
- 语法:const 代理一个对象 = reactive(被代理的对象)   接收一个对象(或数组),返回一个代理器对象(proxy对象)
- reactive定义的响应式数据是“深层次的”
- 内部基于ES6的Proxy实现,通过代理对象内部的数据都是响应式的

它就不用value了,引用数据用reactive更好,它底层不是劫持,而是代理

<template>
  <div class="home">
    <h1>显示vue3.0的数据和方法</h1>
    <h2>姓名:{
   
   {name}}</h2>
    <h2>年龄:{
   
   {age}}</h2>
    <h2>工作:{
   
   {more.job}}</h2>
    <h2>薪资:{
   
   {more.salary}}</h2>
    <h2>c:{
   
   {more.a.b.c}}</h2>
    <button @click="changeMsg()">点击测试vue3.0的基本数据</button>
    <button @click="changeMore()">点击测试vue3.0的引用数据</button>
  </div>
</template>

<script>
//1.引入
import {ref,reactive} from "vue"
export default {
  setup() {
    let name = ref("李国栋");
    let age = ref(18);
    let more = reactive({
      job: "前端开发工程师",
      salary: "10k",
      a:{
        b:{
          c:"ccccccccccccc"
        }
      }
    })

    // 方法
    let changeMsg = function () {
      name.value = "余梦佳";
      age.value = 19;
      console.log(name, age);
    }

	//2.修改 
    let changeMore = function () {
      more.salary = "20K";
      more.a.b.c = "55555555555555555555"
    }

    return {
      name, age, changeMsg, more, changeMore
    }
  }

}
</script>

4.Vue3.0中的响应式原理 (面试题)

1)vue2.0的响应式

  • 实现原理

    • 对象类型:通过Object.definedProperty()对属性的读取、修改进行拦截(数据劫持)

    • 数组类型:通过重写更新数据的一系列方法来实现拦截。(对数组的方法进行了包裹)

      Object.defineProperty(data,"count",{
          get(){},
          set(){}
      })

    存在问题:

    • 新增属性,删除属性都不会刷新界面

    • 直接通过下标修改数组,界面不会自动更新 (可以用$set来刷新页面)

   let person = {
            name:"李国栋",
            age:18
        }

        let p = {};

        Object.defineProperty(p,"name",{
            get(){
                console.log("有人读取数据时调用");
                return person.name
            },

            set(value){
                console.log("有人修改了数据,我要去更新页面");
                person.name = value
            }
        })

2)vue3.0的响应式

- 实现原理
  - 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性的读写,属性的添加,属性的删除等

  - 通过Reflect(反射):对被代理对象的属性进行操作
  - MDN文档中描述的Proxy与Reflect:

 - Proxy:https://developer.mozilla.org/zhCN/docs/Web/JavaScript/Reference/Global_Objects/Proxy
 - Reflect:

https://developer.mozilla.org/zhCN/docs/Web/JavaScript/Reference/Global_Objects/Reflect

   let person = {
            name:"李国栋",
            age:18
        }

        let p = new Proxy(person,{
            // 读取
            get(target,proname){
                // target表示原对象  proname表示对象名
                console.log("有人读取了person上的属性",target);
                return target[proname]
            },
            // 修改或者增加
            set(target,proname,value){
                console.log("有人修改了person上的属性,我要去更新了");
                target[proname] = value
            },
            // 删除
            deleteProperty(target,proname){
                console.log("有人删除了person上面的属性,我要去调用了");
                return delete target[proname]
            },
            
        });

5.Vue3.0中组件的使用

App.vue

<script setup>
//Vue3.0中组件的使用案例
import Box from "./Box.vue"
</script>
<template>
	<div>
		<Box></Box>
	</div>
</template>

Box.vue

<script setup>
import {  reactive } from "vue";
let arr = reactive([{ name: "karen" }, { age: [1, 2, 3, { name: "jack" }] }]);
let fm=function(){
	console.log(obj.age[2].age[1])
	obj.age[2].age[1]=24
}
</script>
<template>
  <div>
	<h1>{
   
   {obj.age[2].age[1]}}</h1>
	<button @click="fm">点击修改obj</button>
  </div>
</template>

6.计算属性 

- 与vue2.x中computed配置功能一致

computed比起方法,它可以缓存上一次的结果,如果下一次关于计算的东西没有变化,那它就不会重新计算,这样就不会消耗太多性能问题

<template>
  <div class="home">
    <h1>vue2.0的计算属性--------{
   
   {total1}}</h1>

    <div v-for="(el,index) in arr2" :key="index">
      <span>{
   
   {el.title}}---</span>
      <span>{
   
   {el.price}}--</span>
      <button @click="jianshao(index)">-</button>
      <span>{
   
   {el.count}}</span>
      <button>+</button>
    </div>

    <h1>vue3.0的计算属性----------{
   
   {total2}}</h1>
  </div>
</template>

<script>

// 注意:vue2.x和vue3.x不要混用
// 1.引入
import { reactive, computed } from "vue"
export default {

  data() {
    return {
      arr: [
        {
          title: "鱼香肉丝",
          price: 10,
          count: 1
        },
        {
          title: "麻婆豆腐",
          price: 10,
          count: 2
        },
        {
          title: "米饭",
          price: 1,
          count: 3
        }
      ],
    };
  },
  computed: {
    total1() {
      return this.arr.reduce((a, b) => {
        return a + b.price * b.count
      }, 0)
    }
  },

  setup() {

    let arr2 = reactive([{ title: "鱼香肉丝", price: 18, count: 1 },
    { title: "鱼香肉丝2", price: 20, count: 2 },
    { title: "鱼香肉丝3", price: 30, count: 4 }
    ])

    // 2.使用
    let total2 = computed(() => {
      return arr2.reduce((n1, n2) => (n1 + n2.price * n2.count), 0)
    })

    // 减少
    let jianshao = function(index){
      arr2[index].count--
    }
    return { arr2, total2,jianshao }

  }

}
</script>

<script setup>
//计算属性 案例一
import { reactive,computed} from "vue";
let arr = reactive([
  { goods: "衣服", price: 120, count: 2 },
  { goods: "裙子", price: 140, count: 1 },
  { goods: "鞋子", price: 200, count: 1 },
]);
let change = () => {
  arr[1].count ++;
};
let total = computed(() => {
  return arr.reduce((n1, n2) => {
    return n1 + n2.price * n2.count;
  }, 0);
},arr); //指定当arr变了,这个函数才会触发
let add=(index)=>{
	arr[index].count++
}
function dec(index){
	arr[index].count--
}
</script>
<template>
  <div>
    <div v-for="(el,index) in arr" :key="index">
      {
   
   { el.goods }}--{
   
   { el.price }}---
	  <button @click="dec(index)">-</button>
	  <span> {
   
   { el.count }}</span>
	  <button @click="add(index)">+</button>
    </div>
	<button @click="change">点击修改count</button>
	<h4>总价:{
   
   {total}}</h4>
  </div>
</template>
<style scoped>
</style>

二、面试题

1、什么是组合式和选项式?

2、什么是hook?

3、hook的代码写在哪里?

写在Vue3.0的setup函数内部

4、Vue3.0中的setup函数的理解

1、Vue3.0中一个新的配置向,值为一个函数

2、setup是所有Composition API(组合API) ”表演的舞台“

3、组件中所有用到的:数据、方法等等,均要配置在setup中

4、 setup函数的两种返回值:

  - 若返回一个对象,则对象中的数据、方法、在模板中均可直接使用,也可以在组件的api中使用,但是这个函数中不能使用组件api中的东西(重点)

特点:

5、setup() 这个函数内部的变量/函数是局部的

6、这个函数的返回值,可以被当前组件的任意地方使用

7、这个函数内部不要使用this来操作组件数据

8、setup在组件加载期间只有运行一次,从创建到销毁只运行一次

9、setup函数可以声明一些变量/函数,然后返回出去,供组件使用

10、setup函数内部的变量可以去设计为响应式的变量,那么可以使用官方的hook,也就是ref、reactive等工具

11、setup函数可以设计成script标签中写这个同名单词的属性,然后使整个标签环境(脚手架实现)

5、Vue3中的响应式数据是怎么设计的?

ref这个响应式是怎么设计的?

就是监听了value的改变,劫持value属性的setter、getter

因此ref一般用在基本数据,或者是引用数据的嵌套层级不深的数据上

reactive也是响应式的设计,怎么设计的呢?

跟ref一样,但是底层采用的是ES6的proxy代理了整个引用数据。比起ref,它的性能更好

6、Vue3.0 和 Vue2.0响应式原理

答案在上面标题4,分别说出Vue2.0   Vue3.0即可

猜你喜欢

转载自blog.csdn.net/qq_52301431/article/details/126884264