Vue Vue3中的setup、ref、reactive

文章目录

  • setup
  • ref 函数
  • reactive 函数
  • reactive对比ref
  • setup 两个注意点
    • 参数props
    • 参数context

setup

1、理解:vue3.0 中一个新的配置项,值为一个函数
2、setup 是所有 Composition API(组合API) “表演的舞台”
3、组件中所用到的:数据、方法等等,均要配置在setup
4、setup函数的两种返回值:
----①、若返回一个对象,则对象中的属性、方法,在模板中均可以直接使用(重点关注! )
----②、若返回一个渲染函数:则可以自定义渲染内容。(了解)
5、注意点:
----①尽量不要与Vue2.x配置混用
-------Vue2.x配置(data、methos、computed…)中可以访问到setup中的属性、方法。但在setup中不能访问到 Vue2.x 配置(data、methos、computed…)。如果有重名, setup优先,
----②setup不能是一个async函数,因为返回值不再是return的对象,而是promise,模板看不到return对象中的属性(后期也可以返回一个 Promise 实例,但需要 Suspense和异步组件的配合)

我们来修改上一节创建的 vue3 项目,修改 App.vue

<template>
  <h1>一个人的信息h1>
  <h3>姓名:{{ name }}h3>
  <h3>年龄:{{ age }}h3>
  <button @click="sayHello">说话button>
template>

<script>

export default {
  name: 'App',
  setup() {
    //数据
    let name = "张三"
    let age = 18

    function sayHello() {
      alert(`我叫${name},我${age}岁了`)
    }

	//返回一个对象
    return {
      name: name,
      //触发简写形式
      age,
      sayHello
    }
  }
}
script>
......

运行:
Vue Vue3中的setup、ref、reactive_第1张图片
测试下上面说的几点中 4.2 返回渲染函数的时候

<script>
import {h} from 'vue'
export default {
  name: 'App',
  setup() {
    return () => {
      return h("h1", "三里屯小学")
    }
  }
}
</script>

Vue Vue3中的setup、ref、reactive_第2张图片

ref 函数

作用:定义一个响应式的数据
语法const xxx = ref(initvalue)
。创建一个包含响应式数据的引用对象(reference对象,简称ref对象)
。JS中操作数据:xxx.value
。模板中读取数据:不需要.value,直接:

{{xxx} }

备注:
。接收的数据可以是:基本类型、也可以是对象类型
。基本类型的数据:响应式依然是靠0bject.defineProperty()getset完成的
。对象类型的数据:内部“求助”了 Vue3.0 中的一个新函数——reactive函数

Vue Vue3中的setup、ref、reactive_第3张图片

<template>
  <h1>一个人的信息h1>
  <h3>姓名:{{ name }}h3>
  <h3>年龄:{{ age }}h3>
  <h3>职业:{{ job.type }}h3>
  <h3>薪水:{{ job.salary }}h3>
  <button @click="changeInfo">修改人的信息button>
template>

<script>
import {ref} from 'vue'

export default {
  name: 'App',
  setup() {
    //数据
    let name = ref("张三")
    let age = ref(18)
    let job = ref({
      type: '前端工程师',
      salary: '30k'
    })

    function changeInfo() {
      name.value = "李四"
      age.value = 25
      job.value.type = "UI设计师"
      job.value.salary = "60k"
    }

    return {
      name,
      age,
      job,
      changeInfo
    }
  }
}
script>

被 ref 包裹的 name 变成了 refimpl 对象,可以打印看下
Vue Vue3中的setup、ref、reactive_第4张图片
RefImpl 就是引用对象实例对象,拆分成两个单词:
reference:引用
implement:实现

可以看到里边有 value,我们用鼠标点开...,值就是我们定义的值。所以在 js 中操作的时候,我们需要 .value 来取值

reactive 函数

作用:定义一个对象类型的响应式数据(基本类型不要用它,要用ref函数)
语法const 代理对象 = reactive(源对象)接收一个对象(或数组),返回一个代理对象(proxy的实例对象,简称proxy对象)
reactive定义的响应式数据是"深层次的"
内部基于 ES6 的 Proxy 实现,通过代理对象操作源对象内部数据进行操作
Vue Vue3中的setup、ref、reactive_第5张图片

<template>
  <h1>一个人的信息h1>
  <h3>职业:{{ job.type }}h3>
  <h3>薪水:{{ job.salary }}h3>
  <h3>爱好:{{ hobby }}h3>
  <h3>测试数据的值:{{ job.a.b.c }}h3>
  <button @click="changeInfo">修改人的信息button>
template>

<script>
import {reactive} from 'vue'

export default {
  name: 'App',
  setup() {
    //数据
    let job = reactive({
      type: '前端工程师',
      salary: '30k',
      a: {
        b: {
          c: 666
        }
      }
    })

    let hobby = reactive(['抽烟', '喝酒', '烫头'])
	//counts changeInfo = ()=>{...}
    function changeInfo() {
      job.type = "UI设计师"
      job.salary = "60k"
      job.a.b.c = 999
      hobby[0] = '学习'
    }

    return {
      job,
      hobby,
      changeInfo
    }
  }
}
script>

可以看到使用 reactive 后不用再使用.value来取值,同时,可以修改深层次的数据,因为我们把 a.b.c 的值改了。而且数组的值也可以改

由于不能处理基本类型数据,如果想处理上一个例子中的姓名、年龄等数据可以将数据都放到一个数组中

<template>
  <h1>一个人的信息h1>
  <h3>姓名:{{ person.name }}h3>
  <h3>年龄:{{ person.age }}h3>
  <h3>职业:{{ person.job.type }}h3>
  <h3>薪水:{{ person.job.salary }}h3>
  <h3>爱好:{{ person.hobby }}h3>
  <h3>测试数据的值:{{ person.job.a.b.c }}h3>
  <button @click="changeInfo">修改人的信息button>
template>

<script>
import {reactive} from 'vue'

export default {
  name: 'App',
  setup() {

    let person = reactive({
      name: '张三',
      age: 18,
      job: {
        type: '前端工程师',
        salary: '30k',
        a: {
          b: {
            c: 666
          }
        }
      },
      hobby: ['抽烟', '喝酒', '烫头']
    })

    function changeInfo() {
      person.name = "李四"
      person.age = 25
      person.job.type = "UI设计师"
      person.job.salary = "60k"
      person.job.a.b.c = 999
      person.hobby[0] = '学习'
    }

    return {
      person,
      changeInfo
    }
  }
}
script>

reactive对比ref

从定义数据角度对比
ref用来定义:基本类型教据
reactive用来定义:对象〔或数组)类型数据
。备注: ref也可以用来定义对象((或数组)类型数据,它内部会自动通过reactive转为代理对象

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

从使用角度对比
ref定义的数据:操作数据需要.value,读取数据时模板中直接读取不需要.value
reactive定义的数据:操f作数据与读取数据:不需要.value

setup 两个注意点

setup 执行的时机
。在beforeCreate之前执行一次,thisundefined
setup 的参数
。props:值为对象,包含:组件外部传递过来,且组件内部声明接收了的属性
。context:上下文对象
-------attrs:值为对象,包含:组件外部传递过来,但没有在 props 配置中声明的属性,相当于 this.$attrs
-------slots:收到的插槽内容,相当于this.$slots
-------emit:分发自定义事件的函数,相当于this.$cmit

参数props

我们来实际打印下,在 App 中引入 Demo 组件并传值

<template>
  <div>
    <Demo msg="hello"/>
  div>
template>

<script>
import Demo from './components/Demo'

export default {
  name: 'App',
  components: {Demo}
}
script>

Demo 组件中接收,并在 setup 中打印 props

<template>
  <h2>{{msg}}h2>
template>

<script>
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  setup(props){
    console.log(props);
  }
}
script>

Vue Vue3中的setup、ref、reactive_第6张图片

参数context

其中 setup 还能接收一个参数,我们来打印下

setup(props,context){
    console.log(context);
  }

Vue Vue3中的setup、ref、reactive_第7张图片
1、其中 attrs,如果 App 给 Demo 传值了,但没有使用 props 接收,那么值就会存在 attrs 中。跟 Vue2 中的 $attrs 的一样

2、看下 emit
我们先给 Demo 传递一个 hello 事件

<template>
  <div>
    <Demo @hello="showHello" msg="hello"/>
  div>
template>

<script>
import Demo from './components/Demo'

export default {
  name: 'App',
  components: {Demo},
  setup(){
    function showHello(value) {
      console.log(`触发hello事件,收到了参数是:${value}`);
    }
    return{
      showHello
    }
  }
}
script>

Demo 中接收

<template>
  ......
  <button @click="test">测试hello事件button>
template>

<script>
export default {
  ......
  emits:['hello'],
  setup(props,context){
    ......
    function test() {
      context.emit("hello",666)
    }

    return{
      test
    }
  }
}
script>

Vue Vue3中的setup、ref、reactive_第8张图片
3、其中slot
App 中使用插槽

<template>
  <div>
    <Demo @hello="showHello" msg="hello">
      <template v-slot:bottom>
        <span>你好span>
      template>
    Demo>
  div>
template>

Demo 中打印下 context.slots

<template>
  <h2>{{msg}}h2>
  <button @click="test">测试hello事件button>
  <slot name="bottom">slot>
template>
<script>
export default {
  ......
  setup(props,context){
    console.log(context.slots);
    ......
  }
}
script>

Vue Vue3中的setup、ref、reactive_第9张图片

你可能感兴趣的:(Vue学习笔记,vue)