简记Vue3(三)—— ref、props、生命周期、hooks

个人简介

👀个人主页: 前端杂货铺

🙋‍♂️学习方向: 主攻前端方向,正逐渐往全干发展

📃个人状态: 研发工程师,现效力于中国工业软件事业

🚀人生格言: 积跬步至千里,积小流成江海

🥇推荐学习:🍍前端面试宝典 🎨100个小功能 🍉Vue2 🍋Vue3 🍓Vue2/3项目实战 🥝Node.js实战 🍒Three.js

🌕个人推广:每篇文章最下方都有加入方式,旨在交流学习&资源分享,快加入进来吧

文章目录

前言

重拾 Vue3,查缺补漏、巩固基础。

ref

作用:用于注册模板引用。

  • 用在普通 DOM 标签上,获取的是 DOM 节点
  • 用在组件标签上,获取的是组件实例对象

App.vue

java 复制代码
<template>
  <h2 ref="title">你好</h2>
  <button @click="showLog">App 测试</button>
  <Person ref="ren"/>
</template>

<script lang="ts" setup>
  import { ref } from 'vue'
  import Person from "./components/Person.vue";

  const title = ref();

  const ren = ref();

  function showLog() {
    console.log(title.value)
    console.log(ren.value)
  }
</script>

Person.vue

java 复制代码
<template>
  <div class="person">
    <h2 ref="title">山东</h2>
    <button @click="showLog">child 输出h2</button>
  </div>
</template>

<script lang="ts" setup>
  import { ref } from "vue"

  const title = ref();

  const a = ref(0);
  const b = ref(1);
  const c = ref(2);

  function showLog() {
    console.log(title.value);
  }

  // 仅暴露给父组件 a 和 b
  defineExpose({ a, b });
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}

button {
  margin: 0 5px;
}
</style>

props

使用 props 可以实现 父组件向子组件传递 数据。

index.ts(定义规则)

java 复制代码
// person 接口
export interface PersonInter {
    id: string,
    name: string,
    age: number
}

// export type Persons = Array<PersonInter>
export type Persons = PersonInter[]

App.vue(父组件)

java 复制代码
<template>
  <Person :list="personList" />
</template>

<script lang="ts" setup>
  import Person from "./components/Person.vue";
  import { reactive } from 'vue';
  import { type Persons } from '@/types';

  const personList = reactive<Persons>([
    { id: '1', name: '张三', age: 20 },
    { id: '2', name: '李四', age: 22 },
    { id: '3', name: '王五', age: 18 }
  ])
</script>

Person.vue(子组件)

java 复制代码
<template>
  <div class="person">
    <ul v-for="person in list" :key="person.id">
      <li>{{ person.name }} -- {{ person.age }}</li>
    </ul>
  </div>
</template>

<script lang="ts" setup>
  import { defineProps, withDefaults } from "vue";
  import { type Persons } from '@/types';

  // 只接收 list
  // defineProps(['list']);

  // 接收 list + 限制类型
  // defineProps<{ list: Persons }>();

  // 接收 list + 限制类型 + 限制必要性 + 指定默认值
  withDefaults(defineProps<{ list?: Persons }>(), {
    list: () => [{id: '001', name: 'zhang', age: 20}]
  })
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}

button {
  margin: 0 5px;
}
</style>

生命周期

  • 创建阶段:setup
  • 挂载阶段:onBeforeMount、onMounted
  • 更新阶段:onBeforeUpate、onUpdated
  • 卸载阶段:onBeforeUnmount、onUnmounted

常用钩子:onMounted(挂载完毕)、onUpdated(更新完毕)、onBeforeUnmount(卸载之前)

App.vue(父组件)

java 复制代码
<template>
  <div class="app">
    <Person v-if=isShow />
    <button @click="unMounted">卸载子组件</button>
  </div>
</template>

<script lang="ts" setup>
  import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref } from 'vue';
  import Person from './components/Person.vue';

  let isShow = ref(true);

  function unMounted() {
    isShow.value = false;
  }

  console.log('父--创建');

  onBeforeMount(() => {
    console.log('父--挂载前');
  }),

  onMounted(() => {
    console.log('父--挂载完毕');
  })

  onBeforeUpdate(() => {
    console.log('父--更新前');
  })

  onUpdated(() => {
    console.log('父--更新完毕');
  })

  onBeforeUnmount(() => {
    console.log('父--卸载前');
  })

  onUnmounted(() => {
    console.log('父--卸载完毕');
  })
</script>

<style scoped>
.app {
  background-color: orange;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}

button {
  margin: 10px 5px;
}
</style>

Person.vue(子组件)

java 复制代码
<template>
  <div class="person">
    {{ sum }}
    <button @click="add">求和</button>
  </div>
</template>

<script lang="ts" setup>
  import { onBeforeMount, onBeforeUnmount, onBeforeUpdate, onMounted, onUnmounted, onUpdated, ref } from 'vue';
  let sum = ref(0);

  function add() {
    sum.value += 1;
  }

  console.log('子--创建');

  onBeforeMount(() => {
    console.log('子--挂载前');
  }),

  onMounted(() => {
    console.log('子--挂载完毕');
  })

  onBeforeUpdate(() => {
    console.log('子--更新前');
  })

  onUpdated(() => {
    console.log('子--更新完毕');
  })

  onBeforeUnmount(() => {
    console.log('子--卸载前');
  })

  onUnmounted(() => {
    console.log('子--卸载完毕');
  })
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}

button {
  margin: 0 5px;
}
</style>

hooks

hooks 主要用于在函数式组件中管理组件的状态和生命周期,下面我们进行一个示例。

Person.vue

javascript 复制代码
<template>
  <div class="person">
    <h2>当前求和为:{{ sum }}</h2>
    <h2>求和放大十倍:{{ bigSum }}</h2>
    <button @click="add">+1</button>
  </div>
</template>

<script lang="ts" setup>
import { reactive, watch } from "vue";
import useSum from "../hooks/useSum";

const { sum, add, bigSum } = useSum();
</script>

<style scoped>
.person {
  background-color: skyblue;
  box-shadow: 0 0 10px;
  border-radius: 10px;
  padding: 20px;
}
button {
  margin: 0 5px;
}
</style>

useSum.ts

javascript 复制代码
import { computed, onMounted, ref } from "vue";

export default function () {
  let sum = ref(0);

  function add() {
    sum.value += 1;
  }

  onMounted(() => {
    add();
  });

  let bigSum = computed(() => {
    return sum.value * 10;
  });

  return { sum, add, bigSum };
}

参考资料:

https://www.bilibili.com/video/BV1Za4y1r7KE?spm_id_from=333.788.player.switch\&vd_source=f839085517d2b7548b2939bfe214d466\&p=29---


相关推荐
HED19 分钟前
VUE项目发版后用户访问的仍然是旧页面?原因和解决方案都在这啦!
前端·vue.js
清风细雨_林木木1 小时前
Vue开发网站会有“#”原因是前端路由使用了 Hash 模式
前端·vue.js·哈希算法
局外人LZ2 小时前
前端项目搭建集锦:vite、vue、react、antd、vant、ts、sass、eslint、prettier、浏览器扩展,开箱即用,附带项目搭建教程
前端·vue.js·react.js
宝拉不想努力了2 小时前
vue element使用el-table时,切换tab,table表格列项发生错位问题
前端·vue.js·elementui
神仙别闹4 小时前
基于VUE+Node.JS实现(Web)学生组队网站
前端·vue.js·node.js
HuaHua的世界6 小时前
说说 Vue 中 CSS scoped 的原理?
css·vue.js
H5开发新纪元6 小时前
Vue 项目中 Loading 状态管理及页面切换 Bug 分析
前端·vue.js
icefiresong248 小时前
如何让 Vue 组件自动清理 EventBus 监听器?告别内存泄漏!
vue.js
tjh000110 小时前
vue3+TS 手动实现表格滚动
前端·javascript·vue.js
章若楠圈外男友10 小时前
修改了Element UI中组件的样式,打包后样式丢失
前端·vue.js