Vue3.0 组合API

166 阅读4分钟

vue3.0 项目创建

使用vue-cli创建

1.查看@vue/cli的版本,确保@vue/cli版本在4.5.0以上
vue --version
2.安装或者升级你的@vue-cli
3.创建
vue create vueproject
4.启动
cd vueproject
npm run serve

使用vite创建

vite要求Node.js版本在16.0以上

npm init vite hello-vue3 -- --template vue //生成模板页面
npm init vite my-vue-app //可以选择是Vue还是React以及选择JS语言还是TS语言
启动项目:npm run dev

hello-vue3和my-vue-app是我们的项目名称,可以随意进行修改,template vue是创建一个vue模板。

  • vite是新一代的前端工具
  • 优势如下:
    • 开发环境中,无需打包,可快速的冷启动
    • 轻量快速的热加载

setup

setup的设计是为了使用组合式API,组合API的入口点就是setup函数,组件中所有用到的数据、方法等,均要配置在setup中。

  • setup函数有两种返回值
    • 1.若返回一个对象,则对象中的数据、方法、在模板中均可直接使用
    • 2.若返回一个渲染函数,则可以自定义渲染内容
// 返回一个对象
<template>
  <div>
    <h1>{{title}}---{{a}}</h1>
    <p>{{msg}}</p>
    <button @click="fn">打印this当前组件</button>
    <button @click="fm">改变响应式数据</button>
  </div>
</template>

<script>
// 引入ref工具,setup函数内部的变量可以设计为响应式数据,就必须使用官方的hook
import { ref } from "vue"
export default {
  setup() {
    let a=13;
    let msg=ref('响应式数据');
    function fn(){
      console.log(this);
    }
    let fm=()=>{
      msg.value=msg.value+'已经改变了';
    }
    return {title:'App组件首页',fn,a,msg,fm}
  }
}
</script>

<style lang="scss">

</style>
  • vue3中setup函数的理解
      1. setup函数返回的对象的成员可以在模板中使用也可以在组件的API中使用,但是这个函数中不能使用组件API中的东西。
      1. setup函数中可以声明标识符(变量和函数)然后返回出去供组件使用。这个函数内部的变量和函数是局部的
      1. setup函数内部的变量不是响应式的,setup在组件加载期间只会运行1次,所以这个函数中的返回的对象中的数据不是响应式的,模板标签只会取第1次运行的变量的值,后面改了数据页面不会更新
      1. setup函数内部的变量可以设计为响应式数据,就必须使用官方的hook,也就是ref和reactive等工具
      1. 这个函数内部可以使用组件的所有属性和功能,data,methods,computed,watch和生命周期函数等
      1. 当setup返回的对象中的数据和data中的数据同名了,setup优先级更高
      1. 这个函数内部不要使用this来操作组件数据,setup位于created 和beforeCreated之前,用于代替created 和beforeCreated,但是在setup函数里不能访问到this。
      1. setup函数可以设计成 script标签中写这个同名单词的属性 然后使整个标签环境都为setup函数环境,就可以不用将所有的数据用对象返回(脚手架实现的一个语法糖)

<script setup>
import { ref,reactive } from "vue"
import son from './components/Son.vue'
  let a=13;
  let title='Tara';
  let obj=ref({age:33,name:'hyomin'});
  let arr=ref([{name:'jzx',age:26}]);
  let fg=()=>{
    obj.value={age:33,name:'jessica jung'}
    arr.value[0].age=18;
  };
  let obj2=reactive({title:'with love J',singer:{name:'jessica',son:['小除号']},music:['fly']});
  let fm=()=>{
    obj2.singer.son[0]='BLANC&ECLARE'
  }
  
</script>

<template>
  <div>
    <h1>{{title}}---{{a}}</h1>
    <p>{{obj.name}}----{{obj.age}}</p>
    <p>{{arr[0].name}}------{{arr[0].age}}</p>
    <p>{{obj2.title}}---{{obj2.music[0]}}</p>
    <p>{{obj2.singer.name}}----{{obj2.singer.son[0]}}</p>
    <button @click='fg'>修改人物</button>
    <button @click='fm'>小除号</button>
    <son></son>
  </div>
</template>

<style scoped>

</style>

ps:1.setup不能是一个async函数,因为返回值不再是return的对象,而是Promise,模板看不到return对象中的属性。

2.尽量不要和Vue2.x配置混用,Vue2.x配置(data,methods,computed等)中可以访问setup中的属性,方法。但在setup中不能访问到Vue2.x配置(data,methods,computed等)

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

ref函数

  • ref函数作用:定义一个响应式的数据
  • 语法:let xxx = ref("value")
    • 创建一个包含响应式的数据的引用对象(reference对象)
    • js中setup函数操作数据:xxx.value
    • 模板中读取数据不需要.value,直接<div>{{xxx}}</div>
  • 注意
    • 接收的数据类型可以是基本数据类型也可以是引用数据类型
    • 基本类型的数据:响应式依然是靠Object.defineProperty()的get和set完成的
    • 对象类型的数据:内部借用了Vue3.0的一个新的函数----reactive函数

ref响应式设计就是它监听了value的改变,劫持value属性的setter和getter

ref一般用于基本数据或者引用数据嵌套层级不深的数据(深层级嵌套的引用数据需要一层一层遍历劫持其数据)

<script setup>
import { ref,reactive } from "vue"
  let a=13;
  let title='Tara';
  let obj=ref({age:33,name:'hyomin'});
  let arr=ref([{name:'jzx',age:26}]);
  // arr不是数组,arr是ref返回的引用对象(reference对象)
  let fg=()=>{
    obj.value={age:33,name:'jessica jung'}
    arr.value[0].age=18;
  };
</script>

<template>
  <div>
    <h1>{{title}}---{{a}}</h1>
    <p>{{obj.name}}----{{obj.age}}</p>
    <p>{{arr[0].name}}------{{arr[0].age}}</p>
    <p>{{obj2.title}}---{{obj2.music[0]}}</p>
    <p>{{obj2.singer.name}}----{{obj2.singer.son[0]}}</p>
    <button @click='fg'>修改人物</button>
  </div>
</template>

<style scoped>

reactive函数

  • 作用:定义一个对象类型的响应式数据
  • 语法:let xxx = reactive(被代理的对象),],接收一个对象(或数组),返回一个代理器对象(proxy对象)
  • reactive定义的响应式数据是深层次嵌套的引用数据
  • 内部基于ES6的Proxy实现,通过代理对象内部的数据都是响应式的
  • js和模板都不需要.value
<script setup>
import { ref,reactive } from "vue"
import son from './components/Son.vue'
  let a=13;
  let title='Tara';
  let obj2=reactive({title:'with love J',singer:{name:'jessica',son:['小除号']},music:['fly']});
  // obj2是 reactive(被代理的数据对象)返回的一个代理器对象(proxy对象)
  // reactive也是响应式设计和ref一样,但是底层采用的ES6的Proxy代理了整个引用数据,实现响应式设计
  let fm=()=>{
    obj2.singer.son[0]='BLANC&ECLARE'
  }
  
</script>

<template>
  <div>
    <h1>{{title}}---{{a}}</h1>
    <p>{{obj2.title}}---{{obj2.music[0]}}</p>
    <p>{{obj2.singer.name}}----{{obj2.singer.son[0]}}</p>
    <button @click='fm'>小除号</button>
  </div>
</template>

<style scoped>

</style>

reactive也是响应式设计和ref一样,但是底层采用的ES6的Proxy代理了整个引用数据,实现响应式设计

Vue3.0中的响应式原理

  • vue2.0的响应式实现原理

    • 对象类型:通过Object.definedProperty()对属性的读取、修改进行拦截(数据劫持)
    • 数组类型:通过重写更新数据的一系列方法来实现拦截。(对数组的方法进行了包裹)
  • 存在问题:

    • 新增属性,删除属性都不会刷新界面
    • 直接通过下标修改数组,界面不会自动更新
  • vue3.0的响应式实现原理

    • 通过Proxy(代理):拦截对象中任意属性的变化,包括:属性的读写,属性的添加,属性的删除等
    • 通过Reflect(反射):对被代理对象的属性进行操作