vue3扩展补充

410 阅读2分钟

扩展补充

Vite 插件 script setup name

说明:一款能让 script setup 添加组件名 name 的插件。

插件地址:github.com/vbenjs/vite…

问题:github.com/vuejs/vue/i…

问题:github.com/vuejs/vue/i…

  • 安装插件
yarn add vite-plugin-vue-setup-extend -D
  • 配置插件:vite.config.ts
import { defineConfig, Plugin } from 'vite'
import vue from '@vitejs/plugin-vue'
+ import vueSetupExtend from 'vite-plugin-vue-setup-extend'

export default defineConfig({
  plugins: [
    vue(), 
+   vueSetupExtend()
  ],
})
  • 组件中使用
+ <script setup lang="ts" name="App">
+ // 
+ </script>

-<script lang="ts">
-export default {
-  name: "App"
-}
-<script/>

<template>
  <div>Hello App Name </div>
</template>

项目打包、预览、部署

拓展阅读:Vite官方文档

项目打包

本节目标:知道打包命令做了哪些工作,了解本地预览。

打包构建

yarn build
  • vue-tsc 安全检查。
  • 打包文件并进行代码压缩。

本地预览

yarn preview

项目部署

说明:为了体验部署流程,我们把项目部署到码云 GiteePages

🚨注意:工作中一般由运营负责部署,部署到公司的服务器。

  1. vite.config.ts 中设置正确的 base
export default defineConfig({
+  base: "./", // 设置打包路径,部署到 GiteePages 需要相对于仓库路径
   ...
});

  1. 新建 deloy.sh 部署脚本
#!/usr/bin/env sh

# 确保脚本抛出遇到的错误
set -e

# 生成静态文件
npm run build

# 进入生成的文件夹
cd dist

# 如果是发布到自定义域名
# echo 'www.example.com' > CNAME

git init
git add -A
git commit -m 'deploy'

# 如果发布到 https://<USERNAME>.github.io/<REPO>
# git push -f git@gitee.com:<USERNAME>/<REPO>.git master:gh-pages
git push -f git@gitee.com:Megasu/rabbit-vue3-ts.git master:gh-pages

cd -
  1. 运行 deploy.sh
  2. 在码云部署 gh-pages 分支。

知识点拓展补充

处理异步请求渲染 - Suspense

我们时常需要:判断异步请求的状态,然后,根据这些请求来展示不同的界面 => Suspense 非常方便

vue3 推出了一个新的内置组件 SuspenseSuspense 是一个特殊的组件。

说明:

  • 它会有两个 template slot ,刚开始会渲染 feedback 内容,直到达到某个条件以后,才会渲染正式的内容,
  • 也就是 default 的内容。这样呢,进行异步内容的渲染就会变得特别简单。

功能1:异步 setup (支持顶层 await)

新建:setup 顶层 await 组件: TopAwaitCom.vue

<script setup lang="ts">
import { http } from '@/utils/request';

// 🚨 顶层 await 以前是不能渲染出组件内容的,所有的数据相当于都被 Promise 包装过
const res = await http('GET', '/home/banner');
console.log(res.data.result);
</script>

<template>
  <h1>我是顶层 await 组件</h1>
</template>

导入使用,但需要套上 Suspense 组件。

<script setup lang="ts">
import { defineAsyncComponent } from "vue";
import TopAwaitCom from "./TopAwaitCom.vue";
</script>

<template>
+  <Suspense
     <TopAwaitCom />
+    <template #fallback>
+      <h1>Loading...</h1>
+    </template>
+  </Suspense>
</template>

功能2:异步组件加载

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

// 直接加载组件
// import TestAsyncCom from "./TestCom.vue";
// 异步加载组件
const TestAsyncCom = () => import("./TestCom.vue");
</script>

<template>
  <Suspense>
    <template #default>
      <TestAsyncCom />
    </template>
    <template #fallback>
      <h1>Loading...</h1>
    </template>
  </Suspense>
</template>

Vue3 响应式原理

<!DOCTYPE html>
<html lang="zh-CN">
  <head>
    <meta charset="UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
  </head>
  <body>
    <h2>双向绑定</h2>
    <input type="text" value="" />
    <button>点击改名</button>
    <script>
      // 目标对象
      const obj = reactive({ name: 'zs', age: 18 });

      function reactive(obj) {
        // 目标对象的代理
        return new Proxy(obj, {
          get(...args) {
            // return obj[prop];
            return Reflect.get(...args);
          },
          set(obj, prop, value) {
            // obj[prop] = value;
            Reflect.set(obj, prop, value);
            document.querySelector('h2').innerHTML = JSON.stringify(obj);
            input.value = value;
          },
        });
      }

      console.log(obj);

      const input = document.querySelector('input');
      input.addEventListener('input', (e) => {
        obj.name = e.target.value;
      });

      const button = document.querySelector('button');
      button.addEventListener('click', () => {
        obj.name += '呀';
      });
    </script>
  </body>
</html>

Reflect 对象

Reflect 对象是 ES6 为了操作对象而提供的新 APIReflect 提供的静态方法让对象的操作更加规范统一。

TS 遍历对象

🔔 经验: 在 TS 项目中,对象遍历配合 Reflect 会更香,用 obj[key] 写法会 TS 项目报错。

Reflect-MDN

Reflect-阮一峰

Reflect 调用传统操作
获取Reflect.get(obj, key)obj[key]
设置Reflect.set(obj, key, value)obj[key] = value
删除Reflect.deleteProperty(obj, key)delete obj[key]
判断是否存在Reflect.has(obj, key)key in obj

代码写法升级:src\store\modules\cart.ts

// 🐛 TS 遍历对象,通过 lastCartInfo[key] 获取和修改对象会报错: key 为 any
for (const key in lastCartInfo) {
    // 获取 value
    const value = Reflect.get(lastCartInfo, key);
}

Reflect 与 Proxy

Reflect 可配合 Proxy 使用,Vue3reactive 函数的源码有应用。

reactive函数源码解读

JSX/TSX 基础-React基础

概述

TSX/JSX 语法糖(React 团队设计发明的,Vue 也进行了支持)

  1. Vue3 中其实就是createVNode 的语法糖,负责创建虚拟DOM用的。底层依赖 babel 插件支持。
  2. 我们在 Test 组件中,演示 jsx/tsx 语法。

没有 jsx/tsx 创建虚拟DOM

代码演示1:

<script setup lang="ts">
import { createVNode } from 'vue';

const VDOM = createVNode('h1', { id: 'box' }, 'hello');
</script>

<template>
  <VDOM />
</template>

代码演示2:

<script setup lang="ts">
import { createVNode } from 'vue';

const VDOM = createVNode("div", { id: "box" }, [
      createVNode("p", {}, "我是一个段落1"),
      createVNode("p", {}, "我是一个段落2"),
    ]);
</script>

思考:渲染以下结构?

<ul>
  <li>111</li>
  <li>222</li>
  <li>333</li>
  <li>444</li>
</ul>

写起来很麻烦,有没有更简单的写法呢?

jsx/tsx 创建虚拟DOM

本节目标:setup 中可以书写响应式数据,用于绑定到 tsx/jsx 结构中。

基础用法

<script setup lang="tsx">
const VDOM = () => <h1>Hello TSX in Setup</h1>;
</script>

<template>
  <VDOM />
</template>

TSX 的进阶用法

本节目标:内容绑定,属性绑定,事件绑定,条件渲染,列表渲染。

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

const count = ref(0);
const isHide = ref(true);
const add = () => {
  count.value += 1;
};
const list = ref([
  { id: 1, content: "吃饭", done: true },
  { id: 2, content: "睡觉", done: false },
  { id: 3, content: "打代码", done: true },
]);
// script - 数据绑定在 JSX 用一对花括号
const VDOM = () => {
  return (
    <div>
      <h1>Hello TSX in Setup</h1>
      <p>{count.value}</p>
      <button onClick={add}>点击+1</button>
      <button
        onClick={() => {
          isHide.value = !isHide.value;
        }}
      >
        切换显示隐藏
      </button>
      <h2>条件渲染</h2>
      {isHide.value ? <div>loading</div> : <div>结构2</div>}
      <h2>列表渲染</h2>
      <ul>
        {list.value.map((item) => (
          <li key={item.id}>{item.content}</li>
        ))}
      </ul>
    </div>
  );
};
</script>

<template>
  <VDOM />
</template>

函数式组件

Vue3 也支持函数式组件,可通过 .tsx/.jsx 后缀名文件创建组件,写法非常类似 React 的函数式组件语法。

现在 JSX/TSX 写法大家看不懂,学完 React 后看起来就轻松了 。

由于 JSX/TSX 不是 Vue 的主流语法,大家可以自行了解即可。

拓展阅读:juejin.cn/post/700773…