快速掌握-vue3

是什么

vue2 的升级版, 使用 ts 重构了代码, 带来了 Composition API RFC。 类似于 react hook 的写法。

  1. ts 重构,代码可读性更强
  2. vue3.x 使用 Proxy 取代 Vue2.x 版本的 Object.defineProperty
  3. 实现了 TreeShaking (当 Javascript 项目达到一定体积时,将代码分成模块会更易于管理。但是,当这样做时,我们最终可能会导入实际上未使用的代码。Tree Shaking 是一种通过消除最终文件中未使用的代码来优化体积的方法。)
  4. 支持 hook 写法 CompositionAPI。受 ReactHook 启发
  5. 支持 jsx
  6. Vue 3 的 Template 支持多个根标签,Vue 2 不支持
  7. 对虚拟 DOM 进行了重写、对模板的编译进行了优化操作
  8. 在 Vue2.x 中具名插槽和作用域插槽分别使用 slot 和 slot-scope 来实现, 在 Vue3.0 中将 slot 和 slot-scope 进行了合并 v-slot
  9. 在 Vue 3 中对自定义指令的 API 进行了更加语义化的修改,名称和组件生命周期名称相同
  10. v-model 变更:在自定义组件上使用 v-model 时,同一组件可以同时设置多个 v-model, 开发者可以自定义 v-model 修饰符

学到什么

  1. vue3 与 vue2 的核心区别
  2. Tree-Shaking
  3. 函数 setup()
  4. 函数 ref()
  5. 函数 isRef()
  6. 函数 toRefs()
  7. 函数 reactive()
  8. 函数 computed()、watch()
  9. LifeCycle Hooks(新的生命周期)
  10. Template refs
  11. vue3 的全局配置
  12. vue3 组件模板结构
  13. 实现 自定义 Hook
  14. 组件 teleport 任意门
  15. 组件 异步组件

vue3 与 vue2 的核心区别

  1. vue3.x 将使用 Proxy 取代 Vue2.x 版本的 Object.defineProperty
  2. Object.defineProperty 只能劫持对象的属性, 而 Proxy 是直接代理对象,由于 Object.defineProperty 只能劫持对象属性,需要遍历对象的每一个属性,如果属性值也是对象,就需要递归进行深度遍历。但是 Proxy 直接代理对象,不需要遍历操作
  3. Object.defineProperty 对新增属性需要手动进行 Observe

Tree-Shaking

当 Javascript 项目达到一定体积时,将代码分成模块会更易于管理。但是,当这样做时,我们最终可能会导入实际上未使用的代码。Tree Shaking 是一种通过消除最终文件中未使用的代码来优化体积的方法。

为什么:因为 Vue 实例是作为单个对象导出的,打包器无法分辨出代码中使用了对象的哪些属性。所以,我们需要单独引用

抽离了 一部分 vue2 中的公用函数,需要单独引用。以前的全局 API 现在只能通过具名导入,这一更改会对以下 API 有影响:

  • Vue.nextTick
  • Vue.observable(用 Vue.reactive 替换)
  • Vue.version
  • Vue.compile(仅限完整版本时可用)
  • Vue.set(仅在 2.x 兼容版本中可用)
  • Vue.delete(与上同)

setup 函数

组件提供的新属性,为了使用 vue3 CompositionAPI 新特性而启用的函数,它有自己独立的生命周期

vue3 取消了 beforeCreate 、created 两个钩子函数,统一用 setup 代替

  1. props 用来接收 props 数据
  2. context 上下文对象
  3. return 返回模板中需要使用的函数
setup(props, context) {
    context.attrs
    context.slots
    context.emit

    return {

    }
  }

ref() 函数

组件提供的新特性函数

创建一个响应式的数据对象,这个对象是响应式的,只返回一个 { value: ""} 值

import { defineComponent, ref } from "vue";
export default defineComponent({
  setup() {
    const name = ref < string > "hello";
    // 在js 中获取ref 中定义的值, 需要通过value属性
    console.log(name.value);
    return {
      name,
    };
  },
});

isRef() 函数

组件提供的新特性函数

isRef() 用来判断某个值是否为 ref() 创建出来的对象

import { defineComponent, isRef, ref } from "vue";
export default defineComponent({
  setup(props, context) {
    const name: string = "vue";
    const age = ref<number>(18);
    console.log(isRef(age)); // true
    console.log(isRef(name)); // false
    return {
      age,
      name,
    };
  },
});

toRefs() 函数

组件提供的新特性函数

toRefs() 函数可以将响应式对象,转换为普通的对象。只不过,这个对象上的每个属性节点,都是 ref() 类型的响应式数据

import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
  setup(props, context) {
    let state = reactive({
      name: "hello",
    });
    const age = ref(18);
    return {
      ...toRefs(state),
      age,
    };
  },
});

reactive() 函数

组件提供的新特性函数

reactive() 函数接收一个普通对象,返回一个响应式的数据对象, 想要使用创建的响应式数据也很简单,创建出来之后,在 setup 中 return 出去,直接在 template 中调用即可

import { defineComponent, reactive, ref, toRefs } from "vue";
export default defineComponent({
  setup(props, context) {
    let state = reactive({
      name: "hello",
    });

    return state;
  },
});

computed()、watch() 函数

组件提供的新特性函数

computed() 函数 ,用来计算属性,返回的值是一个 ref 对象。

import { computed, defineComponent, ref } from "vue";
export default defineComponent({
  setup(props, context) {
    const age = ref<number>(18);

    const computedAge = computed({
      get: () => age.value + 1,
      set: (value) => age.value + value,
    });
    // 为计算属性赋值的操作,会触发 set 函数, 触发 set 函数后,age 的值会被更新
    age.value = 100;
    return {
      age,
      computedAge,
    };
  },
});

watch() 函数,用来监听属性, 当数据源变化的时候才会被执行。

import { computed, defineComponent, reactive, toRefs, watch } from "vue";
interface Person {
  name: string;
  age: number;
}
export default defineComponent({
  setup(props, context) {
    const state = reactive<Person>({ name: "vue", age: 10 });

    watch(
      [() => state.age, () => state.name],
      ([newName, newAge], [oldName, oldAge]) => {
        console.log(newName);
        console.log(newAge);

        console.log(oldName);
        console.log(oldAge);
      }
    );
    // 修改age 时会触发watch 的回调, 打印变更前后的值, 此时需要注意, 更改其中一个值, 都会执行watch的回调
    state.age = 100;
    state.name = "vue3";
    return {
      ...toRefs(state),
    };
  },
});

LifeCycle Hooks 生命周期

组件提供的新特性函数

生命周期组件中新的写法

import { set } from "lodash";
import {
  defineComponent,
  onBeforeMount,
  onBeforeUnmount,
  onBeforeUpdate,
  onErrorCaptured,
  onMounted,
  onUnmounted,
  onUpdated,
} from "vue";
export default defineComponent({
  setup(props, context) {
    onBeforeMount(() => {
      console.log("beformounted!");
    });
    onMounted(() => {
      console.log("mounted!");
    });

    onBeforeUpdate(() => {
      console.log("beforupdated!");
    });
    onUpdated(() => {
      console.log("updated!");
    });

    onBeforeUnmount(() => {
      console.log("beforunmounted!");
    });
    onUnmounted(() => {
      console.log("unmounted!");
    });

    onErrorCaptured(() => {
      console.log("errorCaptured!");
    });

    return {};
  },
});

模板 Template refs

组件提供的新特性函数

通过 refs 来回去真实 dom 元素,onMounted 中可以得到 ref 的 RefImpl 的对象, 通过.value 获取真实 dom

<template>
  <div class="mine" ref="elmRefs">
    <span>hello</span>
  </div>
</template>

<script lang="ts">
import { set } from "lodash";
import { defineComponent, onMounted, ref } from "vue";
export default defineComponent({
  setup(props, context) {
    // 获取真实dom
    const elmRefs = ref<null | HTMLElement>(null);
    onMounted(() => {
      console.log(elmRefs.value); // 得到一个 RefImpl 的对象, 通过 .value 访问到数据
    });

    return {
      elmRefs,
    };
  },
});
</script>

vue 的全局配置

Vue3 可以在组件用通过 getCurrentInstance() 来获取全局 globalProperties 中配置的信息

const app = Vue.createApp({});
app.config.globalProperties.$http = "axios";

setup( ) {
  const { ctx } = getCurrentInstance();
  ctx.$http
}

vue3 组件模板结构

<template>
  <div class="mine" ref="elmRefs">
    <span>{{ name }}</span>
    <br />
    <span>{{ count }}</span>
    <div>
      <button @click="handleClick">测试按钮</button>
    </div>

    <ul>
      <li v-for="item in list" :key="item.id">{{ item.name }}</li>
    </ul>
  </div>
</template>

<script lang="ts">
import {
  computed,
  defineComponent,
  getCurrentInstance,
  onMounted,
  PropType,
  reactive,
  ref,
  toRefs,
} from "vue";

interface IState {
  count: 0;
  name: string;
  list: Array<object>;
}

export default defineComponent({
  name: "demo",
  // 父组件传子组件参数
  props: {
    name: {
      type: String as PropType<null | "">,
      default: "vue3.x",
    },
    list: {
      type: Array as PropType<object[]>,
      default: () => [],
    },
  },
  components: {
    /// TODO 组件注册
  },
  emits: ["emits-name"], // 为了提示作用
  setup(props, context) {
    console.log(props.name);
    console.log(props.list);

    const state = reactive<IState>({
      name: "vue 3.0 组件",
      count: 0,
      list: [
        {
          name: "vue",
          id: 1,
        },
        {
          name: "vuex",
          id: 2,
        },
      ],
    });

    const a = computed(() => state.name);

    onMounted(() => {});

    function handleClick() {
      state.count++;
      // 调用父组件的方法
      context.emit("emits-name", state.count);
    }

    return {
      ...toRefs(state),
      handleClick,
    };
  },
});
</script>

实现 自定义 Hook

功能性组件可以封装成 hook, 以 use 作为前缀,和普通的函数区分

import { ref, Ref, computed } from "vue";

type CountResultProps = {
  count: Ref<number>;
  multiple: Ref<number>;
  increase: (delta?: number) => void;
  decrease: (delta?: number) => void;
};

export default function useCount(initValue = 1): CountResultProps {
  const count = ref(initValue);

  const increase = (delta?: number): void => {
    if (typeof delta !== "undefined") {
      count.value += delta;
    } else {
      count.value += 1;
    }
  };
  const multiple = computed(() => count.value * 2);

  const decrease = (delta?: number): void => {
    if (typeof delta !== "undefined") {
      count.value -= delta;
    } else {
      count.value -= 1;
    }
  };

  return {
    count,
    multiple,
    increase,
    decrease,
  };
}

使用 hook

<template>
  <p>count: {{ count }}</p>
  <p>倍数: {{ multiple }}</p>
  <div>
    <button @click="increase()">加1</button>
    <button @click="decrease()">减一</button>
  </div>
</template>

<script lang="ts">
import useCount from "../hooks/useCount";
 setup() {
    const { count, multiple, increase, decrease } = useCount(10);
        return {
            count,
            multiple,
            increase,
            decrease,
        };
    },
</script>

组件 teleport 任意门

目的: 即希望继续在组件内部使用 Dialog, 又希望渲染的 DOM 结构不嵌套在组件的 DOM 中

场景: 弹框

我们可以用<Teleport>包裹 Dialog, 此时就建立了一个传送门,可以将 Dialog 渲染的内容传送到任何指定的地方。使用 teleport 组件,通过 to 属性,指定该组件渲染的位置与 <div id="app"></div> 同级,也就是在 body 下,但是 Dialog 的状态 dialogVisible 又是完全由内部 Vue 组件控制.

<body>
  <div id="app"></div>
  <div id="dialog"></div>
</body>
// Dialog.vue
<template>
  <teleport to="#dialog">
    <div class="dialog">
      <div class="dialog_wrapper">
        <div class="dialog_header" v-if="title">
          <slot name="header">
            <span>{{ title }}</span>
          </slot>
        </div>
      </div>
      <div class="dialog_content">
        <slot></slot>
      </div>
      <div class="dialog_footer">
        <slot name="footer"></slot>
      </div>
    </div>
  </teleport>
</template>

// Footer.vue 子组件

<div class="footer">
    ...
    <Dialog v-if="dialogVisible"></Dialog>
</div>

组件 异步组件

Vue3 中 使用 defineAsyncComponent 定义异步组件,配置选项 component 替换为 loader ,Loader 函数本身不再接收 resolve 和 reject 参数,且必须返回一个 Promise。

<template>
  <!-- 异步组件的使用 -->
  <AsyncPage />
</template>

<script>
  import { defineAsyncComponent } from "vue";

  export default {
    components: {
      // 无配置项异步组件
      AsyncPage: defineAsyncComponent(() => import("./NextPage.vue")),

      // 有配置项异步组件
      AsyncPageWithOptions: defineAsyncComponent({
        loader: () => import(".NextPage.vue"),
        delay: 200,
        timeout: 3000,
        errorComponent: () => import("./ErrorComponent.vue"),
        loadingComponent: () => import("./LoadingComponent.vue"),
      }),
    },
  };
</script>

参考

  1. vue3 官网 https://v3.vuejs.org/
  2. 构建 vite https://github.com/vitejs/vite
  3. vue3 源码 https://github.com/vuejs/vue-next
  4. vue-cli https://cli.vuejs.org/
  5. vue-router https://github.com/vuejs/vue-router-next
最后编辑于:2024-09-24 21:09:17


喜欢的朋友记得点赞、收藏、关注哦!!!

### 回答1: antd-mobile-vue是一个基于Vue.js框架的移动端组件库,它提供了一系列UI组件,用于开发高质量的移动端应用。 与其它UI组件库相比,antd-mobile-vue具有以下优势和特点: 1. 高质量的组件:antd-mobile-vue提供了丰富的移动端UI组件,如按钮、表单、弹窗、导航等,这些组件都经过了精心设计和开发,具有统一的风格和良好的用户体验。 2. 灵活的布局:antd-mobile-vue提供了灵活的布局组件,如栅格布局、Flex布局,可帮助开发快速搭建页面结构,并自适应不同的屏幕尺寸。 3. 易于使用和扩展:antd-mobile-vue的组件使用简单,开发者可以通过简单的配置和参数就可以实现复杂的交互效果。而且,antd-mobile-vue的组件提供了丰富的扩展能力,可以根据项目需求进行个性化的定制。 4. 生态丰富:antd-mobile-vue拥有庞大的开发者社区和活跃的维护团队,开发者可以通过官方文档和社区资源获取帮助和支持。此外,antd-mobile-vue还与其它Vue.js生态工具和库良好地兼容,如Vue Router、Vue CLI等。 5. 支持国际化:antd-mobile-vue提供了多语言支持,开发者可以根据项目需求灵活地切换多种语言环境。 总之,antd-mobile-vue是一个功能强大、易于使用和扩展的移动端组件库,它可以帮助开发快速构建高质量的移动端应用,提高开发效率和用户体验。 ### 回答2: antd-mobile-vue是一种基于Vue.js框架的移动端UI库。它是对Ant Design Mobile的Vue组件实现的封装和扩展,旨在为开发者提供高质量、易用性的移动端组件库,帮助快速开发移动应用程序。 antd-mobile-vue提供了丰富的移动端UI组件,如按钮、导航栏、标签栏、列表、表单等,可以满足日常开发中绝大部分的界面需求。这些组件都经过精心设计和优化,在视觉和交互上都符合当前移动端的设计原则和用户体验。而且,它还提供了灵活的定制和扩展能力,允许开发者根据具体需求进行个性化定制,提高开发效率和用户体验。 除了UI组件外,antd-mobile-vue还提供了一些实用的工具和功能,如样式工具库、语言国际化、路由管理等。这些工具和功能都是为了让开发者更方便地进行移动应用开发,减少重复性的工作,提高开发效率。 antd-mobile-vue拥有广泛的社区支持和文档资料,开发者可以从社区中获取帮助和解决问题,学习和掌握使用该库的技巧和最佳实践。同时,antd-mobile-vue还提供了详细的官方文档和示例代码,方便开发快速入手和上手该库。 总之,antd-mobile-vue是一款功能强大、易用性强的移动端UI库,适用于各种移动应用的开发。无论是个人开发者还是团队开发,都可以通过使用antd-mobile-vue快速构建高质量的移动应用程序。 ### 回答3: antd-mobile-vue 是一个基于 Vue.js 的移动端 UI 组件库,它提供了丰富的移动端组件和样式风格,可以帮助开发快速构建优雅的移动端应用。 antd-mobile-vue 的特点有以下几个方面: 1. 高度可定制:antd-mobile-vue 提供了大量的组件,涵盖了移动端常见的UI元素,如按钮、导航栏、表单等,这些组件的样式和交互行为都可以通过配置进行定制,满足不同项目的需求。 2. 兼容性强:antd-mobile-vue 提供了对不同移动端浏览器和操作系统的支持,保证组件在不同环境下的正常运行和展示,同时也保证了用户的使用体验。 3. 特色设计:antd-mobile-vue 的设计风格简洁、现代,符合移动端用户的审美要求,同时也遵循了 Material Design 和 iOS Human Interface Guidelines 等设计准则,保证了用户的熟悉感和易用性。 4. 文档丰富:antd-mobile-vue 提供了详细的文档和示例代码,开发者可以根据文档了解组件的使用方法和配置参数,快速上手使用。 5. 生态丰富:antd-mobile-vue 是基于 Ant Design Mobile(antd-mobile)的 Vue 实现,可以与其它 Vue 生态工具和插件无缝集成,如 Vue Router、Vuex 等,方便开发者构建复杂的移动应用。 总之,antd-mobile-vue 是一个强大而灵活的移动端 UI 组件库,它可以帮助开发者节省时间和精力,快速开发出高质量的移动应用。无论是个人项目还是企业应用,都可以考虑使用这个库来提升开发效率和用户体验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

武昌库里写JAVA

您的鼓励将是我前进的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值