一.Vue3.0生命周期对照表
image.png二. 在setup中使用provide 和 inject
事实上之前还学过的Provide和Inject,Composition API也可以替代之前的 Provide 和 Inject 的选项。
image.png二.一.在父组件/爷爷组建中使用provide
<template>
<div>
<h1>我是父组件</h1>
<hr>
<Son />
</div>
</template>
<script>
// 1.引入vue 内置的provide函数
import { provide } from "vue";
import Son from "./Son.vue"
export default {
name:"fatherCom",
components:{
Son
},
setup() {
const name = "huzhenchu";
let counter = 100;
// 2. 使用的provide函数的他有两个参数: 参数一key, 参数二: 父组件中定义的数据名称
provide("name",name)
provide("counter",counter)
},
};
</script>
<style>
</style>
二.二 在子组件/孙子组件使用inject
<template>
<div>
<h1>从父组件/爷爷组件使用provide传递过来的数据:{{ name }}</h1>
</div>
</template>
<script>
// 1. 父组件/爷爷组件中使用provide传值,然后这边子组件/孙子组件使用inject来接收
import { inject } from "vue";
export default {
name: "SonCom",
setup() {
// 2.取值
const name = inject("name");
return {
name,
};
},
};
</script>
<style>
</style>
实际截图
image.png总结: Provide 和 inject 这两个函数传值和接收值的话:
第一,如果使用的普通的ES6 定义的数据那么他不是响应式的,
第二:如果使用ref/reactive定义的数据的话,他就是响应式了
image.png
三. setup 书写计数器demo和逻辑抽离
三.一.在setup中直接写业务逻辑
<template>
<div>
<h1>当前计数:{{ counter }}</h1>
<h1>当前计数*2:{{doubleCounter}}</h1>
<button @click="add">+1</button>
<button @click="jian">-1</button>
</div>
</template>
<script>
import { computed, ref } from "vue";
export default {
setup() {
let counter = ref(0);
const doubleCounter = computed(() => counter.value * 2);
const add = () => counter.value++;
const jian = () => counter.value--;
return {
counter,
doubleCounter,
add,
jian,
};
},
};
</script>
<style>
</style>
实际截图
image.png三.二.在setup中数据抽离的写法:
App-vue3.0hook抽取.vue
<template>
<div>
<h1>当前计数:{{ counter }}</h1>
<h1>当前计数*2:{{ doubleCounter }}</h1>
<button @click="add">+1</button>
<button @click="jian">-1</button>
</div>
</template>
<script>
import userCounter from "./hooks/useCounter.js";
export default {
setup() {
const { counter, doubleCounter, add, jian } = userCounter();
return {
counter,
doubleCounter,
add,
jian,
};
},
};
</script>
<style>
</style>
useCounter.js
import { computed, ref } from "vue";
export default function() {
let counter = ref(0);
const doubleCounter = computed(() => counter.value * 2);
const add = () => counter.value++;
const jian = () => counter.value--;
return {
counter,
doubleCounter,
add,
jian,
};
}
实际截图
image.png三.三.或者直接结构这个函数也是可以的
image.png四. useTitle的使用:
需求我想修改如下图文字该怎么办呢?
image.png
四.一 实现方式一:
image.png四.二实现方式二:(封装一个hook实现)
image.png五. Vue 3.0 滚动 实现在浏览器的右下角永远实现scrollX scrollY的坐标值
实现方式一:(直接在setup函数中实现)
image.png实现方式二:(抽离代码出去在hook中书写):
image.png六. 实现浏览器鼠标经过坐标值
实现方式一:(直接在setup函数中实现)
鼠标在浏览器中移动时,scrollX scrollY 显示对应的值
image.png
实现方式二:(抽离代码出去在hook中书写):
image.png六.获取或者存储回话的Hooks
image.png七. setup顶层编写方式
什么意思呢? 就是说不需要 setup函数的包裹,然后直接像写原生JS那种写代码,怎么做到那种呢?
image.png
七.一.setup顶层编写方式--导入组件
image.png七.二.setup顶层编写方式--在父组件传值给子组件的使用
image.png七.三 setup顶层编写方式--在子组件传给父组件的事件
image.png八.自定义指令的使用:
1. 在Vue中,代码的复用和抽象主要还是通过组件;
-- 通常在某些情况下,需要对DOM元素进行底层操作,这个时候就会用到自定义指令;
2. 自定义指令分为两种:
-- 自定义局部指令:组件中通过 directives 选项,只能在当前组件中使用;
-- 自定义全局指令:app的 directive 方法,可以在任意组件中被使用;
PS: 需求:我想实现当某个元素挂载完成后可以自定获取焦点(当页面加载完,input自动获取焦点)
实现方式一:
<template>
<div>
<input type="text" ref="input" />
</div>
</template>
<script>
import { onMounted, ref } from "vue";
export default {
setup() {
const input = ref(null);
onMounted(() => {
console.log(input);
console.log(input.value);
input.value.focus()
});
return {
input,
};
},
};
</script>
<style>
</style>
实际截图:
image.png实现方式二:局部自定义指令
<template>
<div>
<input type="text" v-focus />
</div>
</template>
<script>
export default {
directives: {
focus: {
/**
* 这个生命周期是当组件挂载到界面的时候,会执行的生命周期:
* -- 当挂载到页面的时候 focus中的mounted函数中就会对标签元素进行回调了,就会有四个参数:
* -- 参数一: el
* -- 参数二: bindings
* -- 参数三: vnode 虚拟节点
* -- 参数四: preVnode 前一次的vnode
*
* **/
mounted(el,bindings,vnode,preVnode) {
console.log("focus mounted",el);
console.log("focus mounted",bindings);
console.log("focus mounted",vnode);
console.log("focus mounted",preVnode);
el.focus()
},
},
},
};
</script>
<style>
</style>
实际截图
image.png实现方式三:全局自定义指令
在全局挂载:
import { createApp } from "vue";
import App from "./App.vue";
const app = createApp(App);
/**
* 全局自定义指令:
* -- 参数一: 自定义组件的名称
* -- 参数二: 对应的是一个对象
*
* **/
app.directive("focus", {
/**
* 这个生命周期是当组件挂载到界面的时候,会执行的生命周期:
* -- 当挂载到页面的时候 focus中的mounted函数中就会对标签元素进行回调了,就会有四个参数:
* -- 参数一: el
* -- 参数二: bindings
* -- 参数三: vnode 虚拟节点
* -- 参数四: preVnode 前一次的vnode
*
* **/
mounted(el, bindings, vnode, preVnode) {
console.log("focus mounted", el);
console.log("focus mounted", bindings);
console.log("focus mounted", vnode);
console.log("focus mounted", preVnode);
el.focus();
},
});
app.mount("#app");
实际截图
image.png八.一.指令的生命周期
一个指令定义的对象,Vue提供了如下的几个钩子函数:
-- created:在绑定元素的 attribute 或事件监听器被应用之前调用;
-- beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用;
-- mounted:在绑定元素的父组件被挂载后调用;
-- beforeUpdate:在更新包含组件的 VNode 之前调用;
-- updated:在包含组件的 VNode 及其子组件的 VNode 更新后调用;
-- beforeUnmount:在卸载绑定元素的父组件之前调用;
-- unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次;
<template>
<div>
<h2 @click="changeCounter">当前计数:{{ counter }}</h2>
<button v-if="counter < 102" v-hzc @click="changeCounter">+1</button>
</div>
</template>
<script>
import { ref } from "vue";
export default {
// 局部指令
directives: {
// PS: 在我们的每个生命周期回调函数中都会有四个参数: 参数一: el 参数二: bindings,参数三: vnode 虚拟节点 参数四: preVnode 前一次的vnode
hzc: {
created(el,bindings,vnode,preVnode) {
console.log("hzc created");
},
beforeMount(el,bindings,vnode,preVnode) {
console.log("hzc beforeMount");
},
mounted(el,bindings,vnode,preVnode) {
console.log("hzc mounted");
},
beforeUpdate(el,bindings,vnode,preVnode) {
console.log("hzc beforeUpdate");
},
updated(el,bindings,vnode,preVnode) {
console.log("hzc updated");
},
beforeUnmount(el,bindings,vnode,preVnode) {
console.log("hzc beforeUnmount");
},
unmount(el,bindings,vnode,preVnode) {
console.log("hzc unmount");
},
},
},
setup() {
let counter = ref(100);
const changeCounter = () => {
counter.value++;
};
return {
counter,
changeCounter,
};
},
};
</script>
<style>
</style>
实际截图
image.png八.三. 指令的参数
<template>
<div>
<!-- 1. v-hzc.aaa.bbb 这些aaa.bbb是修饰符
v-hzc.aaa.bbb="'coderhzc'":这个值可以在下面的created回调函数的第二个参数中获取到 -->
<button v-hzc.aaa.bbb="'coderhzc'" @click="add">
当前计数: {{ counter }}
</button>
</div>
</template>
<script>
import { ref } from "vue";
export default {
directives: {
hzc: {
created(el, bindings, vnode, preVnode) {
console.log(el);
console.log(bindings);
console.log(vnode);
console.log(preVnode);
console.log(bindings.value);
},
},
},
setup() {
const counter = ref(100);
const add = () => {
counter.value++;
};
return {
counter,
add,
};
},
};
</script>
<style>
</style>
实际截图
image.png八.四. 指令的修饰符
image.png八.五.自定义指令的业务场景
如何在vue项目中去使用全局自定义组件的使用呢?一下步骤是详细的步骤:
image.png
八.六自定义指令的业务场景
假如格式不想使用上面的那样的话,可以让用户传递一个格式来展示
image.png
九.认识Teleport
在Vue 项目中一般是挂载到#app上面的,但是我现在不想挂载到#app上面 我想单独的挂载到一个组件上面,此时就可以使用Teleport内置组件了,,类似于react的Portals;
Teleport它有两个属性:
-- to:指定将其中的内容移动到的目标元素,可以使用选择器;
-- disabled:是否禁用 teleport 的功能;
十.认识Vue插件
通常我们向Vue全局添加一些功能时,会采用插件的模式,它有两种编写方式:
-- 对象类型:一个对象,但是必须包含一个 install 的函数,该函数会在安装插件时执行;
-- 函数类型:一个function,这个函数会在安装插件时自动执行;
插件可以完成的功能没有限制,比如下面的几种都是可以的:
-- 添加全局方法或者 property,通过把它们添加到 config.globalProperties 上实现;
-- 添加全局资源:指令/过滤器/过渡等;
-- 通过全局 mixin 来添加一些组件选项;
-- 一个库,提供自己的 API,同时提供上面提到的一个或多个功能;
网友评论