vue重学笔记六:vue3.2 使用手册

  vite 构建的应用,vue3.2 版本中最新的语法糖是 <script setup>,自动执行 setup 函数。组件在编译的过程中代码运行的上下文是在 setup() 函数中,所有变量和函数都直接在这里面声明,此时已无需 renturn,其中定义的变量和函数会自动导出,可在 template 模板中直接使用。

比较 vue2.x  和 <vue3.2 与 vue3.2 的区别

vue2.x

组件 JS 模块中引入的  变量 需要在 data 中重新声明 才可在 template 模板中使用,直接使用会报错。

<vue3.2

setup 的写法是:

<script>

    import { ref } from 'vue'

    export default{

   setup(){

    const count = ref(0) // 声明基本数据类型

   }

 }  

</script>

整个组件的结构在《vue3重新笔记二:安装or创建》一文中已描述,今天主要来说下生命周期及常用的使用方法。

 

生命周期

vue 3.x 中 与 vue 2.x 相比较,vue3.x 中 直接废除了 beforeCreate 和 created 函数,直接以 setup 来代替,其他的钩子函数都一样,只是在前面加上 on 

vue2.x vue3.x
beforeCreate 废除,setup
created 废除,setup
beforeMount onBeforeMount
mounted onMounted
beforeUpdate onBeforeUpdate
updated onUpdated
beforeUnmount onBeforeUnmount
unmounted onUnmounted
errorCaptured onErrorCaptured
renderTracked onRenderTracked
renderTriggered onRenderTriggered

 

vue3.2 使用手册 

 常用API

该模块下的代码都在 script-setup 中。

注意事项都在代码注释中写明,此代码已经过实践。使用方法如下:

 【import 引用】

// 从vue 中 按需加载,在开发过程中使用时,会自动添加
import { computed, nextTick, onMounted, reactive, ref, toRefs, watch } from "vue";
 
// 引用子组件与vue2.x 一样,只是不用再在 components 中声明,因 script-setup 已默认导出所有数据供 template 使用
import child from "./child.vue"; 

 

 

【props】的使用

 defineProps 在 <script setup>中自动可用,无需导入

两个方式只能任选其一。

// 方式一
defineProps({
  msg: String,
});
 
// 方式二
const props = defineProps({
  name: {
    type: String,
    default: "",
  },
});

 

 

【emit】 的使用

// 子组件
const emit = defineEmits(["update-name"]);
 
//methods 在template 中调用 changeName函数
const changeName = () => {
  emit("update-name", "uiui");  // 执行 emit  修改:updateName 更改为 update-name  原因:v-on事件监听器在DOM模板中会自动转换为小写,所以建议使用 kebab-case模式
};
 
// 父组件
<script setup>
    // 这里用例我是在 App.vue 组件中实践的,所以 引入地址有点不同,可以忽略,使用的时候会自动引入
    import { ref } from '@vue/reactivity'
    import HelloWorld from './components/HelloWorld.vue'
 
    const name = ref('123')
    const updateName = (str)=>{
        name.value = str
    }
</script>
<template>
  <HelloWorld :name="name" @update-name="updateName" />
</template>

 

 

【data】的使用

声明响应式数据。

import { ref, reactive } from "vue";
 
// 声明基本类型数据
const count = ref(0); 
count.value = 1 // 修改
 
// 声明引用类型数据
const person = reactive({
  name: "keri",
  sex: "女",
});
person.name = "anni" // 修改

 

 

【mounted 】的使用

import { onMounted } from "vue";
 
onMounted(() => {
    ...
  // console.log("props==>", props.customStr); // 123
});

 

 

【computed】的使用

import { computed } from "vue";
 
// changeCount 在 template 中直接使用
const changeCount = computed(() => {
  return count.value + 3;
});

 

 

【watch】的使用

import { reactive, watch } from "vue";
 
const person = reactive({
  name: "keri",
  sex: "女",
});
 
watch(
  () => person.sex,
  (newVal, oldVal) => {
    console.log("newVal==>", newVal);
    console.log("oldVal==>", oldVal);
  },
  {
    immediate: true,
    deep: true,
  }
);

 

 

【nextTick】的使用

import { reactive, nextTick} from "vue";
 
const person = reactive({
  name: "keri",
  sex: "女",
});
 
nextTick(()=>{
  person.name = '小红'
})

 

 

【methods】的使用

import { reactive} from "vue";
 
const person = reactive({
  name: "keri",
  sex: "女",
});
 
// methods
const changePerson = (val) => {
  person.sex = val ? val : '男'
};

 

 

【refs】的使用

vue2.x & <vue 3.2 中子组件的数据都是默认隐式暴露给父组件,但在 script-setup模式下,
所有数据只是默认 return 给 template 使用,不会暴露到组件外,
所以父组件无法直接通过挂载 refs 获取子组件的数据,此时就需要子组件暴露出数据,父组件才能拿到。

*注意:

这个位置一定要非常注意,必须要放在暴露出去数据或函数的后面,否则就会报错,
提示:Uncaught ReferenceError: Cannot access 'changePerson' before initialization
// 子组件 暴露数据
defineExpose({
  ...toRefs(person),
  changePerson
})

 

// 父组件
<script setup>
    // 这里用例我是在 App.vue 组件中实践的,所以 引入地址有点不同,可以忽略,使用的时候会自动引入
    import { ref } from '@vue/reactivity'
    import { onMounted } from '@vue/runtime-core'
    import HelloWorld from './components/HelloWorld.vue'
 
    // 这个变量名 必须和 ref 命名的名字一样,要不然也会报错
    const helloWD = ref('helloWD') 
 
    onMounted(()=>{
        helloWD.value.changePerson('sss')
    })
</script>
 
<template>
  <HelloWorld ref="helloWD" :name="name" @update-name="updateName" />
</template>

 

【defineAsyncComponent】的使用

从上文中可以看出,引入组件都是直接 import 引入,但是由于vue 本身是一个单页面应用,这种引入方式会将所有的 js 打包成一个整体,如果项目很小只有几个页面,不会有什么问题,但是如果项目很大,全部采用同步载入组件,会导致一个 JS 文件很大,页面加载时长时间处于空白状态。这时候异步加载 defineAsyncComponent 的优势就体现了。

*注意:项目只有几个文件,不建议使用该功能。

defineAsyncComponent :创建一个只有在需要时才会加载的异步组件。

// 简单用法
import { defineAsyncComponent } from "vue";
const Child = defineAsyncComponent(() => import('./child.vue'))

<template>
    <child/>
<template>


// 高阶用法
import { defineAsyncComponent } from "vue";
const AsyncComp = defineAsyncComponent({
  // 工厂函数
  loader: () => import('./Foo.vue')
  // 加载异步组件时要使用的组件
  loadingComponent: LoadingComponent,
  // 加载失败时要使用的组件
  errorComponent: ErrorComponent,
  // 在显示 loadingComponent 之前的延迟 | 默认值:200(单位 ms)
  delay: 200,
  // 如果提供了 timeout ,并且加载组件的时间超过了设定值,将显示错误组件
  // 默认值:Infinity(即永不超时,单位 ms)
  timeout: 3000,
  // 定义组件是否可挂起 | 默认值:true
  suspensible: false,
  /**
   *
   * @param {*} error 错误信息对象
   * @param {*} retry 一个函数,用于指示当 promise 加载器 reject 时,加载器是否应该重试
   * @param {*} fail  一个函数,指示加载程序结束退出
   * @param {*} attempts 允许的最大重试次数
   */
  onError(error, retry, fail, attempts) {
    if (error.message.match(/fetch/) && attempts <= 3) {
      // 请求发生错误时重试,最多可尝试 3 次
      retry()
    } else {
      // 注意,retry/fail 就像 promise 的 resolve/reject 一样:
      // 必须调用其中一个才能继续错误处理。
      fail()
    }
  }
})

 

【slot】的使用

// 常规用法
// 子组件  foot.vue
<template>
    <div>11111111</div>
    <slot/>
    <div>33333333</div>
</template>

// 父组件
<script setup>
    import Foot from './foot.vue'
</script>

<template>
    <div>......</div>
    
    <foot>
        自定义模板内容,会插入子组件中
    </foot>
</template>


// 默认值用法
// 子组件
<template>
    <div>11111111</div>
    <slot>默认模板/值</slot>
    <div>33333333</div>
</template>

// 父组件
<script setup>
    import Foot from './foot.vue'
</script>
<template>
    ……
    <foot>
        // 无内容,则会自动渲染默认组件/值
        // 若有内容,则会替换默认组件/值
    </foot>
</template>

 

 

 

 

emits  定义自定义事件

 

posted on 2022-06-15 15:40  bala001  阅读(4081)  评论(0编辑  收藏  举报

导航