美文网首页react & vue & angular
Vue3.0 基础学习自我理解(六)

Vue3.0 基础学习自我理解(六)

作者: coderhzc | 来源:发表于2022-07-05 11:23 被阅读0次

    一.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,同时提供上面提到的一个或多个功能;

    十.一. 通过注册一个全局的plugins插件--方式一:对象注册

    实际截图

    image.png

    PS: 这种注册了以后 在全局任何页面都可以按照以上方式取值

    十.二. 通过注册一个全局的plugins插件--方式二:函数注册

    image.png

    相关文章

      网友评论

        本文标题:Vue3.0 基础学习自我理解(六)

        本文链接:https://www.haomeiwen.com/subject/avksbrtx.html