【架构师(第二十二篇)】编辑器开发之项目整体搭建

我心飞翔 分类:vue

这个阶段更多的是编写业务代码,除了编辑器之外没什么难度,需要记录笔记的部分并不多,除非有特殊需要记录的地 方,否则代码不会放在笔记里。

TypeScript 技术补充

由于对 tsvue3 已经有了初步了解,本文就不对基础记录笔记,只补充一些自己不是很掌握的知识点。

👉👉 【初学者笔记】🐯年要掌握 Typescript

👉👉 【初学者笔记】整理的一些Vue3知识点

interface

// 声明函数类型
interface Foo {
  (x: number, y: number): number;
}

// 可索引类型
interface RandomMap {
  [propName: string]: string;
}

// 类数组 , 可以通过数组取值 , 但是不能调用方法
interface LikeArray {
  [index: number]: string;
}

// 函数添加属性
interface FunctionWithProps {
  (x: number): number;
  name: string;
}

// 定义接口类型
interface Animal {
  name: string;
  run(): void;
}

// 实现接口
class cat implements Animal {
  name: string = "cat";
  run() {
    this.name + "run";
  }
}

// 定义接口类型
interface Live {
  breathe(): void;
}

// 实现多个类型的接口
class liveCat implements Animal, Live {
  name: string = "cat";
  run() {
    this.name + "run";
  }
  breathe() {
    this.name + "breathing";
  }
}

// 定义类的静态类型
interface CatStatic {
  // 可以被 new 调用的构造函数
  new (eyes: number, hands: number): void;
}

// 类的阴阳两面, 包含静态类型和实例类型
const FooCat: CatStatic = class FooCat implements Cat {
  constructor(eyes: number, hands: number) {}
  name: string = "cat";
  run() {
    this.name + "run";
  }
};

泛型

// 泛型基础
function foo<T>(arg: T): T {
  return arg;
}

// 交换 tuple 的位置
function swap<T, K>(tuple: [T, K]): [K, T] {
  return [tuple[1], tuple[0]];
}

interface Person {
  name: string;
  age: number;
}

interface Car {
  color: string;
  wheels: number;
}

// 约定请求返回值结果
function getInfo<T>(url: string): Promise<T> {
  return fetch(url).then((resp) => resp.json());
}

// resp 是 Person 类型
getInfo<Person>('/getperson').then((resp) => {});
// resp 是 Car 类型
getInfo<Car>('/getcar').then((resp) => {});

// 传入一个泛型, 把泛型中的属性全部变为可选
type PersonPartial = Partial<Person>;

// 遍历某个类型的键,返回由这些键组成的新的类型
type PersonKeys = keyof Person;

// lookup types 返回某个属性的类型
type NameType = Person['name'];

// mapped types 遍历
type Test = {
  [key in PersonKeys]: any;
};

// 相当于复制了一份 Person 类型
type PersonCopy = {
  [p in PersonKeys]: Person[p];
};

// 实现了 Partial 
type PersonCopy = {
  [p in PersonKeys]?: Person[p];
};

// 泛型约束
interface IWithLength {
  length: number;
}
// 传入的类型必须包含 length 属性
function echoWithArr<T extends IWithLength>(arg: T): T {
  console.log(arg.length);
  return arg;
}

// 条件类型关键字
// 判断一个类型是否满足另一个类型的约束
type NonType<T> = T extends null | undefined ? never : T;

Vue3 技术补充

纯函数 pure function

相同的输入,永远得到相同的输出

// 输入 2 ,永远输出 4
function foo(a){
 return a * 2
}
// 输入 2, 输出不确定
function bar(a){
 return a * Math.random()
}

没有副作用

  • 网络请求
  • DOM 操作
  • 订阅数据来源
  • 写入文件系统
  • 获取用户输入
  • ... ...

watchEffect

  • 初始化的时候会执行一次进行依赖的收集
  • 组件销毁的时候会自动移除 watchEffect
  • 返回一个函数可以手动清除 watchEffect
  • 可以提供一个参数修改 watchEffect 的执行时机
const count = ref(0);
const stop = watchEffect(()=>{
    console.log(count.value)
});
stop();
watchEffect(
    ()=>{
        console.log(count.value)
    },
    {
        flush:"post" // 更新 dom 之后
    }
);

编辑器开发之项目整体搭建

将收获什么

  • 前端工具链的相关工具介绍
  • 脚手架工具的使用和对比
    • imooc-cli
    • vue-cli
    • vite
  • 编码规范
    • ESLint
    • Prettier
    • 产出文档
  • 项目结构规范
    • 产出文档
  • Git 操作规范
    • 产出文档

创建项目

安装 imooc-cli 脚手架,并生成项目。

npm install -g @imooc-cli/core
npm install -g cnpm
imooc-cli --version
imooc-cli init

Git Flow 标准操作流程

  • 根据需求,从 master 拉出分支
  • 开发阶段,提交 commit
  • 开发完毕,发起 PR(pull request)
  • 代码评审
  • 部署,测试
  • mergemaster

两大规则

  • 分支命名
    • feature 开头代表新功能开发
    • hotfix 开头代表 bug 修复
  • commit 信息需要明确,杜绝 updatebugfix 等废话,言之有物,言简意赅的把一次 commit 说清楚。

项目基础搭建

安装第三方组件库 ant-design-vue

通过 npm 安装

npm install ant-design-vue --save

引入

// src\main.ts

import { createApp } from 'vue';
import App from './App.vue';

// 引入 Antd 组件库
import Antd from 'ant-design-vue';
import 'ant-design-vue/dist/antd.css';

const app = createApp(App);

app.use(Antd).mount('#app');

使用

// App.vue
<template>
  <a-button type="primary">Primary Button</a-button>
</template>

vue-router

通过 npm 安装

npm install vue-router@next --save

配置

// src\routes\index.ts

import { createRouter, createWebHistory } from 'vue-router';
import Home from '../views/Home.vue';
import Editor from '../views/Editor.vue';
import TemplateDetail from '../views/TemplateDetail.vue';

const router = createRouter({
  history: createWebHistory(),
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home,
    },
    {
      path: '/editor',
      name: 'editor',
      component: Editor,
    },
    {
      path: '/template/:id',
      name: 'template',
      component: TemplateDetail,
    },
  ],
});
export default router;

挂载到 vue 实例

// src\main.ts

import router from './routes/index';
app.use(router);

vuex

通过 npm 安装

npm install vuex@next --save

配置

// src\store\index.ts

import { createStore } from 'vuex';

const store = createStore({
  state: { count: 0 },
});

export default store;

挂载到 vue 实例

// src\main.ts

import vuex from './routes/index';
app.use(vuex);

结合 ts

// src\store\index.ts

import { createStore } from 'vuex';

export interface GlobalStore {
  count: number;
}

const store = createStore<GlobalStore>({
  state: { count: 0 },
});

export default store;

vue 文件中使用

// src\App.vue

import { useStore } from 'vuex'
import { GlobalStore} from './store/index'
import { computed } from 'vue';

const store = useStore<GlobalStore>()
const count = computed(() => store.state.count)

使用 Module 分割 Vuex 模块

// src\store\index.ts

import { createStore } from 'vuex';
import user from './user';
import template from './template';
import type { UserStore } from './user';
import type { TemplateStore } from './template';

export interface GlobalStore {
  user: UserStore;
  template: TemplateStore;
}

const store = createStore<GlobalStore>({
  modules: {
    user,
    template,
  },
});

export default store;
//  src\store\user.ts

import type { Module } from 'vuex';
import type { GlobalStore } from './index';
export interface UserProps {
  username: string;
  age: number;
}

export type UserList = UserProps[];

export interface UserStore {
  userList: UserList;
}

const userList: UserList = [
  {
    username: 'foo',
    age: 18,
  },
  {
    username: 'boo',
    age: 20,
  },
];

const userStore: Module<UserStore, GlobalStore> = {
  state: {
    userList: userList,
  },
  getters: {
    getUserByName: (state) => (name: string) => {
      return state.userList.find((u) => u.username === name);
    },
  },
};

export default userStore;
//  src\store\template.ts

import type { Module } from 'vuex';
import type { GlobalStore } from './index';
export interface TemplateProps {
  templateName: string;
  age: number;
}

export type TemplateList = TemplateProps[];

export interface TemplateStore {
  templateList: TemplateList;
}

const templateList: TemplateList = [
  {
    templateName: 'foo',
    age: 18,
  },
  {
    templateName: 'boo',
    age: 20,
  },
];

const templateStore: Module<TemplateStore, GlobalStore> = {
  state: {
    templateList: templateList,
  },
  getters: {
    getTemplateByName: (state) => (name: string) => {
      return state.templateList.find((t) => t.templateName === name);
    },
  },
};

export default templateStore;

回复

我来回复
  • 暂无回复内容