├── .DS_Store
├── .gitignore
├── 1-template
├── index.html
├── package-lock.json
└── package.json
├── 10-mini-vue
├── App.js
├── core
│ ├── h.js
│ ├── index.js
│ ├── reactivity
│ │ └── index.js
│ └── renderer.js
├── index.html
├── index.js
├── package.json
└── yarn.lock
├── 2-component
├── index.html
├── package-lock.json
└── package.json
├── 3-vue-cli-unit-test
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── jest.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ ├── ModifyPanel.vue
│ │ └── UserForm.vue
│ └── main.js
└── tests
│ └── unit
│ └── ModifyPanel.spec.js
├── 4-vue-router
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── jest.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── UserForm.vue
│ ├── main.js
│ ├── pages
│ │ ├── Home.vue
│ │ ├── Login.vue
│ │ └── ModifyPanel.vue
│ └── router
│ │ └── index.js
└── tests
│ └── unit
│ └── ModifyPanel.spec.js
├── 5-vuex
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── jest.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── UserForm.vue
│ ├── main.js
│ ├── pages
│ │ ├── Home.vue
│ │ ├── Login.vue
│ │ └── ModifyPanel.vue
│ ├── router
│ │ └── index.js
│ └── store
│ │ └── index.js
└── tests
│ └── unit
│ └── example.spec.js
├── 6-practice
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── jest.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── serve
│ ├── data.js
│ ├── index.js
│ ├── package-lock.json
│ └── package.json
├── src
│ ├── App.vue
│ ├── api
│ │ └── index.js
│ ├── assets
│ │ └── logo.png
│ ├── components
│ │ └── UserForm.vue
│ ├── http.js
│ ├── main.js
│ ├── pages
│ │ ├── Home.vue
│ │ ├── Login.vue
│ │ └── ModifyPanel.vue
│ ├── router
│ │ └── index.js
│ └── store
│ │ └── index.js
├── tests
│ └── unit
│ │ └── example.spec.js
├── vue.config.js
└── yarn.lock
├── 7-vue3-todo-list
├── .browserslistrc
├── .eslintrc.js
├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
└── src
│ ├── App.vue
│ ├── assets
│ └── logo.png
│ ├── components
│ ├── TodoItem.vue
│ └── TodoList.vue
│ ├── main.js
│ ├── store
│ └── index.js
│ └── utils
│ └── generateId.js
├── 8-custom-renderer
├── .DS_Store
├── assets
│ ├── bullet.png
│ ├── end_page.jpg
│ ├── enemy.png
│ ├── map.jpg
│ ├── plane.png
│ ├── restartBtn.png
│ ├── startBtn.png
│ └── start_page.jpg
├── dist
│ ├── build.js
│ └── index.html
├── main.js
├── package-lock.json
├── package.json
├── src
│ ├── .DS_Store
│ ├── App.js
│ ├── Game.js
│ └── runtime-canvas
│ │ └── index.js
├── webpack.config.js
├── work.md
└── yarn.lock
├── 9-play-plane
├── .gitignore
├── README.md
├── babel.config.js
├── package-lock.json
├── package.json
├── public
│ ├── favicon.ico
│ └── index.html
├── src
│ ├── App.vue
│ ├── assets
│ │ ├── bullet.png
│ │ ├── end_page.jpg
│ │ ├── enemy.png
│ │ ├── logo copy.png
│ │ ├── logo.png
│ │ ├── map.jpg
│ │ ├── plane.png
│ │ ├── restartBtn.png
│ │ ├── startBtn.png
│ │ └── start_page.jpg
│ ├── components
│ │ ├── Bullet.vue
│ │ ├── EnemyPlane.vue
│ │ ├── HelloWorld.vue
│ │ ├── Map.vue
│ │ └── Plane.vue
│ ├── game
│ │ └── index.js
│ ├── main.js
│ ├── pages
│ │ ├── EndPage.vue
│ │ ├── GamePage.vue
│ │ └── StartPage.vue
│ ├── runtime-canvas
│ │ └── index.js
│ └── utils
│ │ └── index.js
└── yarn.lock
└── README.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
--------------------------------------------------------------------------------
/1-template/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
13 | id |
14 | 用户名 |
15 | 邮箱 |
16 | 性别 |
17 | 爱好 |
18 | 操作 |
19 |
20 |
21 | {{ item.id }} |
22 | {{ item.username }} |
23 | {{ item.email }} |
24 | {{ item.gender }} |
25 | {{ item.hobby.join(' | ') }} |
26 |
27 |
28 | |
29 |
30 |
31 |
32 |
33 |
92 |
93 |
94 |
--------------------------------------------------------------------------------
/1-template/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "1-template",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "version": "1.0.0",
9 | "license": "ISC",
10 | "dependencies": {
11 | "vue": "^2.6.12"
12 | }
13 | },
14 | "node_modules/vue": {
15 | "version": "2.6.12",
16 | "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1609359858533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
17 | "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
18 | }
19 | },
20 | "dependencies": {
21 | "vue": {
22 | "version": "2.6.12",
23 | "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1609359858533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
24 | "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/1-template/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "1-template",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "vue": "^2.6.12"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/10-mini-vue/App.js:
--------------------------------------------------------------------------------
1 | import { reactive, watchEffect } from "./core/reactivity/index.js";
2 | import { h } from "./core/h.js";
3 | export default {
4 | render(context) {
5 | // 构建 view
6 | // b
7 | // 0. mini-vue
8 | // 1. 优化点,没有必要把之前的 dom 都干掉
9 | // 2. 如何去优化着一点呢? -> diff
10 | // 3. vdom -> js 对象来表示 -》 diff
11 | // 4 .写死的 dom -> canvas
12 | // 5. 渲染api 抽象出来
13 | // 6. 整理出初始化流程
14 | // document.querySelector("#app").innerHTML = ``;
15 | // diff -> vDom
16 | // diff
17 | // dom -> dom element
18 | // const div = document.createElement("div");
19 | // 响应式数据 get set
20 | // div.innerText = context.state.count;
21 |
22 | // div -> app root 容器
23 | // return div;
24 | // 1. string 2. 数组的写法
25 | // return h("div", { id: "test" }, "test for app");
26 | return h("div", { id: "id:" + context.state.count }, [
27 | h("p", null, "count:" + context.state.count),
28 | h("p", null, "double:" + context.state.double),
29 | h(
30 | "button",
31 | {
32 | onClick: context.handleClick,
33 | },
34 | "click"
35 | ),
36 | h("p", null, "child2"),
37 | ]);
38 | },
39 |
40 | // template -> render -> vnode
41 |
42 | setup() {
43 | const state = reactive({
44 | count: 1,
45 | double: 1,
46 | });
47 |
48 | watchEffect(() => {
49 | state.double = state.count * 2;
50 | });
51 |
52 | const handleClick = () => {
53 | state.count++;
54 | };
55 |
56 | return {
57 | handleClick,
58 | state,
59 | };
60 | },
61 | };
62 |
--------------------------------------------------------------------------------
/10-mini-vue/core/h.js:
--------------------------------------------------------------------------------
1 | // 创建一个虚拟dom
2 | // js -> object
3 | // 来描述一个 dom element 的对象
4 | // dom element -> 1. type 2. props 属性 3. children
5 |
6 | // vnode
7 | // vue3 h
8 | // createVNode
9 | export function h(type, props, children) {
10 | return {
11 | type,
12 | props,
13 | children,
14 | };
15 | }
16 |
--------------------------------------------------------------------------------
/10-mini-vue/core/index.js:
--------------------------------------------------------------------------------
1 | // 程序的入口
2 | import { watchEffect } from "./reactivity/index.js";
3 | import { mountElement,diff } from "./renderer.js";
4 | export function createApp(rootComponent) {
5 | return {
6 | mount(rootContainer) {
7 | const setupResult = rootComponent.setup();
8 | let isMounted = false;
9 | let prevSubTree = null;
10 |
11 | watchEffect(() => {
12 | if (!isMounted) {
13 | // 初始化的时候
14 | isMounted = true;
15 | const subTree = rootComponent.render(setupResult);
16 | // vnodeTree
17 | console.log(subTree);
18 |
19 | rootContainer.innerHTML = ``;
20 | mountElement(subTree, rootContainer);
21 | // rootContainer.append(element);
22 | prevSubTree = subTree;
23 | } else {
24 | // update
25 | // diff
26 | // 我们需要2个节点 当前 subTree 之前的 subTree
27 | const subTree = rootComponent.render(setupResult);
28 | console.log("currentSubTree", subTree);
29 | console.log("prevSubTree", prevSubTree);
30 | diff(prevSubTree, subTree);
31 | prevSubTree = subTree;
32 | }
33 | });
34 | },
35 | };
36 | }
37 |
--------------------------------------------------------------------------------
/10-mini-vue/core/reactivity/index.js:
--------------------------------------------------------------------------------
1 | // 响应式 reactivity
2 | // 1. 收集依赖
3 | // 2. 触发依赖
4 | // ref reactive
5 | // effect
6 |
7 | let currentEffect = null;
8 | // 依赖
9 | class Dep {
10 | constructor() {
11 | // this._val = val;
12 | this.effects = new Set();
13 | }
14 |
15 | // get value() {
16 | // this.depend();
17 | // return this._val;
18 | // }
19 |
20 | // set value(newVal) {
21 | // this._val = newVal;
22 | // this.notice();
23 | // }
24 |
25 | depend() {
26 | // 收集依赖
27 | if (currentEffect) {
28 | this.effects.add(currentEffect);
29 | }
30 | }
31 |
32 | notice() {
33 | // 触发依赖
34 | this.effects.forEach((effect) => {
35 | effect();
36 | });
37 | }
38 | }
39 |
40 | export function watchEffect(effect) {
41 | // 就是这个 effect
42 | currentEffect = effect;
43 | effect();
44 | currentEffect = null;
45 | }
46 |
47 | // const dep = new Dep(10);
48 |
49 | // ref - watchEffect
50 |
51 | // 使用
52 | // watchEffect(() => {
53 | // // dep get set
54 | // console.log(dep.value);
55 | // // 收集依赖
56 | // // dep.depend();
57 | // });
58 |
59 | // dep.value = 20;
60 | // dep.notice();
61 |
62 | // 如果是一个对象呢?
63 | //
64 |
65 | // 1. key -> dep 存在哪里?存储问题
66 | // 2. 如何取?
67 |
68 | // 存储所有的对象
69 | // 对象作为 key
70 | // deps 作为 val
71 | const targetsMap = new Map();
72 |
73 | function getDep(target, key) {
74 | let depsMap = targetsMap.get(target);
75 | // 不能取出来,是因为我们之前都没有存过
76 | if (!depsMap) {
77 | // 存一下呗
78 | depsMap = new Map();
79 | targetsMap.set(target, depsMap);
80 | }
81 | // dep
82 | let dep = depsMap.get(key);
83 | if (!dep) {
84 | dep = new Dep();
85 | depsMap.set(key, dep);
86 | }
87 |
88 | return dep;
89 | }
90 |
91 | export function reactive(raw) {
92 | // 取 key
93 |
94 | // vue2 -> object.defineProperty
95 | return new Proxy(raw, {
96 | get(target, key) {
97 | // key
98 | // 必须要取出 key 对应的那个 dep
99 | // 在这里的时候 dep 肯定是获取到了
100 | // 收集依赖
101 | const dep = getDep(target, key);
102 | dep.depend();
103 |
104 | // 写法 已经废弃了
105 | // return target[key];
106 | return Reflect.get(target, key);
107 | },
108 | set(target, key, value) {
109 | // key -> dep -> notice()
110 | const dep = getDep(target, key);
111 | // target[key] = value;
112 | const result = Reflect.set(target, key, value);
113 | // notice 一定要在修改值之后调用
114 | dep.notice();
115 | return result;
116 | },
117 | });
118 | }
119 |
120 | // const user = {
121 | // name: "xiaohong",
122 | // age: 18,
123 | // };
124 | // const userState = reactive(user);
125 |
126 | // watchEffect(() => {
127 | // console.log(userState.name);
128 | // });
129 |
130 | // userState.name = "xiaohei";
131 |
--------------------------------------------------------------------------------
/10-mini-vue/core/renderer.js:
--------------------------------------------------------------------------------
1 | function createElement(type) {
2 | // canvas ?
3 | return document.createElement(type);
4 | }
5 |
6 | function patchProp(el, key, prevValue, nextValue) {
7 | if (nextValue === null) {
8 | el.removeAttribute(key);
9 | } else {
10 | // 支持 onXXX
11 | if (key.startsWith("on")) {
12 | const eventName = key.slice(2).toLocaleLowerCase();
13 | el.addEventListener(eventName, nextValue);
14 | } else {
15 | el.setAttribute(key, nextValue);
16 | }
17 | }
18 | }
19 |
20 | // 把虚拟节点转换成真实的节点
21 | export function mountElement(vnode, container) {
22 | // type
23 | // props
24 | // children
25 | const { type, props, children } = vnode;
26 |
27 | const el = (vnode.el = createElement(type));
28 |
29 | // props
30 | if (props) {
31 | for (const key in props) {
32 | const val = props[key];
33 | patchProp(el, key, null, val);
34 | }
35 | }
36 |
37 | // children
38 | if (typeof children === "string") {
39 | const text = document.createTextNode(children);
40 | el.append(text);
41 | } else if (Array.isArray(children)) {
42 | // 递归
43 | children.forEach((v) => {
44 | mountElement(v, el);
45 | });
46 | }
47 |
48 | // insert
49 | container.append(el);
50 | }
51 |
52 | // n1 是老的 vnode
53 | // n2 是新的 vnode
54 | export function diff(n1, n2) {
55 | // type
56 | if (n1.type !== n2.type) {
57 | // 如果 type 不一样的话,那么直接用新的 type 来替换掉之前的
58 | n1.el.replaceWith(createElement(n2.type));
59 | } else {
60 | // 处理 props
61 | // 新的: {id:"test",data-hei ="123"}
62 | // 旧的: {id: "test-old",data-test="test"}
63 | const el = (n2.el = n1.el);
64 |
65 | const oldProps = n1.props || {};
66 | const newProps = n2.props || {};
67 |
68 | // 处理新值
69 | Object.keys(newProps).forEach((key) => {
70 | // 如果新的值 不等于 旧的值 那么更新
71 | if (newProps[key] !== oldProps[key]) {
72 | patchProp(el, key, oldProps[key], newProps[key]);
73 | }
74 | });
75 |
76 | // 处理老值
77 | // 如果老的props 里面有,而新的props 里面没有的话 那么就需要删除
78 | Object.keys(oldProps).forEach((key) => {
79 | if (!newProps[key]) {
80 | patchProp(el, key, oldProps[key], null);
81 | }
82 | });
83 |
84 | // 处理 children
85 | // children -> string | array
86 | // newChildren -> string -> oldChildren string | array
87 | // newChildren -> array ->oldChildren string | array
88 | const newChildren = n2.children || [];
89 | const oldChildren = n1.children || [];
90 |
91 | if (typeof newChildren === "string") {
92 | if (typeof oldChildren === "string") {
93 | // 还需要对比一下 children 是否不同
94 | if (newChildren !== oldChildren) {
95 | el.textContent = newChildren;
96 | }
97 | } else if (Array.isArray(oldChildren)) {
98 | el.textContent = newChildren;
99 | }
100 | } else if (Array.isArray(newChildren)) {
101 | // 数组
102 | if (typeof oldChildren === "string") {
103 | // 清空一下
104 | el.innerHTML = ``;
105 | newChildren.forEach((v) => {
106 | mountElement(v, el);
107 | });
108 | } else if (Array.isArray(oldChildren)) {
109 | // 有意思的来了
110 | // 2个 都是 数组了
111 | // 源码里面是特别复杂的
112 | // 暴力算法 最简单的方式来实现
113 | // 第一种情况:
114 | // old: {a,b,c}
115 | // new: {a,b,e}
116 | // 长度是一致的
117 | // 直接调用 diff 做递归处理
118 | // 第二种情况
119 | // old: {a,b,c,d,e,f}
120 | // new: {a,b,e}
121 | // 老的比新的长
122 | // 老的多出来的 都需要删除掉
123 | // 第三种情况
124 | // old: {a,b,c}
125 | // new: {a,b,c,e}
126 | // 新的比老的长
127 | // 新的需要创建
128 |
129 | // 公共长度
130 | const length = Math.min(newChildren.length, oldChildren.length);
131 |
132 | for (let i = 0; i < length; i++) {
133 | const oldVnode = oldChildren[i];
134 | const newVnode = newChildren[i];
135 |
136 | diff(oldVnode, newVnode);
137 | }
138 |
139 | // 如果老的多,那么需要删除掉
140 | if (oldChildren.length > length) {
141 | for (let i = length; i < oldChildren.length; i++) {
142 | const vnode = oldChildren[i];
143 | // 父级节点删除子节点
144 | el.removeChild(vnode.el);
145 | }
146 | }
147 |
148 | // 如果新的多,那么需要创建
149 | if (newChildren.length > length) {
150 | for (let i = length; i < newChildren.length; i++) {
151 | const vnode = newChildren[i];
152 | mountElement(vnode, el);
153 | }
154 | }
155 | }
156 | }
157 | }
158 | }
159 |
--------------------------------------------------------------------------------
/10-mini-vue/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/10-mini-vue/index.js:
--------------------------------------------------------------------------------
1 | // const { ref, reactive, effect } = require("@vue/reactivity");
2 | // import {
3 | // ref,
4 | // reactive,
5 | // effect,
6 | // } from "@vue/reactivity/dist/reactivity.esm-browser";
7 | // import { reactive, watchEffect } from "./core/reactivity/index.js";
8 |
9 | // 收集依赖 和 触发依赖的过程?
10 |
11 | // const a = ref(10);
12 |
13 | // let b;
14 | // // view -> 响应式数据
15 |
16 | // // watchEffect
17 | // effect(() => {
18 | // b = a.value + 10;
19 | // console.log(b);
20 | // });
21 |
22 | // a.value = 20;
23 |
24 | // reutrn {} -> setup -> temaplte
25 |
26 | // vue3 的更新机制 -> 最小模型
27 | // vue3 -> mini
28 | // const App = {
29 | // // template -> render
30 | // render(context) {
31 | // // 构建 view
32 | // // b
33 | // watchEffect(() => {
34 | // // 0. mini-vue
35 | // // 1. 优化点,没有必要把之前的 dom 都干掉
36 | // // 2. 如何去优化着一点呢? -> diff
37 | // // 3. vdom -> js 对象来表示 -》 diff
38 | // // 4 .写死的 dom -> canvas
39 | // // 5. 渲染api 抽象出来
40 | // // 6. 整理出初始化流程
41 | // document.querySelector("#app").innerHTML = ``;
42 | // // diff -> vDom
43 | // const div = document.createElement("div");
44 | // // 响应式数据 get set
45 | // div.innerText = context.state.count;
46 | // // 添加到
47 | // document.querySelector("#app").append(div);
48 | // });
49 | // },
50 |
51 | // setup() {
52 | // const state = reactive({
53 | // count: 1,
54 | // });
55 | // window.state = state;
56 | // // count -> change
57 | // return {
58 | // state,
59 | // };
60 | // },
61 | // };
62 |
63 | // App.render(App.setup());
64 |
65 | import { createApp } from "./core/index.js";
66 | import App from "./App.js";
67 |
68 | // 这个 api 熟悉嘛?
69 | createApp(App).mount(document.querySelector("#app"));
70 |
--------------------------------------------------------------------------------
/10-mini-vue/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "learn-rectivity",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "@vue/reactivity": "^3.0.4"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/10-mini-vue/yarn.lock:
--------------------------------------------------------------------------------
1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.
2 | # yarn lockfile v1
3 |
4 |
5 | "@vue/reactivity@^3.0.4":
6 | version "3.0.5"
7 | resolved "https://registry.npm.taobao.org/@vue/reactivity/download/@vue/reactivity-3.0.5.tgz#e3789e4d523d845f9ae0b4d770e2b45594742fd2"
8 | integrity sha1-43ieTVI9hF+a4LTXcOK0VZR0L9I=
9 | dependencies:
10 | "@vue/shared" "3.0.5"
11 |
12 | "@vue/shared@3.0.5":
13 | version "3.0.5"
14 | resolved "https://registry.npm.taobao.org/@vue/shared/download/@vue/shared-3.0.5.tgz#c131d88bd6713cc4d93b3bb1372edb1983225ff0"
15 | integrity sha1-wTHYi9ZxPMTZOzuxNy7bGYMiX/A=
16 |
--------------------------------------------------------------------------------
/2-component/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 | Document
7 |
8 |
9 |
10 |
11 |
12 |
13 | id |
14 | 用户名 |
15 | 邮箱 |
16 | 性别 |
17 | 爱好 |
18 | 操作 |
19 |
20 |
21 | {{ item.id }} |
22 | {{ item.username }} |
23 | {{ item.email }} |
24 | {{ item.gender }} |
25 | {{ item.hobby.join(' | ') }} |
26 |
27 |
28 |
29 | |
30 |
31 |
32 |
33 |
38 |
39 |
40 |
41 |
207 |
208 |
209 |
--------------------------------------------------------------------------------
/2-component/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "1-template",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "version": "1.0.0",
9 | "license": "ISC",
10 | "dependencies": {
11 | "vue": "^2.6.12"
12 | }
13 | },
14 | "node_modules/vue": {
15 | "version": "2.6.12",
16 | "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1609359858533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
17 | "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
18 | }
19 | },
20 | "dependencies": {
21 | "vue": {
22 | "version": "2.6.12",
23 | "resolved": "https://registry.npm.taobao.org/vue/download/vue-2.6.12.tgz?cache=0&sync_timestamp=1609359858533&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fvue%2Fdownload%2Fvue-2.6.12.tgz",
24 | "integrity": "sha1-9evU+mvShpQD4pqJau1JBEVskSM="
25 | }
26 | }
27 | }
28 |
--------------------------------------------------------------------------------
/2-component/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "1-template",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "vue": "^2.6.12"
14 | }
15 | }
16 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
7 | parserOptions: {
8 | parser: "babel-eslint"
9 | },
10 | rules: {
11 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
12 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
13 | },
14 | overrides: [
15 | {
16 | files: [
17 | "**/__tests__/*.{j,t}s?(x)",
18 | "**/tests/unit/**/*.spec.{j,t}s?(x)"
19 | ],
20 | env: {
21 | jest: true
22 | }
23 | }
24 | ]
25 | };
26 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/README.md:
--------------------------------------------------------------------------------
1 | # 3-vue-cli-unit-test
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Run your unit tests
19 | ```
20 | npm run test:unit
21 | ```
22 |
23 | ### Lints and fixes files
24 | ```
25 | npm run lint
26 | ```
27 |
28 | ### Customize configuration
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"]
3 | };
4 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: "@vue/cli-plugin-unit-jest"
3 | };
4 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "3-vue-cli-unit-test",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "test:unit": "vue-cli-service test:unit",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "core-js": "^3.6.5",
13 | "vue": "^2.6.11"
14 | },
15 | "devDependencies": {
16 | "@vue/cli-plugin-babel": "~4.5.0",
17 | "@vue/cli-plugin-eslint": "~4.5.0",
18 | "@vue/cli-plugin-unit-jest": "~4.5.0",
19 | "@vue/cli-service": "~4.5.0",
20 | "@vue/eslint-config-prettier": "^6.0.0",
21 | "@vue/test-utils": "^1.0.3",
22 | "babel-eslint": "^10.1.0",
23 | "eslint": "^6.7.2",
24 | "eslint-plugin-prettier": "^3.1.3",
25 | "eslint-plugin-vue": "^6.2.2",
26 | "prettier": "^1.19.1",
27 | "vue-template-compiler": "^2.6.11"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/3-vue-cli-unit-test/public/favicon.ico
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
17 |
18 |
28 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/3-vue-cli-unit-test/src/assets/logo.png
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/src/components/ModifyPanel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
113 |
114 |
115 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/src/components/UserForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | id |
6 | 用户名 |
7 | 邮箱 |
8 | 性别 |
9 | 爱好 |
10 | 操作 |
11 |
12 |
13 | {{ item.id }} |
14 | {{ item.username }} |
15 | {{ item.email }} |
16 | {{ item.gender }} |
17 | {{ item.hobby.join(" | ") }} |
18 |
19 |
20 |
21 | |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
34 |
121 |
122 |
123 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 |
4 | Vue.config.productionTip = false;
5 |
6 | new Vue({
7 | render: h => h(App)
8 | }).$mount("#app");
9 |
--------------------------------------------------------------------------------
/3-vue-cli-unit-test/tests/unit/ModifyPanel.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from "@vue/test-utils";
2 | import ModifyPanel from "@/components/ModifyPanel.vue";
3 |
4 | describe("ModifyPanel.vue", () => {
5 | it("emit update:visible event when click cancel btn ", () => {
6 | const wrapper = mount(ModifyPanel, {
7 | propsData: {
8 | visible: true,
9 | },
10 | });
11 | wrapper.get("[data-testid=cancel]").trigger("click");
12 |
13 | expect(wrapper.emitted("update:visible")[0]).toEqual([false]);
14 | expect(wrapper.emitted("cancel")[0]).toBeTruthy()
15 | });
16 |
17 | it("emit save event when click cancel btn", () => {
18 | const item = {
19 | id: 1,
20 | username: "小红",
21 | email: "xiaohong@qq.com",
22 | gender: "女",
23 | hobby: ["弹琴", "读书"],
24 | };
25 |
26 | const wrapper = mount(ModifyPanel, {
27 | propsData: {
28 | visible: true,
29 | item,
30 | },
31 | });
32 |
33 | wrapper.get("[data-testid=save]").trigger("click");
34 | expect(wrapper.emitted("save")[0]).toEqual([item]);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/4-vue-router/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/4-vue-router/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
7 | parserOptions: {
8 | parser: "babel-eslint"
9 | },
10 | rules: {
11 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
12 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
13 | },
14 | overrides: [
15 | {
16 | files: [
17 | "**/__tests__/*.{j,t}s?(x)",
18 | "**/tests/unit/**/*.spec.{j,t}s?(x)"
19 | ],
20 | env: {
21 | jest: true
22 | }
23 | }
24 | ]
25 | };
26 |
--------------------------------------------------------------------------------
/4-vue-router/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/4-vue-router/README.md:
--------------------------------------------------------------------------------
1 | # 4-vue-router
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Run your unit tests
19 | ```
20 | npm run test:unit
21 | ```
22 |
23 | ### Lints and fixes files
24 | ```
25 | npm run lint
26 | ```
27 |
28 | ### Customize configuration
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/4-vue-router/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"]
3 | };
4 |
--------------------------------------------------------------------------------
/4-vue-router/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: "@vue/cli-plugin-unit-jest"
3 | };
4 |
--------------------------------------------------------------------------------
/4-vue-router/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "4-vue-router",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "test:unit": "vue-cli-service test:unit",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "core-js": "^3.6.5",
13 | "vue": "^2.6.11",
14 | "vue-router": "^3.2.0"
15 | },
16 | "devDependencies": {
17 | "@vue/cli-plugin-babel": "~4.5.0",
18 | "@vue/cli-plugin-eslint": "~4.5.0",
19 | "@vue/cli-plugin-router": "~4.5.0",
20 | "@vue/cli-plugin-unit-jest": "~4.5.0",
21 | "@vue/cli-service": "~4.5.0",
22 | "@vue/eslint-config-prettier": "^6.0.0",
23 | "@vue/test-utils": "^1.0.3",
24 | "babel-eslint": "^10.1.0",
25 | "eslint": "^6.7.2",
26 | "eslint-plugin-prettier": "^3.1.3",
27 | "eslint-plugin-vue": "^6.2.2",
28 | "prettier": "^1.19.1",
29 | "vue-template-compiler": "^2.6.11"
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/4-vue-router/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/4-vue-router/public/favicon.ico
--------------------------------------------------------------------------------
/4-vue-router/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/4-vue-router/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
12 |
13 |
23 |
--------------------------------------------------------------------------------
/4-vue-router/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/4-vue-router/src/assets/logo.png
--------------------------------------------------------------------------------
/4-vue-router/src/components/UserForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | id |
6 | 用户名 |
7 | 邮箱 |
8 | 性别 |
9 | 爱好 |
10 | 操作 |
11 |
12 |
13 | {{ item.id }} |
14 | {{ item.username }} |
15 | {{ item.email }} |
16 | {{ item.gender }} |
17 | {{ item.hobby.join(" | ") }} |
18 |
19 |
20 |
21 | |
22 |
23 |
24 |
25 |
26 |
27 |
115 |
116 |
117 |
--------------------------------------------------------------------------------
/4-vue-router/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 |
5 | Vue.config.productionTip = false;
6 |
7 | new Vue({
8 | router,
9 | render: (h) => h(App),
10 | }).$mount("#app");
11 |
--------------------------------------------------------------------------------
/4-vue-router/src/pages/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/4-vue-router/src/pages/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
52 |
53 |
92 |
--------------------------------------------------------------------------------
/4-vue-router/src/pages/ModifyPanel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
110 |
111 |
112 |
--------------------------------------------------------------------------------
/4-vue-router/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter from "vue-router";
3 | import Home from "../pages/Home.vue";
4 | import Login from "../pages/Login.vue";
5 | import ModifyPanel from "../pages/ModifyPanel.vue";
6 |
7 | Vue.use(VueRouter);
8 |
9 | export default new VueRouter({
10 | routes: [
11 | {
12 | path: "/",
13 | name: "Home",
14 | component: Home,
15 | },
16 | {
17 | path: "/login",
18 | name: "Login",
19 | component: Login,
20 | },
21 | {
22 | path: "/modify",
23 | name: "Modify",
24 | props: true,
25 | component: ModifyPanel,
26 | },
27 | ],
28 | });
29 |
--------------------------------------------------------------------------------
/4-vue-router/tests/unit/ModifyPanel.spec.js:
--------------------------------------------------------------------------------
1 | import { mount } from "@vue/test-utils";
2 | import ModifyPanel from "@/components/ModifyPanel.vue";
3 |
4 | describe("ModifyPanel.vue", () => {
5 | it("emit update:visible event when click cancel btn ", () => {
6 | const wrapper = mount(ModifyPanel, {
7 | propsData: {
8 | visible: true,
9 | },
10 | });
11 | wrapper.get("[data-testid=cancel]").trigger("click");
12 |
13 | expect(wrapper.emitted("update:visible")[0]).toEqual([false]);
14 | expect(wrapper.emitted("cancel")[0]).toBeTruthy()
15 | });
16 |
17 | it("emit save event when click cancel btn", () => {
18 | const item = {
19 | id: 1,
20 | username: "小红",
21 | email: "xiaohong@qq.com",
22 | gender: "女",
23 | hobby: ["弹琴", "读书"],
24 | };
25 |
26 | const wrapper = mount(ModifyPanel, {
27 | propsData: {
28 | visible: true,
29 | item,
30 | },
31 | });
32 |
33 | wrapper.get("[data-testid=save]").trigger("click");
34 | expect(wrapper.emitted("save")[0]).toEqual([item]);
35 | });
36 | });
37 |
--------------------------------------------------------------------------------
/5-vuex/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/5-vuex/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
7 | parserOptions: {
8 | parser: "babel-eslint"
9 | },
10 | rules: {
11 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
12 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
13 | },
14 | overrides: [
15 | {
16 | files: [
17 | "**/__tests__/*.{j,t}s?(x)",
18 | "**/tests/unit/**/*.spec.{j,t}s?(x)"
19 | ],
20 | env: {
21 | jest: true
22 | }
23 | }
24 | ]
25 | };
26 |
--------------------------------------------------------------------------------
/5-vuex/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/5-vuex/README.md:
--------------------------------------------------------------------------------
1 | # 5-vuex
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Run your unit tests
19 | ```
20 | npm run test:unit
21 | ```
22 |
23 | ### Lints and fixes files
24 | ```
25 | npm run lint
26 | ```
27 |
28 | ### Customize configuration
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/5-vuex/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"]
3 | };
4 |
--------------------------------------------------------------------------------
/5-vuex/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: "@vue/cli-plugin-unit-jest"
3 | };
4 |
--------------------------------------------------------------------------------
/5-vuex/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "5-vuex",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "test:unit": "vue-cli-service test:unit",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "core-js": "^3.6.5",
13 | "vue": "^2.6.11",
14 | "vue-router": "^3.2.0",
15 | "vuex": "^3.4.0"
16 | },
17 | "devDependencies": {
18 | "@vue/cli-plugin-babel": "~4.5.0",
19 | "@vue/cli-plugin-eslint": "~4.5.0",
20 | "@vue/cli-plugin-router": "~4.5.0",
21 | "@vue/cli-plugin-unit-jest": "~4.5.0",
22 | "@vue/cli-plugin-vuex": "~4.5.0",
23 | "@vue/cli-service": "~4.5.0",
24 | "@vue/eslint-config-prettier": "^6.0.0",
25 | "@vue/test-utils": "^1.0.3",
26 | "babel-eslint": "^10.1.0",
27 | "eslint": "^6.7.2",
28 | "eslint-plugin-prettier": "^3.1.3",
29 | "eslint-plugin-vue": "^6.2.2",
30 | "prettier": "^1.19.1",
31 | "vue-template-compiler": "^2.6.11"
32 | }
33 | }
34 |
--------------------------------------------------------------------------------
/5-vuex/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/5-vuex/public/favicon.ico
--------------------------------------------------------------------------------
/5-vuex/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/5-vuex/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
29 |
--------------------------------------------------------------------------------
/5-vuex/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/5-vuex/src/assets/logo.png
--------------------------------------------------------------------------------
/5-vuex/src/components/UserForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | id |
6 | 用户名 |
7 | 邮箱 |
8 | 性别 |
9 | 爱好 |
10 | 操作 |
11 |
12 |
13 | {{ item.id }} |
14 | {{ item.username }} |
15 | {{ item.email }} |
16 | {{ item.gender }} |
17 | {{ item.hobby.join(" | ") }} |
18 |
19 |
20 |
21 | |
22 |
23 |
24 |
25 |
26 |
27 |
62 |
63 |
64 |
--------------------------------------------------------------------------------
/5-vuex/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 | import store from "./store";
5 |
6 | Vue.config.productionTip = false;
7 |
8 | new Vue({
9 | router,
10 | store,
11 | render: h => h(App)
12 | }).$mount("#app");
13 |
--------------------------------------------------------------------------------
/5-vuex/src/pages/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/5-vuex/src/pages/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
52 |
53 |
92 |
--------------------------------------------------------------------------------
/5-vuex/src/pages/ModifyPanel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/5-vuex/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter from "vue-router";
3 | import Home from "../pages/Home.vue";
4 | import Login from "../pages/Login.vue";
5 | import ModifyPanel from "../pages/ModifyPanel.vue";
6 |
7 | Vue.use(VueRouter);
8 |
9 | export default new VueRouter({
10 | routes: [
11 | {
12 | path: "/",
13 | name: "Home",
14 | component: Home,
15 | },
16 | {
17 | path: "/login",
18 | name: "Login",
19 | component: Login,
20 | },
21 | {
22 | path: "/modify",
23 | name: "Modify",
24 | props: true,
25 | component: ModifyPanel,
26 | },
27 | ],
28 | });
29 |
--------------------------------------------------------------------------------
/5-vuex/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 |
4 | Vue.use(Vuex);
5 |
6 | export default new Vuex.Store({
7 | state: {
8 | username: "",
9 | formData: [
10 | {
11 | id: 1,
12 | username: "小红",
13 | email: "xiaohong@qq.com",
14 | gender: "女",
15 | hobby: ["弹琴", "读书"],
16 | },
17 | {
18 | id: 2,
19 | username: "小黑",
20 | email: "xiaohei@qq.com",
21 | gender: "男",
22 | hobby: ["篮球", "读书", "编程"],
23 | },
24 | {
25 | id: 3,
26 | username: "小亮",
27 | email: "xiaoliang@qq.com",
28 | gender: "男",
29 | hobby: ["篮球", "读书", "编程"],
30 | },
31 | {
32 | id: 4,
33 | username: "小五",
34 | email: "xiaowu@qq.com",
35 | gender: "男",
36 | hobby: ["篮球", "读书", "编程"],
37 | },
38 | {
39 | id: 5,
40 | username: "小海",
41 | email: "aaa@qq.com",
42 | gender: "男",
43 | hobby: ["篮球", "读书", "编程"],
44 | },
45 | {
46 | id: 6,
47 | username: "小紫",
48 | email: "aaa@qq.com",
49 | gender: "男",
50 | hobby: ["篮球", "读书", "编程"],
51 | },
52 | ],
53 | },
54 | mutations: {
55 | login(state, payload) {
56 | state.username = payload.username;
57 | },
58 |
59 | modifyForm(state, payload) {
60 | const rawData = state.formData.find((d) => d.id === payload.id);
61 | if (rawData) {
62 | rawData.hobby = payload.hobby;
63 | rawData.username = payload.username;
64 | rawData.email = payload.email;
65 | rawData.gender = payload.gender;
66 | }
67 | },
68 |
69 | deleteForm(state, payload) {
70 | const { id } = payload;
71 | const index = state.formData.findIndex((d) => d.id === id);
72 | state.formData.splice(index, 1);
73 | },
74 | },
75 | actions: {},
76 | modules: {},
77 | });
78 |
--------------------------------------------------------------------------------
/5-vuex/tests/unit/example.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from "@vue/test-utils";
2 | import HelloWorld from "@/components/HelloWorld.vue";
3 |
4 | describe("HelloWorld.vue", () => {
5 | it("renders props.msg when passed", () => {
6 | const msg = "new message";
7 | const wrapper = shallowMount(HelloWorld, {
8 | propsData: { msg }
9 | });
10 | expect(wrapper.text()).toMatch(msg);
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/6-practice/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/6-practice/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true
5 | },
6 | extends: ["plugin:vue/essential", "eslint:recommended", "@vue/prettier"],
7 | parserOptions: {
8 | parser: "babel-eslint"
9 | },
10 | rules: {
11 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
12 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off"
13 | },
14 | overrides: [
15 | {
16 | files: [
17 | "**/__tests__/*.{j,t}s?(x)",
18 | "**/tests/unit/**/*.spec.{j,t}s?(x)"
19 | ],
20 | env: {
21 | jest: true
22 | }
23 | }
24 | ]
25 | };
26 |
--------------------------------------------------------------------------------
/6-practice/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/6-practice/README.md:
--------------------------------------------------------------------------------
1 | # 5-vuex
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Run your unit tests
19 | ```
20 | npm run test:unit
21 | ```
22 |
23 | ### Lints and fixes files
24 | ```
25 | npm run lint
26 | ```
27 |
28 | ### Customize configuration
29 | See [Configuration Reference](https://cli.vuejs.org/config/).
30 |
--------------------------------------------------------------------------------
/6-practice/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"]
3 | };
4 |
--------------------------------------------------------------------------------
/6-practice/jest.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | preset: "@vue/cli-plugin-unit-jest"
3 | };
4 |
--------------------------------------------------------------------------------
/6-practice/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "6-practice",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "test:unit": "vue-cli-service test:unit",
9 | "lint": "vue-cli-service lint"
10 | },
11 | "dependencies": {
12 | "axios": "^0.21.1",
13 | "core-js": "^3.6.5",
14 | "vue": "^2.6.11",
15 | "vue-router": "^3.2.0",
16 | "vuex": "^3.4.0"
17 | },
18 | "devDependencies": {
19 | "@vue/cli-plugin-babel": "~4.5.0",
20 | "@vue/cli-plugin-eslint": "~4.5.0",
21 | "@vue/cli-plugin-router": "~4.5.0",
22 | "@vue/cli-plugin-unit-jest": "~4.5.0",
23 | "@vue/cli-plugin-vuex": "~4.5.0",
24 | "@vue/cli-service": "~4.5.0",
25 | "@vue/eslint-config-prettier": "^6.0.0",
26 | "@vue/test-utils": "^1.0.3",
27 | "babel-eslint": "^10.1.0",
28 | "eslint": "^6.7.2",
29 | "eslint-plugin-prettier": "^3.1.3",
30 | "eslint-plugin-vue": "^6.2.2",
31 | "prettier": "^1.19.1",
32 | "vue-template-compiler": "^2.6.11"
33 | }
34 | }
35 |
--------------------------------------------------------------------------------
/6-practice/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/6-practice/public/favicon.ico
--------------------------------------------------------------------------------
/6-practice/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/6-practice/serve/data.js:
--------------------------------------------------------------------------------
1 | const formData = [
2 | {
3 | id: 1,
4 | username: "小红",
5 | email: "xiaohong@qq.com",
6 | gender: "女",
7 | hobby: ["弹琴", "读书"],
8 | },
9 | {
10 | id: 2,
11 | username: "小黑",
12 | email: "xiaohei@qq.com",
13 | gender: "男",
14 | hobby: ["篮球", "读书", "编程"],
15 | },
16 | {
17 | id: 3,
18 | username: "小亮",
19 | email: "xiaoliang@qq.com",
20 | gender: "男",
21 | hobby: ["篮球", "读书", "编程"],
22 | },
23 | {
24 | id: 4,
25 | username: "小五",
26 | email: "xiaowu@qq.com",
27 | gender: "男",
28 | hobby: ["篮球", "读书", "编程"],
29 | },
30 | {
31 | id: 5,
32 | username: "小海",
33 | email: "aaa@qq.com",
34 | gender: "男",
35 | hobby: ["篮球", "读书", "编程"],
36 | },
37 | {
38 | id: 6,
39 | username: "小紫",
40 | email: "aaa@qq.com",
41 | gender: "男",
42 | hobby: ["篮球", "读书", "编程"],
43 | },
44 | ];
45 |
46 | module.exports = {
47 | getData() {
48 | return formData;
49 | },
50 |
51 | modifyData({ id, hobby, username, email, gender }) {
52 | const rawData = formData.find((d) => d.id == id);
53 | if (!rawData) {
54 | console.log("无效的id");
55 | return;
56 | }
57 | if (hobby) rawData.hobby = hobby;
58 | if (username) rawData.username = username;
59 | if (email) rawData.email = email;
60 | if (gender) rawData.gender = gender;
61 | },
62 |
63 | deleteData(id) {
64 | const index = formData.findIndex((d) => d.id == id);
65 | formData.splice(index, 1);
66 | },
67 | };
68 |
--------------------------------------------------------------------------------
/6-practice/serve/index.js:
--------------------------------------------------------------------------------
1 | const Koa = require("koa");
2 | const Router = require("koa-router");
3 | const serve = require("koa-static");
4 | const koaBody = require("koa-body");
5 | const formData = require("./data.js");
6 |
7 | const app = new Koa();
8 |
9 | app.use(serve(__dirname + "/static"));
10 |
11 | app.use(
12 | koaBody({
13 | multipart: true,
14 | })
15 | );
16 |
17 | const router = new Router();
18 |
19 | // 获取 form 表单数据
20 | router.get("/data", (ctx) => {
21 | ctx.body = {
22 | state: 1,
23 | data: formData.getData(),
24 | };
25 | });
26 |
27 | // 数据编辑
28 | router.post("/modify", (ctx) => {
29 | const { id, hobby, username, email, gender } = ctx.request.body;
30 | formData.modifyData({ id, hobby, username, email, gender });
31 | ctx.body = { state: 1, data: formData.getData() };
32 | });
33 |
34 | // 数据删除
35 | router.get("/delete", (ctx) => {
36 | const { id } = ctx.query;
37 | console.log(id)
38 | formData.deleteData(id);
39 | ctx.body = { state: 1, data: formData.getData() };
40 | });
41 |
42 | app.use(router.routes());
43 |
44 | app.listen(8081, () => {
45 | console.log("open server localhost:8081");
46 | });
47 |
--------------------------------------------------------------------------------
/6-practice/serve/package-lock.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serve",
3 | "version": "1.0.0",
4 | "lockfileVersion": 2,
5 | "requires": true,
6 | "packages": {
7 | "": {
8 | "version": "1.0.0",
9 | "license": "ISC",
10 | "dependencies": {
11 | "koa": "^2.13.1",
12 | "koa-body": "^4.2.0",
13 | "koa-router": "^10.0.0",
14 | "koa-static": "^5.0.0"
15 | }
16 | },
17 | "node_modules/@types/formidable": {
18 | "version": "1.0.32",
19 | "resolved": "https://registry.npm.taobao.org/@types/formidable/download/@types/formidable-1.0.32.tgz",
20 | "integrity": "sha1-2afu+6qZWkSG7E45YOlVLmiz8zw=",
21 | "dependencies": {
22 | "@types/node": "*"
23 | }
24 | },
25 | "node_modules/@types/node": {
26 | "version": "14.14.20",
27 | "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.14.20.tgz",
28 | "integrity": "sha1-95dIY+3SHR+KSUpz6OKzZYYVw0A="
29 | },
30 | "node_modules/accepts": {
31 | "version": "1.3.7",
32 | "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz",
33 | "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=",
34 | "dependencies": {
35 | "mime-types": "~2.1.24",
36 | "negotiator": "0.6.2"
37 | },
38 | "engines": {
39 | "node": ">= 0.6"
40 | }
41 | },
42 | "node_modules/any-promise": {
43 | "version": "1.3.0",
44 | "resolved": "https://registry.npm.taobao.org/any-promise/download/any-promise-1.3.0.tgz",
45 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
46 | },
47 | "node_modules/bytes": {
48 | "version": "3.1.0",
49 | "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz",
50 | "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY=",
51 | "engines": {
52 | "node": ">= 0.8"
53 | }
54 | },
55 | "node_modules/cache-content-type": {
56 | "version": "1.0.1",
57 | "resolved": "https://registry.npm.taobao.org/cache-content-type/download/cache-content-type-1.0.1.tgz",
58 | "integrity": "sha1-A1zeKwjuISn0qDFeqPAKANuhRTw=",
59 | "dependencies": {
60 | "mime-types": "^2.1.18",
61 | "ylru": "^1.2.0"
62 | },
63 | "engines": {
64 | "node": ">= 6.0.0"
65 | }
66 | },
67 | "node_modules/co": {
68 | "version": "4.6.0",
69 | "resolved": "https://registry.npm.taobao.org/co/download/co-4.6.0.tgz",
70 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=",
71 | "engines": {
72 | "iojs": ">= 1.0.0",
73 | "node": ">= 0.12.0"
74 | }
75 | },
76 | "node_modules/co-body": {
77 | "version": "5.2.0",
78 | "resolved": "https://registry.npm.taobao.org/co-body/download/co-body-5.2.0.tgz?cache=0&sync_timestamp=1602173624065&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fco-body%2Fdownload%2Fco-body-5.2.0.tgz",
79 | "integrity": "sha1-WgpljEYCkTHg46MG9nZHMC9xwSQ=",
80 | "dependencies": {
81 | "inflation": "^2.0.0",
82 | "qs": "^6.4.0",
83 | "raw-body": "^2.2.0",
84 | "type-is": "^1.6.14"
85 | }
86 | },
87 | "node_modules/content-disposition": {
88 | "version": "0.5.3",
89 | "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz",
90 | "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=",
91 | "dependencies": {
92 | "safe-buffer": "5.1.2"
93 | },
94 | "engines": {
95 | "node": ">= 0.6"
96 | }
97 | },
98 | "node_modules/content-type": {
99 | "version": "1.0.4",
100 | "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz",
101 | "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js=",
102 | "engines": {
103 | "node": ">= 0.6"
104 | }
105 | },
106 | "node_modules/cookies": {
107 | "version": "0.8.0",
108 | "resolved": "https://registry.npm.taobao.org/cookies/download/cookies-0.8.0.tgz",
109 | "integrity": "sha1-EpPOSzkXQKhAbjyYcOgoxLVPP5A=",
110 | "dependencies": {
111 | "depd": "~2.0.0",
112 | "keygrip": "~1.1.0"
113 | },
114 | "engines": {
115 | "node": ">= 0.8"
116 | }
117 | },
118 | "node_modules/cookies/node_modules/depd": {
119 | "version": "2.0.0",
120 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-2.0.0.tgz",
121 | "integrity": "sha1-tpYWPMdXVg0JzyLMj60Vcbeedt8=",
122 | "engines": {
123 | "node": ">= 0.8"
124 | }
125 | },
126 | "node_modules/debug": {
127 | "version": "4.3.1",
128 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566551397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz",
129 | "integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=",
130 | "dependencies": {
131 | "ms": "2.1.2"
132 | },
133 | "engines": {
134 | "node": ">=6.0"
135 | }
136 | },
137 | "node_modules/deep-equal": {
138 | "version": "1.0.1",
139 | "resolved": "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.0.1.tgz?cache=0&sync_timestamp=1606860101281&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeep-equal%2Fdownload%2Fdeep-equal-1.0.1.tgz",
140 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
141 | },
142 | "node_modules/delegates": {
143 | "version": "1.0.0",
144 | "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz",
145 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
146 | },
147 | "node_modules/depd": {
148 | "version": "1.1.2",
149 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz",
150 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
151 | "engines": {
152 | "node": ">= 0.6"
153 | }
154 | },
155 | "node_modules/destroy": {
156 | "version": "1.0.4",
157 | "resolved": "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz",
158 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
159 | },
160 | "node_modules/ee-first": {
161 | "version": "1.1.1",
162 | "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
163 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
164 | },
165 | "node_modules/encodeurl": {
166 | "version": "1.0.2",
167 | "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz",
168 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
169 | "engines": {
170 | "node": ">= 0.8"
171 | }
172 | },
173 | "node_modules/escape-html": {
174 | "version": "1.0.3",
175 | "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz",
176 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
177 | },
178 | "node_modules/formidable": {
179 | "version": "1.2.2",
180 | "resolved": "https://registry.npm.taobao.org/formidable/download/formidable-1.2.2.tgz",
181 | "integrity": "sha1-v2muopcpgmdfAIZTQrmCmG9rjdk="
182 | },
183 | "node_modules/fresh": {
184 | "version": "0.5.2",
185 | "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz",
186 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
187 | "engines": {
188 | "node": ">= 0.6"
189 | }
190 | },
191 | "node_modules/http-assert": {
192 | "version": "1.4.1",
193 | "resolved": "https://registry.npm.taobao.org/http-assert/download/http-assert-1.4.1.tgz",
194 | "integrity": "sha1-xfcl1neqfoc+9zYZm4lobM6zeHg=",
195 | "dependencies": {
196 | "deep-equal": "~1.0.1",
197 | "http-errors": "~1.7.2"
198 | },
199 | "engines": {
200 | "node": ">= 0.8"
201 | }
202 | },
203 | "node_modules/http-assert/node_modules/http-errors": {
204 | "version": "1.7.3",
205 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.3.tgz",
206 | "integrity": "sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY=",
207 | "dependencies": {
208 | "depd": "~1.1.2",
209 | "inherits": "2.0.4",
210 | "setprototypeof": "1.1.1",
211 | "statuses": ">= 1.5.0 < 2",
212 | "toidentifier": "1.0.0"
213 | },
214 | "engines": {
215 | "node": ">= 0.6"
216 | }
217 | },
218 | "node_modules/http-assert/node_modules/setprototypeof": {
219 | "version": "1.1.1",
220 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz",
221 | "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM="
222 | },
223 | "node_modules/http-errors": {
224 | "version": "1.8.0",
225 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.8.0.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.8.0.tgz",
226 | "integrity": "sha1-ddG75JfhBE9R5O6ecEpi8o0zZQc=",
227 | "dependencies": {
228 | "depd": "~1.1.2",
229 | "inherits": "2.0.4",
230 | "setprototypeof": "1.2.0",
231 | "statuses": ">= 1.5.0 < 2",
232 | "toidentifier": "1.0.0"
233 | },
234 | "engines": {
235 | "node": ">= 0.6"
236 | }
237 | },
238 | "node_modules/iconv-lite": {
239 | "version": "0.4.24",
240 | "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1594184325364&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz",
241 | "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
242 | "dependencies": {
243 | "safer-buffer": ">= 2.1.2 < 3"
244 | },
245 | "engines": {
246 | "node": ">=0.10.0"
247 | }
248 | },
249 | "node_modules/inflation": {
250 | "version": "2.0.0",
251 | "resolved": "https://registry.npm.taobao.org/inflation/download/inflation-2.0.0.tgz",
252 | "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8=",
253 | "engines": {
254 | "node": ">= 0.8.0"
255 | }
256 | },
257 | "node_modules/inherits": {
258 | "version": "2.0.4",
259 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz",
260 | "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w="
261 | },
262 | "node_modules/is-generator-function": {
263 | "version": "1.0.8",
264 | "resolved": "https://registry.npm.taobao.org/is-generator-function/download/is-generator-function-1.0.8.tgz?cache=0&sync_timestamp=1606926808749&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-generator-function%2Fdownload%2Fis-generator-function-1.0.8.tgz",
265 | "integrity": "sha1-37XCsSDgKwqNnSxoBs1WIaqSL3s=",
266 | "engines": {
267 | "node": ">= 0.4"
268 | }
269 | },
270 | "node_modules/keygrip": {
271 | "version": "1.1.0",
272 | "resolved": "https://registry.npm.taobao.org/keygrip/download/keygrip-1.1.0.tgz",
273 | "integrity": "sha1-hxsWgdXhWcYqRFsMdLYV4JF+ciY=",
274 | "dependencies": {
275 | "tsscmp": "1.0.6"
276 | },
277 | "engines": {
278 | "node": ">= 0.6"
279 | }
280 | },
281 | "node_modules/koa": {
282 | "version": "2.13.1",
283 | "resolved": "https://registry.npm.taobao.org/koa/download/koa-2.13.1.tgz?cache=0&sync_timestamp=1609771532233&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa%2Fdownload%2Fkoa-2.13.1.tgz",
284 | "integrity": "sha1-YnUXKHWye8/h1FQ1altrn1qbEFE=",
285 | "dependencies": {
286 | "accepts": "^1.3.5",
287 | "cache-content-type": "^1.0.0",
288 | "content-disposition": "~0.5.2",
289 | "content-type": "^1.0.4",
290 | "cookies": "~0.8.0",
291 | "debug": "~3.1.0",
292 | "delegates": "^1.0.0",
293 | "depd": "^2.0.0",
294 | "destroy": "^1.0.4",
295 | "encodeurl": "^1.0.2",
296 | "escape-html": "^1.0.3",
297 | "fresh": "~0.5.2",
298 | "http-assert": "^1.3.0",
299 | "http-errors": "^1.6.3",
300 | "is-generator-function": "^1.0.7",
301 | "koa-compose": "^4.1.0",
302 | "koa-convert": "^1.2.0",
303 | "on-finished": "^2.3.0",
304 | "only": "~0.0.2",
305 | "parseurl": "^1.3.2",
306 | "statuses": "^1.5.0",
307 | "type-is": "^1.6.16",
308 | "vary": "^1.1.2"
309 | },
310 | "engines": {
311 | "node": "^4.8.4 || ^6.10.1 || ^7.10.1 || >= 8.1.4"
312 | }
313 | },
314 | "node_modules/koa-body": {
315 | "version": "4.2.0",
316 | "resolved": "https://registry.npm.taobao.org/koa-body/download/koa-body-4.2.0.tgz",
317 | "integrity": "sha1-NyKSCLggdhrKWCLRTF/FXO4xsm8=",
318 | "dependencies": {
319 | "@types/formidable": "^1.0.31",
320 | "co-body": "^5.1.1",
321 | "formidable": "^1.1.1"
322 | }
323 | },
324 | "node_modules/koa-compose": {
325 | "version": "4.1.0",
326 | "resolved": "https://registry.npm.taobao.org/koa-compose/download/koa-compose-4.1.0.tgz",
327 | "integrity": "sha1-UHMGuTcZAdtBEhyBLpI9DWfT6Hc="
328 | },
329 | "node_modules/koa-convert": {
330 | "version": "1.2.0",
331 | "resolved": "https://registry.npm.taobao.org/koa-convert/download/koa-convert-1.2.0.tgz?cache=0&sync_timestamp=1599761700662&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa-convert%2Fdownload%2Fkoa-convert-1.2.0.tgz",
332 | "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=",
333 | "dependencies": {
334 | "co": "^4.6.0",
335 | "koa-compose": "^3.0.0"
336 | },
337 | "engines": {
338 | "node": ">= 4"
339 | }
340 | },
341 | "node_modules/koa-convert/node_modules/koa-compose": {
342 | "version": "3.2.1",
343 | "resolved": "https://registry.npm.taobao.org/koa-compose/download/koa-compose-3.2.1.tgz",
344 | "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
345 | "dependencies": {
346 | "any-promise": "^1.1.0"
347 | }
348 | },
349 | "node_modules/koa-router": {
350 | "version": "10.0.0",
351 | "resolved": "https://registry.npm.taobao.org/koa-router/download/koa-router-10.0.0.tgz",
352 | "integrity": "sha1-e8dqAxCFcx5h/JLBaDaHsvRN5qQ=",
353 | "dependencies": {
354 | "debug": "^4.1.1",
355 | "http-errors": "^1.7.3",
356 | "koa-compose": "^4.1.0",
357 | "methods": "^1.1.2",
358 | "path-to-regexp": "^6.1.0"
359 | },
360 | "engines": {
361 | "node": ">= 8.0.0"
362 | }
363 | },
364 | "node_modules/koa-send": {
365 | "version": "5.0.1",
366 | "resolved": "https://registry.npm.taobao.org/koa-send/download/koa-send-5.0.1.tgz?cache=0&sync_timestamp=1594224361920&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa-send%2Fdownload%2Fkoa-send-5.0.1.tgz",
367 | "integrity": "sha1-Odzuv6+zldDWC+r/ujpwtPVD/nk=",
368 | "dependencies": {
369 | "debug": "^4.1.1",
370 | "http-errors": "^1.7.3",
371 | "resolve-path": "^1.4.0"
372 | },
373 | "engines": {
374 | "node": ">= 8"
375 | }
376 | },
377 | "node_modules/koa-static": {
378 | "version": "5.0.0",
379 | "resolved": "https://registry.npm.taobao.org/koa-static/download/koa-static-5.0.0.tgz",
380 | "integrity": "sha1-XpL8lrU3rVIZ9CUxnJW2R3J3aUM=",
381 | "dependencies": {
382 | "debug": "^3.1.0",
383 | "koa-send": "^5.0.0"
384 | },
385 | "engines": {
386 | "node": ">= 7.6.0"
387 | }
388 | },
389 | "node_modules/koa-static/node_modules/debug": {
390 | "version": "3.2.7",
391 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1607566551397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz",
392 | "integrity": "sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o=",
393 | "dependencies": {
394 | "ms": "^2.1.1"
395 | }
396 | },
397 | "node_modules/koa/node_modules/debug": {
398 | "version": "3.1.0",
399 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz?cache=0&sync_timestamp=1607566551397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.1.0.tgz",
400 | "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
401 | "dependencies": {
402 | "ms": "2.0.0"
403 | }
404 | },
405 | "node_modules/koa/node_modules/depd": {
406 | "version": "2.0.0",
407 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-2.0.0.tgz",
408 | "integrity": "sha1-tpYWPMdXVg0JzyLMj60Vcbeedt8=",
409 | "engines": {
410 | "node": ">= 0.8"
411 | }
412 | },
413 | "node_modules/koa/node_modules/ms": {
414 | "version": "2.0.0",
415 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433856030&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
416 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
417 | },
418 | "node_modules/media-typer": {
419 | "version": "0.3.0",
420 | "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
421 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
422 | "engines": {
423 | "node": ">= 0.6"
424 | }
425 | },
426 | "node_modules/methods": {
427 | "version": "1.1.2",
428 | "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz",
429 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
430 | "engines": {
431 | "node": ">= 0.6"
432 | }
433 | },
434 | "node_modules/mime-db": {
435 | "version": "1.45.0",
436 | "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.45.0.tgz?cache=0&sync_timestamp=1600831212519&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.45.0.tgz",
437 | "integrity": "sha1-zO7aIczXw6dF66LezVXUtz54eeo=",
438 | "engines": {
439 | "node": ">= 0.6"
440 | }
441 | },
442 | "node_modules/mime-types": {
443 | "version": "2.1.28",
444 | "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.28.tgz?cache=0&sync_timestamp=1609559936613&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-types%2Fdownload%2Fmime-types-2.1.28.tgz",
445 | "integrity": "sha1-EWDEdX6rLFNjiI4AUnPs950qDs0=",
446 | "dependencies": {
447 | "mime-db": "1.45.0"
448 | },
449 | "engines": {
450 | "node": ">= 0.6"
451 | }
452 | },
453 | "node_modules/ms": {
454 | "version": "2.1.2",
455 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1607433856030&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
456 | "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
457 | },
458 | "node_modules/negotiator": {
459 | "version": "0.6.2",
460 | "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz",
461 | "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs=",
462 | "engines": {
463 | "node": ">= 0.6"
464 | }
465 | },
466 | "node_modules/on-finished": {
467 | "version": "2.3.0",
468 | "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz",
469 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
470 | "dependencies": {
471 | "ee-first": "1.1.1"
472 | },
473 | "engines": {
474 | "node": ">= 0.8"
475 | }
476 | },
477 | "node_modules/only": {
478 | "version": "0.0.2",
479 | "resolved": "https://registry.npm.taobao.org/only/download/only-0.0.2.tgz",
480 | "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
481 | },
482 | "node_modules/parseurl": {
483 | "version": "1.3.3",
484 | "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz",
485 | "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ=",
486 | "engines": {
487 | "node": ">= 0.8"
488 | }
489 | },
490 | "node_modules/path-is-absolute": {
491 | "version": "1.0.1",
492 | "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
493 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=",
494 | "engines": {
495 | "node": ">=0.10.0"
496 | }
497 | },
498 | "node_modules/path-to-regexp": {
499 | "version": "6.2.0",
500 | "resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-6.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-to-regexp%2Fdownload%2Fpath-to-regexp-6.2.0.tgz",
501 | "integrity": "sha1-97OAMzYQTDRoia3s5hRmkjBkXzg="
502 | },
503 | "node_modules/qs": {
504 | "version": "6.9.6",
505 | "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.9.6.tgz?cache=0&sync_timestamp=1610598174727&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.9.6.tgz",
506 | "integrity": "sha1-Ju08gkOkMbKSSsqEzJBHHzXVoO4=",
507 | "engines": {
508 | "node": ">=0.6"
509 | }
510 | },
511 | "node_modules/raw-body": {
512 | "version": "2.4.1",
513 | "resolved": "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.1.tgz",
514 | "integrity": "sha1-MKyC+Yu1rowVLmcUnayNVRU7Fow=",
515 | "dependencies": {
516 | "bytes": "3.1.0",
517 | "http-errors": "1.7.3",
518 | "iconv-lite": "0.4.24",
519 | "unpipe": "1.0.0"
520 | },
521 | "engines": {
522 | "node": ">= 0.8"
523 | }
524 | },
525 | "node_modules/raw-body/node_modules/http-errors": {
526 | "version": "1.7.3",
527 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.3.tgz",
528 | "integrity": "sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY=",
529 | "dependencies": {
530 | "depd": "~1.1.2",
531 | "inherits": "2.0.4",
532 | "setprototypeof": "1.1.1",
533 | "statuses": ">= 1.5.0 < 2",
534 | "toidentifier": "1.0.0"
535 | },
536 | "engines": {
537 | "node": ">= 0.6"
538 | }
539 | },
540 | "node_modules/raw-body/node_modules/setprototypeof": {
541 | "version": "1.1.1",
542 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz",
543 | "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM="
544 | },
545 | "node_modules/resolve-path": {
546 | "version": "1.4.0",
547 | "resolved": "https://registry.npm.taobao.org/resolve-path/download/resolve-path-1.4.0.tgz",
548 | "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
549 | "dependencies": {
550 | "http-errors": "~1.6.2",
551 | "path-is-absolute": "1.0.1"
552 | },
553 | "engines": {
554 | "node": ">= 0.8"
555 | }
556 | },
557 | "node_modules/resolve-path/node_modules/http-errors": {
558 | "version": "1.6.3",
559 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.6.3.tgz",
560 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
561 | "dependencies": {
562 | "depd": "~1.1.2",
563 | "inherits": "2.0.3",
564 | "setprototypeof": "1.1.0",
565 | "statuses": ">= 1.4.0 < 2"
566 | },
567 | "engines": {
568 | "node": ">= 0.6"
569 | }
570 | },
571 | "node_modules/resolve-path/node_modules/inherits": {
572 | "version": "2.0.3",
573 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz",
574 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
575 | },
576 | "node_modules/resolve-path/node_modules/setprototypeof": {
577 | "version": "1.1.0",
578 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz",
579 | "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY="
580 | },
581 | "node_modules/safe-buffer": {
582 | "version": "5.1.2",
583 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
584 | "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
585 | },
586 | "node_modules/safer-buffer": {
587 | "version": "2.1.2",
588 | "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz",
589 | "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
590 | },
591 | "node_modules/setprototypeof": {
592 | "version": "1.2.0",
593 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.2.0.tgz",
594 | "integrity": "sha1-ZsmiSnP5/CjL5msJ/tPTPcrxtCQ="
595 | },
596 | "node_modules/statuses": {
597 | "version": "1.5.0",
598 | "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1609654438540&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz",
599 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
600 | "engines": {
601 | "node": ">= 0.6"
602 | }
603 | },
604 | "node_modules/toidentifier": {
605 | "version": "1.0.0",
606 | "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz",
607 | "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM=",
608 | "engines": {
609 | "node": ">=0.6"
610 | }
611 | },
612 | "node_modules/tsscmp": {
613 | "version": "1.0.6",
614 | "resolved": "https://registry.npm.taobao.org/tsscmp/download/tsscmp-1.0.6.tgz",
615 | "integrity": "sha1-hbmVg6w1iexL/vgltQAKqRHWBes=",
616 | "engines": {
617 | "node": ">=0.6.x"
618 | }
619 | },
620 | "node_modules/type-is": {
621 | "version": "1.6.18",
622 | "resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz",
623 | "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=",
624 | "dependencies": {
625 | "media-typer": "0.3.0",
626 | "mime-types": "~2.1.24"
627 | },
628 | "engines": {
629 | "node": ">= 0.6"
630 | }
631 | },
632 | "node_modules/unpipe": {
633 | "version": "1.0.0",
634 | "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz",
635 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
636 | "engines": {
637 | "node": ">= 0.8"
638 | }
639 | },
640 | "node_modules/vary": {
641 | "version": "1.1.2",
642 | "resolved": "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz",
643 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
644 | "engines": {
645 | "node": ">= 0.8"
646 | }
647 | },
648 | "node_modules/ylru": {
649 | "version": "1.2.1",
650 | "resolved": "https://registry.npm.taobao.org/ylru/download/ylru-1.2.1.tgz",
651 | "integrity": "sha1-9Xa2M0FUeYnB3nuiiHYJI7J/6E8=",
652 | "engines": {
653 | "node": ">= 4.0.0"
654 | }
655 | }
656 | },
657 | "dependencies": {
658 | "@types/formidable": {
659 | "version": "1.0.32",
660 | "resolved": "https://registry.npm.taobao.org/@types/formidable/download/@types/formidable-1.0.32.tgz",
661 | "integrity": "sha1-2afu+6qZWkSG7E45YOlVLmiz8zw=",
662 | "requires": {
663 | "@types/node": "*"
664 | }
665 | },
666 | "@types/node": {
667 | "version": "14.14.20",
668 | "resolved": "https://registry.npm.taobao.org/@types/node/download/@types/node-14.14.20.tgz",
669 | "integrity": "sha1-95dIY+3SHR+KSUpz6OKzZYYVw0A="
670 | },
671 | "accepts": {
672 | "version": "1.3.7",
673 | "resolved": "https://registry.npm.taobao.org/accepts/download/accepts-1.3.7.tgz",
674 | "integrity": "sha1-UxvHJlF6OytB+FACHGzBXqq1B80=",
675 | "requires": {
676 | "mime-types": "~2.1.24",
677 | "negotiator": "0.6.2"
678 | }
679 | },
680 | "any-promise": {
681 | "version": "1.3.0",
682 | "resolved": "https://registry.npm.taobao.org/any-promise/download/any-promise-1.3.0.tgz",
683 | "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8="
684 | },
685 | "bytes": {
686 | "version": "3.1.0",
687 | "resolved": "https://registry.npm.taobao.org/bytes/download/bytes-3.1.0.tgz",
688 | "integrity": "sha1-9s95M6Ng4FiPqf3oVlHNx/gF0fY="
689 | },
690 | "cache-content-type": {
691 | "version": "1.0.1",
692 | "resolved": "https://registry.npm.taobao.org/cache-content-type/download/cache-content-type-1.0.1.tgz",
693 | "integrity": "sha1-A1zeKwjuISn0qDFeqPAKANuhRTw=",
694 | "requires": {
695 | "mime-types": "^2.1.18",
696 | "ylru": "^1.2.0"
697 | }
698 | },
699 | "co": {
700 | "version": "4.6.0",
701 | "resolved": "https://registry.npm.taobao.org/co/download/co-4.6.0.tgz",
702 | "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ="
703 | },
704 | "co-body": {
705 | "version": "5.2.0",
706 | "resolved": "https://registry.npm.taobao.org/co-body/download/co-body-5.2.0.tgz?cache=0&sync_timestamp=1602173624065&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fco-body%2Fdownload%2Fco-body-5.2.0.tgz",
707 | "integrity": "sha1-WgpljEYCkTHg46MG9nZHMC9xwSQ=",
708 | "requires": {
709 | "inflation": "^2.0.0",
710 | "qs": "^6.4.0",
711 | "raw-body": "^2.2.0",
712 | "type-is": "^1.6.14"
713 | }
714 | },
715 | "content-disposition": {
716 | "version": "0.5.3",
717 | "resolved": "https://registry.npm.taobao.org/content-disposition/download/content-disposition-0.5.3.tgz",
718 | "integrity": "sha1-4TDK9+cnkIfFYWwgB9BIVpiYT70=",
719 | "requires": {
720 | "safe-buffer": "5.1.2"
721 | }
722 | },
723 | "content-type": {
724 | "version": "1.0.4",
725 | "resolved": "https://registry.npm.taobao.org/content-type/download/content-type-1.0.4.tgz",
726 | "integrity": "sha1-4TjMdeBAxyexlm/l5fjJruJW/js="
727 | },
728 | "cookies": {
729 | "version": "0.8.0",
730 | "resolved": "https://registry.npm.taobao.org/cookies/download/cookies-0.8.0.tgz",
731 | "integrity": "sha1-EpPOSzkXQKhAbjyYcOgoxLVPP5A=",
732 | "requires": {
733 | "depd": "~2.0.0",
734 | "keygrip": "~1.1.0"
735 | },
736 | "dependencies": {
737 | "depd": {
738 | "version": "2.0.0",
739 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-2.0.0.tgz",
740 | "integrity": "sha1-tpYWPMdXVg0JzyLMj60Vcbeedt8="
741 | }
742 | }
743 | },
744 | "debug": {
745 | "version": "4.3.1",
746 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-4.3.1.tgz?cache=0&sync_timestamp=1607566551397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-4.3.1.tgz",
747 | "integrity": "sha1-8NIpxQXgxtjEmsVT0bE9wYP2su4=",
748 | "requires": {
749 | "ms": "2.1.2"
750 | }
751 | },
752 | "deep-equal": {
753 | "version": "1.0.1",
754 | "resolved": "https://registry.npm.taobao.org/deep-equal/download/deep-equal-1.0.1.tgz?cache=0&sync_timestamp=1606860101281&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdeep-equal%2Fdownload%2Fdeep-equal-1.0.1.tgz",
755 | "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU="
756 | },
757 | "delegates": {
758 | "version": "1.0.0",
759 | "resolved": "https://registry.npm.taobao.org/delegates/download/delegates-1.0.0.tgz",
760 | "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o="
761 | },
762 | "depd": {
763 | "version": "1.1.2",
764 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-1.1.2.tgz",
765 | "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
766 | },
767 | "destroy": {
768 | "version": "1.0.4",
769 | "resolved": "https://registry.npm.taobao.org/destroy/download/destroy-1.0.4.tgz",
770 | "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
771 | },
772 | "ee-first": {
773 | "version": "1.1.1",
774 | "resolved": "https://registry.npm.taobao.org/ee-first/download/ee-first-1.1.1.tgz",
775 | "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
776 | },
777 | "encodeurl": {
778 | "version": "1.0.2",
779 | "resolved": "https://registry.npm.taobao.org/encodeurl/download/encodeurl-1.0.2.tgz",
780 | "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
781 | },
782 | "escape-html": {
783 | "version": "1.0.3",
784 | "resolved": "https://registry.npm.taobao.org/escape-html/download/escape-html-1.0.3.tgz",
785 | "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
786 | },
787 | "formidable": {
788 | "version": "1.2.2",
789 | "resolved": "https://registry.npm.taobao.org/formidable/download/formidable-1.2.2.tgz",
790 | "integrity": "sha1-v2muopcpgmdfAIZTQrmCmG9rjdk="
791 | },
792 | "fresh": {
793 | "version": "0.5.2",
794 | "resolved": "https://registry.npm.taobao.org/fresh/download/fresh-0.5.2.tgz",
795 | "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
796 | },
797 | "http-assert": {
798 | "version": "1.4.1",
799 | "resolved": "https://registry.npm.taobao.org/http-assert/download/http-assert-1.4.1.tgz",
800 | "integrity": "sha1-xfcl1neqfoc+9zYZm4lobM6zeHg=",
801 | "requires": {
802 | "deep-equal": "~1.0.1",
803 | "http-errors": "~1.7.2"
804 | },
805 | "dependencies": {
806 | "http-errors": {
807 | "version": "1.7.3",
808 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.3.tgz",
809 | "integrity": "sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY=",
810 | "requires": {
811 | "depd": "~1.1.2",
812 | "inherits": "2.0.4",
813 | "setprototypeof": "1.1.1",
814 | "statuses": ">= 1.5.0 < 2",
815 | "toidentifier": "1.0.0"
816 | }
817 | },
818 | "setprototypeof": {
819 | "version": "1.1.1",
820 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz",
821 | "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM="
822 | }
823 | }
824 | },
825 | "http-errors": {
826 | "version": "1.8.0",
827 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.8.0.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.8.0.tgz",
828 | "integrity": "sha1-ddG75JfhBE9R5O6ecEpi8o0zZQc=",
829 | "requires": {
830 | "depd": "~1.1.2",
831 | "inherits": "2.0.4",
832 | "setprototypeof": "1.2.0",
833 | "statuses": ">= 1.5.0 < 2",
834 | "toidentifier": "1.0.0"
835 | }
836 | },
837 | "iconv-lite": {
838 | "version": "0.4.24",
839 | "resolved": "https://registry.npm.taobao.org/iconv-lite/download/iconv-lite-0.4.24.tgz?cache=0&sync_timestamp=1594184325364&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Ficonv-lite%2Fdownload%2Ficonv-lite-0.4.24.tgz",
840 | "integrity": "sha1-ICK0sl+93CHS9SSXSkdKr+czkIs=",
841 | "requires": {
842 | "safer-buffer": ">= 2.1.2 < 3"
843 | }
844 | },
845 | "inflation": {
846 | "version": "2.0.0",
847 | "resolved": "https://registry.npm.taobao.org/inflation/download/inflation-2.0.0.tgz",
848 | "integrity": "sha1-i0F+R8KPklpFEz2RTKH9OJEH8w8="
849 | },
850 | "inherits": {
851 | "version": "2.0.4",
852 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.4.tgz",
853 | "integrity": "sha1-D6LGT5MpF8NDOg3tVTY6rjdBa3w="
854 | },
855 | "is-generator-function": {
856 | "version": "1.0.8",
857 | "resolved": "https://registry.npm.taobao.org/is-generator-function/download/is-generator-function-1.0.8.tgz?cache=0&sync_timestamp=1606926808749&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fis-generator-function%2Fdownload%2Fis-generator-function-1.0.8.tgz",
858 | "integrity": "sha1-37XCsSDgKwqNnSxoBs1WIaqSL3s="
859 | },
860 | "keygrip": {
861 | "version": "1.1.0",
862 | "resolved": "https://registry.npm.taobao.org/keygrip/download/keygrip-1.1.0.tgz",
863 | "integrity": "sha1-hxsWgdXhWcYqRFsMdLYV4JF+ciY=",
864 | "requires": {
865 | "tsscmp": "1.0.6"
866 | }
867 | },
868 | "koa": {
869 | "version": "2.13.1",
870 | "resolved": "https://registry.npm.taobao.org/koa/download/koa-2.13.1.tgz?cache=0&sync_timestamp=1609771532233&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa%2Fdownload%2Fkoa-2.13.1.tgz",
871 | "integrity": "sha1-YnUXKHWye8/h1FQ1altrn1qbEFE=",
872 | "requires": {
873 | "accepts": "^1.3.5",
874 | "cache-content-type": "^1.0.0",
875 | "content-disposition": "~0.5.2",
876 | "content-type": "^1.0.4",
877 | "cookies": "~0.8.0",
878 | "debug": "~3.1.0",
879 | "delegates": "^1.0.0",
880 | "depd": "^2.0.0",
881 | "destroy": "^1.0.4",
882 | "encodeurl": "^1.0.2",
883 | "escape-html": "^1.0.3",
884 | "fresh": "~0.5.2",
885 | "http-assert": "^1.3.0",
886 | "http-errors": "^1.6.3",
887 | "is-generator-function": "^1.0.7",
888 | "koa-compose": "^4.1.0",
889 | "koa-convert": "^1.2.0",
890 | "on-finished": "^2.3.0",
891 | "only": "~0.0.2",
892 | "parseurl": "^1.3.2",
893 | "statuses": "^1.5.0",
894 | "type-is": "^1.6.16",
895 | "vary": "^1.1.2"
896 | },
897 | "dependencies": {
898 | "debug": {
899 | "version": "3.1.0",
900 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.1.0.tgz?cache=0&sync_timestamp=1607566551397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.1.0.tgz",
901 | "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=",
902 | "requires": {
903 | "ms": "2.0.0"
904 | }
905 | },
906 | "depd": {
907 | "version": "2.0.0",
908 | "resolved": "https://registry.npm.taobao.org/depd/download/depd-2.0.0.tgz",
909 | "integrity": "sha1-tpYWPMdXVg0JzyLMj60Vcbeedt8="
910 | },
911 | "ms": {
912 | "version": "2.0.0",
913 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.0.0.tgz?cache=0&sync_timestamp=1607433856030&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.0.0.tgz",
914 | "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
915 | }
916 | }
917 | },
918 | "koa-body": {
919 | "version": "4.2.0",
920 | "resolved": "https://registry.npm.taobao.org/koa-body/download/koa-body-4.2.0.tgz",
921 | "integrity": "sha1-NyKSCLggdhrKWCLRTF/FXO4xsm8=",
922 | "requires": {
923 | "@types/formidable": "^1.0.31",
924 | "co-body": "^5.1.1",
925 | "formidable": "^1.1.1"
926 | }
927 | },
928 | "koa-compose": {
929 | "version": "4.1.0",
930 | "resolved": "https://registry.npm.taobao.org/koa-compose/download/koa-compose-4.1.0.tgz",
931 | "integrity": "sha1-UHMGuTcZAdtBEhyBLpI9DWfT6Hc="
932 | },
933 | "koa-convert": {
934 | "version": "1.2.0",
935 | "resolved": "https://registry.npm.taobao.org/koa-convert/download/koa-convert-1.2.0.tgz?cache=0&sync_timestamp=1599761700662&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa-convert%2Fdownload%2Fkoa-convert-1.2.0.tgz",
936 | "integrity": "sha1-2kCHXfSd4FOQmNFwC1CCDOvNIdA=",
937 | "requires": {
938 | "co": "^4.6.0",
939 | "koa-compose": "^3.0.0"
940 | },
941 | "dependencies": {
942 | "koa-compose": {
943 | "version": "3.2.1",
944 | "resolved": "https://registry.npm.taobao.org/koa-compose/download/koa-compose-3.2.1.tgz",
945 | "integrity": "sha1-qFzLQLfZhtjlo0Wzoazo6rz1Tec=",
946 | "requires": {
947 | "any-promise": "^1.1.0"
948 | }
949 | }
950 | }
951 | },
952 | "koa-router": {
953 | "version": "10.0.0",
954 | "resolved": "https://registry.npm.taobao.org/koa-router/download/koa-router-10.0.0.tgz",
955 | "integrity": "sha1-e8dqAxCFcx5h/JLBaDaHsvRN5qQ=",
956 | "requires": {
957 | "debug": "^4.1.1",
958 | "http-errors": "^1.7.3",
959 | "koa-compose": "^4.1.0",
960 | "methods": "^1.1.2",
961 | "path-to-regexp": "^6.1.0"
962 | }
963 | },
964 | "koa-send": {
965 | "version": "5.0.1",
966 | "resolved": "https://registry.npm.taobao.org/koa-send/download/koa-send-5.0.1.tgz?cache=0&sync_timestamp=1594224361920&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fkoa-send%2Fdownload%2Fkoa-send-5.0.1.tgz",
967 | "integrity": "sha1-Odzuv6+zldDWC+r/ujpwtPVD/nk=",
968 | "requires": {
969 | "debug": "^4.1.1",
970 | "http-errors": "^1.7.3",
971 | "resolve-path": "^1.4.0"
972 | }
973 | },
974 | "koa-static": {
975 | "version": "5.0.0",
976 | "resolved": "https://registry.npm.taobao.org/koa-static/download/koa-static-5.0.0.tgz",
977 | "integrity": "sha1-XpL8lrU3rVIZ9CUxnJW2R3J3aUM=",
978 | "requires": {
979 | "debug": "^3.1.0",
980 | "koa-send": "^5.0.0"
981 | },
982 | "dependencies": {
983 | "debug": {
984 | "version": "3.2.7",
985 | "resolved": "https://registry.npm.taobao.org/debug/download/debug-3.2.7.tgz?cache=0&sync_timestamp=1607566551397&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fdebug%2Fdownload%2Fdebug-3.2.7.tgz",
986 | "integrity": "sha1-clgLfpFF+zm2Z2+cXl+xALk0F5o=",
987 | "requires": {
988 | "ms": "^2.1.1"
989 | }
990 | }
991 | }
992 | },
993 | "media-typer": {
994 | "version": "0.3.0",
995 | "resolved": "https://registry.npm.taobao.org/media-typer/download/media-typer-0.3.0.tgz",
996 | "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
997 | },
998 | "methods": {
999 | "version": "1.1.2",
1000 | "resolved": "https://registry.npm.taobao.org/methods/download/methods-1.1.2.tgz",
1001 | "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
1002 | },
1003 | "mime-db": {
1004 | "version": "1.45.0",
1005 | "resolved": "https://registry.npm.taobao.org/mime-db/download/mime-db-1.45.0.tgz?cache=0&sync_timestamp=1600831212519&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-db%2Fdownload%2Fmime-db-1.45.0.tgz",
1006 | "integrity": "sha1-zO7aIczXw6dF66LezVXUtz54eeo="
1007 | },
1008 | "mime-types": {
1009 | "version": "2.1.28",
1010 | "resolved": "https://registry.npm.taobao.org/mime-types/download/mime-types-2.1.28.tgz?cache=0&sync_timestamp=1609559936613&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmime-types%2Fdownload%2Fmime-types-2.1.28.tgz",
1011 | "integrity": "sha1-EWDEdX6rLFNjiI4AUnPs950qDs0=",
1012 | "requires": {
1013 | "mime-db": "1.45.0"
1014 | }
1015 | },
1016 | "ms": {
1017 | "version": "2.1.2",
1018 | "resolved": "https://registry.npm.taobao.org/ms/download/ms-2.1.2.tgz?cache=0&sync_timestamp=1607433856030&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fms%2Fdownload%2Fms-2.1.2.tgz",
1019 | "integrity": "sha1-0J0fNXtEP0kzgqjrPM0YOHKuYAk="
1020 | },
1021 | "negotiator": {
1022 | "version": "0.6.2",
1023 | "resolved": "https://registry.npm.taobao.org/negotiator/download/negotiator-0.6.2.tgz",
1024 | "integrity": "sha1-/qz3zPUlp3rpY0Q2pkiD/+yjRvs="
1025 | },
1026 | "on-finished": {
1027 | "version": "2.3.0",
1028 | "resolved": "https://registry.npm.taobao.org/on-finished/download/on-finished-2.3.0.tgz",
1029 | "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
1030 | "requires": {
1031 | "ee-first": "1.1.1"
1032 | }
1033 | },
1034 | "only": {
1035 | "version": "0.0.2",
1036 | "resolved": "https://registry.npm.taobao.org/only/download/only-0.0.2.tgz",
1037 | "integrity": "sha1-Kv3oTQPlC5qO3EROMGEKcCle37Q="
1038 | },
1039 | "parseurl": {
1040 | "version": "1.3.3",
1041 | "resolved": "https://registry.npm.taobao.org/parseurl/download/parseurl-1.3.3.tgz",
1042 | "integrity": "sha1-naGee+6NEt/wUT7Vt2lXeTvC6NQ="
1043 | },
1044 | "path-is-absolute": {
1045 | "version": "1.0.1",
1046 | "resolved": "https://registry.npm.taobao.org/path-is-absolute/download/path-is-absolute-1.0.1.tgz",
1047 | "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
1048 | },
1049 | "path-to-regexp": {
1050 | "version": "6.2.0",
1051 | "resolved": "https://registry.npm.taobao.org/path-to-regexp/download/path-to-regexp-6.2.0.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fpath-to-regexp%2Fdownload%2Fpath-to-regexp-6.2.0.tgz",
1052 | "integrity": "sha1-97OAMzYQTDRoia3s5hRmkjBkXzg="
1053 | },
1054 | "qs": {
1055 | "version": "6.9.6",
1056 | "resolved": "https://registry.npm.taobao.org/qs/download/qs-6.9.6.tgz?cache=0&sync_timestamp=1610598174727&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fqs%2Fdownload%2Fqs-6.9.6.tgz",
1057 | "integrity": "sha1-Ju08gkOkMbKSSsqEzJBHHzXVoO4="
1058 | },
1059 | "raw-body": {
1060 | "version": "2.4.1",
1061 | "resolved": "https://registry.npm.taobao.org/raw-body/download/raw-body-2.4.1.tgz",
1062 | "integrity": "sha1-MKyC+Yu1rowVLmcUnayNVRU7Fow=",
1063 | "requires": {
1064 | "bytes": "3.1.0",
1065 | "http-errors": "1.7.3",
1066 | "iconv-lite": "0.4.24",
1067 | "unpipe": "1.0.0"
1068 | },
1069 | "dependencies": {
1070 | "http-errors": {
1071 | "version": "1.7.3",
1072 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.7.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.7.3.tgz",
1073 | "integrity": "sha1-bGGeT5xgMIw4UZSYwU+7EKrOuwY=",
1074 | "requires": {
1075 | "depd": "~1.1.2",
1076 | "inherits": "2.0.4",
1077 | "setprototypeof": "1.1.1",
1078 | "statuses": ">= 1.5.0 < 2",
1079 | "toidentifier": "1.0.0"
1080 | }
1081 | },
1082 | "setprototypeof": {
1083 | "version": "1.1.1",
1084 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.1.tgz",
1085 | "integrity": "sha1-fpWsskqpL1iF4KvvW6ExMw1K5oM="
1086 | }
1087 | }
1088 | },
1089 | "resolve-path": {
1090 | "version": "1.4.0",
1091 | "resolved": "https://registry.npm.taobao.org/resolve-path/download/resolve-path-1.4.0.tgz",
1092 | "integrity": "sha1-xL2p9e+y/OZSR4c6s2u02DT+Fvc=",
1093 | "requires": {
1094 | "http-errors": "~1.6.2",
1095 | "path-is-absolute": "1.0.1"
1096 | },
1097 | "dependencies": {
1098 | "http-errors": {
1099 | "version": "1.6.3",
1100 | "resolved": "https://registry.npm.taobao.org/http-errors/download/http-errors-1.6.3.tgz?cache=0&sync_timestamp=1593407611415&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fhttp-errors%2Fdownload%2Fhttp-errors-1.6.3.tgz",
1101 | "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=",
1102 | "requires": {
1103 | "depd": "~1.1.2",
1104 | "inherits": "2.0.3",
1105 | "setprototypeof": "1.1.0",
1106 | "statuses": ">= 1.4.0 < 2"
1107 | }
1108 | },
1109 | "inherits": {
1110 | "version": "2.0.3",
1111 | "resolved": "https://registry.npm.taobao.org/inherits/download/inherits-2.0.3.tgz",
1112 | "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
1113 | },
1114 | "setprototypeof": {
1115 | "version": "1.1.0",
1116 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.1.0.tgz",
1117 | "integrity": "sha1-0L2FU2iHtv58DYGMuWLZ2RxU5lY="
1118 | }
1119 | }
1120 | },
1121 | "safe-buffer": {
1122 | "version": "5.1.2",
1123 | "resolved": "https://registry.npm.taobao.org/safe-buffer/download/safe-buffer-5.1.2.tgz",
1124 | "integrity": "sha1-mR7GnSluAxN0fVm9/St0XDX4go0="
1125 | },
1126 | "safer-buffer": {
1127 | "version": "2.1.2",
1128 | "resolved": "https://registry.npm.taobao.org/safer-buffer/download/safer-buffer-2.1.2.tgz",
1129 | "integrity": "sha1-RPoWGwGHuVSd2Eu5GAL5vYOFzWo="
1130 | },
1131 | "setprototypeof": {
1132 | "version": "1.2.0",
1133 | "resolved": "https://registry.npm.taobao.org/setprototypeof/download/setprototypeof-1.2.0.tgz",
1134 | "integrity": "sha1-ZsmiSnP5/CjL5msJ/tPTPcrxtCQ="
1135 | },
1136 | "statuses": {
1137 | "version": "1.5.0",
1138 | "resolved": "https://registry.npm.taobao.org/statuses/download/statuses-1.5.0.tgz?cache=0&sync_timestamp=1609654438540&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fstatuses%2Fdownload%2Fstatuses-1.5.0.tgz",
1139 | "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
1140 | },
1141 | "toidentifier": {
1142 | "version": "1.0.0",
1143 | "resolved": "https://registry.npm.taobao.org/toidentifier/download/toidentifier-1.0.0.tgz",
1144 | "integrity": "sha1-fhvjRw8ed5SLxD2Uo8j013UrpVM="
1145 | },
1146 | "tsscmp": {
1147 | "version": "1.0.6",
1148 | "resolved": "https://registry.npm.taobao.org/tsscmp/download/tsscmp-1.0.6.tgz",
1149 | "integrity": "sha1-hbmVg6w1iexL/vgltQAKqRHWBes="
1150 | },
1151 | "type-is": {
1152 | "version": "1.6.18",
1153 | "resolved": "https://registry.npm.taobao.org/type-is/download/type-is-1.6.18.tgz",
1154 | "integrity": "sha1-TlUs0F3wlGfcvE73Od6J8s83wTE=",
1155 | "requires": {
1156 | "media-typer": "0.3.0",
1157 | "mime-types": "~2.1.24"
1158 | }
1159 | },
1160 | "unpipe": {
1161 | "version": "1.0.0",
1162 | "resolved": "https://registry.npm.taobao.org/unpipe/download/unpipe-1.0.0.tgz",
1163 | "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
1164 | },
1165 | "vary": {
1166 | "version": "1.1.2",
1167 | "resolved": "https://registry.npm.taobao.org/vary/download/vary-1.1.2.tgz",
1168 | "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
1169 | },
1170 | "ylru": {
1171 | "version": "1.2.1",
1172 | "resolved": "https://registry.npm.taobao.org/ylru/download/ylru-1.2.1.tgz",
1173 | "integrity": "sha1-9Xa2M0FUeYnB3nuiiHYJI7J/6E8="
1174 | }
1175 | }
1176 | }
1177 |
--------------------------------------------------------------------------------
/6-practice/serve/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "serve",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1"
8 | },
9 | "keywords": [],
10 | "author": "",
11 | "license": "ISC",
12 | "dependencies": {
13 | "koa": "^2.13.1",
14 | "koa-body": "^4.2.0",
15 | "koa-router": "^10.0.0",
16 | "koa-static": "^5.0.0"
17 | }
18 | }
19 |
--------------------------------------------------------------------------------
/6-practice/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
29 |
--------------------------------------------------------------------------------
/6-practice/src/api/index.js:
--------------------------------------------------------------------------------
1 | // api
2 | // 命名上的规范
3 | // axios
4 | import http from "../http";
5 |
6 | export function apiGetFormData() {
7 | return http.get("/data");
8 | }
9 |
10 | export function apiModifyFormData(payload) {
11 | return http.post("/modify", payload);
12 | }
13 |
14 | export function apiDeleteFormData(id) {
15 | return http.get("/delete", {
16 | params: {
17 | id,
18 | },
19 | });
20 | }
21 |
--------------------------------------------------------------------------------
/6-practice/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/6-practice/src/assets/logo.png
--------------------------------------------------------------------------------
/6-practice/src/components/UserForm.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | id |
6 | 用户名 |
7 | 邮箱 |
8 | 性别 |
9 | 爱好 |
10 | 操作 |
11 |
12 |
13 | {{ item.id }} |
14 | {{ item.username }} |
15 | {{ item.email }} |
16 | {{ item.gender }} |
17 | {{ item.hobby.join(" | ") }} |
18 |
19 |
20 |
21 | |
22 |
23 |
24 |
25 |
26 |
27 |
65 |
66 |
67 |
--------------------------------------------------------------------------------
/6-practice/src/http.js:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 |
3 | // dev -> /api
4 | // prod -> xxxx 线上的服务地址
5 | // /api/login
6 | const myAxios = axios.create({
7 | baseURL: "/api",
8 | });
9 |
10 | export default myAxios;
11 |
--------------------------------------------------------------------------------
/6-practice/src/main.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import App from "./App.vue";
3 | import router from "./router";
4 | import store from "./store";
5 |
6 | Vue.config.productionTip = false;
7 |
8 | new Vue({
9 | router,
10 | store,
11 | render: h => h(App)
12 | }).$mount("#app");
13 |
--------------------------------------------------------------------------------
/6-practice/src/pages/Home.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/6-practice/src/pages/Login.vue:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
25 |
52 |
53 |
92 |
--------------------------------------------------------------------------------
/6-practice/src/pages/ModifyPanel.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/6-practice/src/router/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import VueRouter from "vue-router";
3 | import Home from "../pages/Home.vue";
4 | import Login from "../pages/Login.vue";
5 | import ModifyPanel from "../pages/ModifyPanel.vue";
6 |
7 | Vue.use(VueRouter);
8 |
9 | export default new VueRouter({
10 | routes: [
11 | {
12 | path: "/",
13 | name: "Home",
14 | component: Home,
15 | },
16 | {
17 | path: "/login",
18 | name: "Login",
19 | component: Login,
20 | },
21 | {
22 | path: "/modify",
23 | name: "Modify",
24 | props: true,
25 | component: ModifyPanel,
26 | },
27 | ],
28 | });
29 |
--------------------------------------------------------------------------------
/6-practice/src/store/index.js:
--------------------------------------------------------------------------------
1 | import Vue from "vue";
2 | import Vuex from "vuex";
3 | import { apiGetFormData, apiDeleteFormData, apiModifyFormData } from "../api";
4 |
5 | Vue.use(Vuex);
6 |
7 | export default new Vuex.Store({
8 | state: {
9 | username: "",
10 | formData: [],
11 | },
12 | mutations: {
13 | login(state, payload) {
14 | state.username = payload.username;
15 | },
16 |
17 | modifyForm(state, payload) {
18 | const rawData = state.formData.find((d) => d.id === payload.id);
19 | if (rawData) {
20 | rawData.hobby = payload.hobby;
21 | rawData.username = payload.username;
22 | rawData.email = payload.email;
23 | rawData.gender = payload.gender;
24 | }
25 | },
26 |
27 | deleteForm(state, payload) {
28 | const { id } = payload;
29 | const index = state.formData.findIndex((d) => d.id === id);
30 | state.formData.splice(index, 1);
31 | },
32 |
33 | updateFormData(state, payload) {
34 | state.formData = payload.data;
35 | },
36 | },
37 | actions: {
38 | async getFormData({ commit }) {
39 | const { data } = await apiGetFormData();
40 | commit("updateFormData", data);
41 | },
42 |
43 | async deleteForm({ commit }, payload) {
44 | const { data } = await apiDeleteFormData(payload.id);
45 | commit("updateFormData", data);
46 | },
47 |
48 | async modifyForm({ commit }, payload) {
49 | const { data } = await apiModifyFormData(payload);
50 | commit("updateFormData", data);
51 | },
52 | },
53 | modules: {},
54 | });
55 |
--------------------------------------------------------------------------------
/6-practice/tests/unit/example.spec.js:
--------------------------------------------------------------------------------
1 | import { shallowMount } from "@vue/test-utils";
2 | import HelloWorld from "@/components/HelloWorld.vue";
3 |
4 | describe("HelloWorld.vue", () => {
5 | it("renders props.msg when passed", () => {
6 | const msg = "new message";
7 | const wrapper = shallowMount(HelloWorld, {
8 | propsData: { msg }
9 | });
10 | expect(wrapper.text()).toMatch(msg);
11 | });
12 | });
13 |
--------------------------------------------------------------------------------
/6-practice/vue.config.js:
--------------------------------------------------------------------------------
1 | // vue-cli
2 | // webpack
3 | // cjs
4 | // /api
5 | module.exports = {
6 | devServer: {
7 | proxy: {
8 | "/api": {
9 | target: "http://localhost:8081",
10 | pathRewrite: {
11 | "^/api": ""
12 | }
13 | }
14 | }
15 | }
16 | };
17 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/.browserslistrc:
--------------------------------------------------------------------------------
1 | > 1%
2 | last 2 versions
3 | not dead
4 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/.eslintrc.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | root: true,
3 | env: {
4 | node: true,
5 | },
6 | extends: ["plugin:vue/vue3-essential", "eslint:recommended", "@vue/prettier"],
7 | parserOptions: {
8 | parser: "babel-eslint",
9 | },
10 | rules: {
11 | "no-console": process.env.NODE_ENV === "production" ? "warn" : "off",
12 | "no-debugger": process.env.NODE_ENV === "production" ? "warn" : "off",
13 | },
14 | };
15 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/README.md:
--------------------------------------------------------------------------------
1 | # 7-vue3-todo-list
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: ["@vue/cli-plugin-babel/preset"],
3 | };
4 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "7-vue3-todo-list",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "core-js": "^3.6.5",
12 | "element3": "^0.0.40",
13 | "vue": "^3.0.0",
14 | "vuex": "^4.0.0-0"
15 | },
16 | "devDependencies": {
17 | "@vue/cli-plugin-babel": "~4.5.0",
18 | "@vue/cli-plugin-eslint": "~4.5.0",
19 | "@vue/cli-plugin-vuex": "~4.5.0",
20 | "@vue/cli-service": "~4.5.0",
21 | "@vue/compiler-sfc": "^3.0.0",
22 | "@vue/eslint-config-prettier": "^6.0.0",
23 | "babel-eslint": "^10.1.0",
24 | "eslint": "^6.7.2",
25 | "eslint-plugin-prettier": "^3.3.1",
26 | "eslint-plugin-vue": "^7.0.0",
27 | "prettier": "^2.2.1"
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/7-vue3-todo-list/public/favicon.ico
--------------------------------------------------------------------------------
/7-vue3-todo-list/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
16 |
17 |
27 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/7-vue3-todo-list/src/assets/logo.png
--------------------------------------------------------------------------------
/7-vue3-todo-list/src/components/TodoItem.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{ item.context }}
4 | X
5 | completed
6 |
7 |
8 |
9 |
34 |
35 |
40 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/src/components/TodoList.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | todo-list
4 |
5 |
6 |
13 |
14 |
15 | all
16 | active
17 | completed
18 |
19 |
20 |
21 |
22 |
73 |
74 |
75 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "vue";
2 | import App from "./App.vue";
3 | import store from "./store";
4 | import "element3/lib/theme-chalk/index.css";
5 | import Element3 from "element3";
6 |
7 | createApp(App).use(store).use(Element3).mount("#app");
8 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/src/store/index.js:
--------------------------------------------------------------------------------
1 | import { createStore } from "vuex";
2 | import { generateId } from "../utils/generateId.js";
3 |
4 | const createTodoItem = (context) => {
5 | return {
6 | id: generateId(),
7 | context,
8 | state: "active",
9 | };
10 | };
11 |
12 | export default createStore({
13 | state: {
14 | todoList: [],
15 | },
16 | mutations: {
17 | addTodo(state, { context }) {
18 | // create new todoItem
19 | state.todoList.push(createTodoItem(context));
20 | },
21 | removeTodo(state, { id }) {
22 | state.todoList = state.todoList.filter((todo) => todo.id !== id);
23 | },
24 |
25 | completeTodo(state, { id }) {
26 | const todoItem = state.todoList.find((todo) => todo.id === id);
27 | const isCompleted = (todo) => todo.state === "completed";
28 |
29 | if (todoItem) {
30 | todoItem.state = isCompleted(todoItem) ? "active" : "completed";
31 | }
32 | },
33 | },
34 | actions: {},
35 | modules: {},
36 | });
37 |
--------------------------------------------------------------------------------
/7-vue3-todo-list/src/utils/generateId.js:
--------------------------------------------------------------------------------
1 | let id = 0;
2 | export function generateId() {
3 | return id++;
4 | }
5 |
--------------------------------------------------------------------------------
/8-custom-renderer/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/.DS_Store
--------------------------------------------------------------------------------
/8-custom-renderer/assets/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/bullet.png
--------------------------------------------------------------------------------
/8-custom-renderer/assets/end_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/end_page.jpg
--------------------------------------------------------------------------------
/8-custom-renderer/assets/enemy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/enemy.png
--------------------------------------------------------------------------------
/8-custom-renderer/assets/map.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/map.jpg
--------------------------------------------------------------------------------
/8-custom-renderer/assets/plane.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/plane.png
--------------------------------------------------------------------------------
/8-custom-renderer/assets/restartBtn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/restartBtn.png
--------------------------------------------------------------------------------
/8-custom-renderer/assets/startBtn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/startBtn.png
--------------------------------------------------------------------------------
/8-custom-renderer/assets/start_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/assets/start_page.jpg
--------------------------------------------------------------------------------
/8-custom-renderer/dist/build.js:
--------------------------------------------------------------------------------
1 | !function(e){var t={};function n(r){if(t[r])return t[r].exports;var o=t[r]={i:r,l:!1,exports:{}};return e[r].call(o.exports,o,o.exports,n),o.l=!0,o.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var o in e)n.d(r,o,function(t){return e[t]}.bind(null,o));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=0)}([function(e,t){console.log("main")}]);
--------------------------------------------------------------------------------
/8-custom-renderer/dist/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 | Document
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/8-custom-renderer/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "./src/runtime-canvas";
2 | import App from "./src/App";
3 | import { getCanvasRootContainer } from "./src/Game";
4 |
5 | createApp(App).mount(getCanvasRootContainer());
6 |
--------------------------------------------------------------------------------
/8-custom-renderer/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "play-plane",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "echo \"Error: no test specified\" && exit 1",
8 | "build": "webpack",
9 | "serve": "webpack-dev-server --open"
10 | },
11 | "keywords": [],
12 | "author": "",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "webpack": "^4.43.0",
16 | "webpack-cli": "^3.3.12"
17 | },
18 | "dependencies": {
19 | "@vue/runtime-core": "^3.0.0-beta.18",
20 | "pixi.js": "^5.3.0",
21 | "webpack-dev-server": "^3.11.0",
22 | "file-loader": "^6.0.0"
23 | }
24 | }
25 |
--------------------------------------------------------------------------------
/8-custom-renderer/src/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/8-custom-renderer/src/.DS_Store
--------------------------------------------------------------------------------
/8-custom-renderer/src/App.js:
--------------------------------------------------------------------------------
1 | import {
2 | defineComponent,
3 | h,
4 | ref,
5 | onMounted,
6 | onUnmounted,
7 | reactive,
8 | } from "@vue/runtime-core";
9 |
10 | export default defineComponent({
11 | setup() {
12 | const { x } = useMove();
13 |
14 | return {
15 | x,
16 | };
17 | },
18 | render(ctx) {
19 | return h("circle", { x: ctx.x, y: 200 });
20 | },
21 | });
22 |
23 | function useMove() {
24 | const stageWidth = 750;
25 |
26 | const moveX = ref(200);
27 |
28 | const r = 50 * 2;
29 | let intervalNumber;
30 | const speed = 1;
31 | let dir = 1;
32 | onMounted(() => {
33 | intervalNumber = setInterval(() => {
34 | moveX.value += speed * dir;
35 |
36 | if (moveX.value > stageWidth - r) {
37 | dir = -1;
38 | }
39 |
40 | if (moveX.value < 0 + r) {
41 | dir = 1;
42 | }
43 | });
44 | });
45 |
46 | onUnmounted(() => {
47 | clearInterval(intervalNumber);
48 | });
49 |
50 | return {
51 | x: moveX,
52 | };
53 | }
54 |
--------------------------------------------------------------------------------
/8-custom-renderer/src/Game.js:
--------------------------------------------------------------------------------
1 | import * as PIXI from "pixi.js";
2 | // mount 需要 根容器
3 | // createApp(App).mount('#app')
4 | // pixi.js
5 | // 初始化
6 | const game = new PIXI.Application({
7 | width: 750,
8 | height: 1080,
9 | });
10 |
11 | document.body.appendChild(game.view);
12 |
13 | export function getCanvasRootContainer() {
14 | return game.stage;
15 | }
16 |
--------------------------------------------------------------------------------
/8-custom-renderer/src/runtime-canvas/index.js:
--------------------------------------------------------------------------------
1 | import { createRenderer } from "@vue/runtime-core";
2 | import { Graphics, Text } from "pixi.js";
3 | // 创建渲染器
4 | // 实现渲染接口
5 | const renderer = createRenderer({
6 | createElement(type) {
7 | console.log(type);
8 | // 基于 type 去创建视图
9 | let element;
10 | if (type === "circle") {
11 | // 画圆
12 | // pixi
13 | element = new Graphics();
14 | element.beginFill(0xff0000, 1);
15 | element.drawCircle(0, 0, 100);
16 | element.endFill();
17 | }
18 | return element;
19 | },
20 | insert(el, parent) {
21 | // console.log("-----insert ------");
22 | // console.log(el);
23 | parent.addChild(el);
24 | },
25 | patchProp(el, key, prevValue, nextValue) {
26 | // console.log("----patchProp-----");
27 | // console.log(el);
28 | // console.log(key);
29 | // console.log(prevValue);
30 | // console.log(nextValue);
31 | // pixi
32 | // el.x = nextValue
33 | el[key] = nextValue;
34 | },
35 | setElementText(node, text) {
36 | console.log("elementText");
37 | console.log(node);
38 | console.log(text);
39 | const canvasText = new Text(text);
40 | node.addChild(canvasText);
41 | },
42 | createText(text) {
43 | return new Text(text);
44 | },
45 | // 新加
46 | // 处理注释
47 | createComment() {},
48 | // 获取父节点
49 | parentNode() {},
50 | // 获取兄弟节点
51 | nextSibling() {},
52 | // 删除节点时调用
53 | remove(el) {
54 | const parent = el.parent;
55 | if (parent) {
56 | parent.removeChild(el);
57 | }
58 | },
59 | });
60 |
61 | export function createApp(rootComponent) {
62 | // 调用 renderer
63 | return renderer.createApp(rootComponent);
64 | }
65 |
--------------------------------------------------------------------------------
/8-custom-renderer/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require("path");
2 | module.exports = {
3 | entry: path.resolve(__dirname, "./main.js"),
4 | output: {
5 | filename: "build.js",
6 | path: path.resolve(__dirname, "./dist"),
7 | },
8 | devServer: {
9 | contentBase: path.resolve(__dirname, "./dist")
10 | },
11 | module: {
12 | rules: [
13 | {
14 | test: /\.(png|jpe?g|gif)$/i,
15 | use: [
16 | {
17 | loader: "file-loader",
18 | options: {
19 | outputPath: "assets/",
20 | publicPath: "",
21 | },
22 | },
23 | ],
24 | },
25 | ],
26 | },
27 | };
28 |
--------------------------------------------------------------------------------
/8-custom-renderer/work.md:
--------------------------------------------------------------------------------
1 | ## 第二天作业
2 |
3 | 通过 pixi.js 绘制出一个小球
4 | 然后让小球一直向右移动
5 |
6 | 1. 组件挂载完成后在让小球移动
7 | 2. 组件销毁后需要移除循环监听
8 | 3. 小球碰到屏幕会回弹
9 |
10 | ## 答案
11 |
12 | ```
13 | import {
14 | defineComponent,
15 | h,
16 | ref,
17 | onMounted,
18 | onUnmounted,
19 | } from "@vue/runtime-core";
20 | export default defineComponent({
21 | setup() {
22 | const stageWidth = 750;
23 |
24 | const moveX = ref(200);
25 |
26 | const r = 50 * 2;
27 | let intervalNumber;
28 | const speed = 1;
29 | let dir = 1;
30 | onMounted(() => {
31 | intervalNumber = setInterval(() => {
32 | moveX.value += speed * dir;
33 |
34 | if(moveX.value > stageWidth - r )
35 | {
36 | dir = -1
37 | }
38 |
39 | if(moveX.value < 0 + r){
40 | dir = 1
41 | }
42 | });
43 | });
44 |
45 | onUnmounted(() => {
46 | clearInterval(intervalNumber);
47 | });
48 |
49 | return {
50 | x: moveX,
51 | };
52 | },
53 | render(ctx) {
54 | return h("circle", { x: ctx.x, y: 200 });
55 | },
56 | });
57 |
58 | ```
59 |
--------------------------------------------------------------------------------
/9-play-plane/.gitignore:
--------------------------------------------------------------------------------
1 | .DS_Store
2 | node_modules
3 | /dist
4 |
5 |
6 | # local env files
7 | .env.local
8 | .env.*.local
9 |
10 | # Log files
11 | npm-debug.log*
12 | yarn-debug.log*
13 | yarn-error.log*
14 | pnpm-debug.log*
15 |
16 | # Editor directories and files
17 | .idea
18 | .vscode
19 | *.suo
20 | *.ntvs*
21 | *.njsproj
22 | *.sln
23 | *.sw?
24 |
--------------------------------------------------------------------------------
/9-play-plane/README.md:
--------------------------------------------------------------------------------
1 | # play-plane
2 |
3 | ## Project setup
4 | ```
5 | npm install
6 | ```
7 |
8 | ### Compiles and hot-reloads for development
9 | ```
10 | npm run serve
11 | ```
12 |
13 | ### Compiles and minifies for production
14 | ```
15 | npm run build
16 | ```
17 |
18 | ### Lints and fixes files
19 | ```
20 | npm run lint
21 | ```
22 |
23 | ### Customize configuration
24 | See [Configuration Reference](https://cli.vuejs.org/config/).
25 |
--------------------------------------------------------------------------------
/9-play-plane/babel.config.js:
--------------------------------------------------------------------------------
1 | module.exports = {
2 | presets: [
3 | '@vue/cli-plugin-babel/preset'
4 | ]
5 | }
6 |
--------------------------------------------------------------------------------
/9-play-plane/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "play-plane",
3 | "version": "0.1.0",
4 | "private": true,
5 | "scripts": {
6 | "serve": "vue-cli-service serve",
7 | "build": "vue-cli-service build",
8 | "lint": "vue-cli-service lint"
9 | },
10 | "dependencies": {
11 | "core-js": "^3.6.5",
12 | "pixi.js": "^5.3.6",
13 | "vue": "^3.0.0"
14 | },
15 | "devDependencies": {
16 | "@vue/cli-plugin-babel": "~4.5.0",
17 | "@vue/cli-plugin-eslint": "~4.5.0",
18 | "@vue/cli-service": "~4.5.0",
19 | "@vue/compiler-sfc": "^3.0.0",
20 | "babel-eslint": "^10.1.0",
21 | "eslint": "^6.7.2",
22 | "eslint-plugin-vue": "^7.0.0-0"
23 | },
24 | "eslintConfig": {
25 | "root": true,
26 | "env": {
27 | "node": true
28 | },
29 | "extends": [
30 | "plugin:vue/vue3-essential",
31 | "eslint:recommended"
32 | ],
33 | "parserOptions": {
34 | "parser": "babel-eslint"
35 | },
36 | "rules": {}
37 | },
38 | "browserslist": [
39 | "> 1%",
40 | "last 2 versions",
41 | "not dead"
42 | ]
43 | }
44 |
--------------------------------------------------------------------------------
/9-play-plane/public/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/public/favicon.ico
--------------------------------------------------------------------------------
/9-play-plane/public/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 | <%= htmlWebpackPlugin.options.title %>
9 |
10 |
11 |
14 |
15 |
16 |
17 |
18 |
--------------------------------------------------------------------------------
/9-play-plane/src/App.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
50 |
--------------------------------------------------------------------------------
/9-play-plane/src/assets/bullet.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/bullet.png
--------------------------------------------------------------------------------
/9-play-plane/src/assets/end_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/end_page.jpg
--------------------------------------------------------------------------------
/9-play-plane/src/assets/enemy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/enemy.png
--------------------------------------------------------------------------------
/9-play-plane/src/assets/logo copy.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/logo copy.png
--------------------------------------------------------------------------------
/9-play-plane/src/assets/logo.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/logo.png
--------------------------------------------------------------------------------
/9-play-plane/src/assets/map.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/map.jpg
--------------------------------------------------------------------------------
/9-play-plane/src/assets/plane.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/plane.png
--------------------------------------------------------------------------------
/9-play-plane/src/assets/restartBtn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/restartBtn.png
--------------------------------------------------------------------------------
/9-play-plane/src/assets/startBtn.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/startBtn.png
--------------------------------------------------------------------------------
/9-play-plane/src/assets/start_page.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/cuixiaorui/teach-vue-practice/af121916c2a039d4efdff26ac6b8921f8f320db8/9-play-plane/src/assets/start_page.jpg
--------------------------------------------------------------------------------
/9-play-plane/src/components/Bullet.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/9-play-plane/src/components/EnemyPlane.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
86 |
--------------------------------------------------------------------------------
/9-play-plane/src/components/HelloWorld.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
{{ msg }}
4 |
5 | For a guide and recipes on how to configure / customize this project,
6 | check out the
7 | vue-cli documentation.
8 |
9 |
Installed CLI Plugins
10 |
14 |
Essential Links
15 |
22 |
Ecosystem
23 |
30 |
31 |
32 |
33 |
41 |
42 |
43 |
59 |
--------------------------------------------------------------------------------
/9-play-plane/src/components/Map.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/9-play-plane/src/components/Plane.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
81 |
--------------------------------------------------------------------------------
/9-play-plane/src/game/index.js:
--------------------------------------------------------------------------------
1 | import { Application } from "pixi.js";
2 |
3 | export const game = new Application({
4 | width: 750,
5 | height: 1080,
6 | });
7 |
8 | document.body.append(game.view);
9 |
10 | export function getRootContainer() {
11 | return game.stage;
12 | }
13 |
--------------------------------------------------------------------------------
/9-play-plane/src/main.js:
--------------------------------------------------------------------------------
1 | import { createApp } from "./runtime-canvas";
2 | import { getRootContainer } from "./game";
3 | import App from "./App.vue";
4 |
5 | console.warn = () => {};
6 |
7 | createApp(App).mount(getRootContainer());
8 |
--------------------------------------------------------------------------------
/9-play-plane/src/pages/EndPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/9-play-plane/src/pages/GamePage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
11 |
12 |
18 |
19 |
20 |
21 |
95 |
96 |
97 |
--------------------------------------------------------------------------------
/9-play-plane/src/pages/StartPage.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
11 |
12 |
13 |
14 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/9-play-plane/src/runtime-canvas/index.js:
--------------------------------------------------------------------------------
1 | // 实现基于 canvas 自定义的渲染器
2 | import { createRenderer } from "vue";
3 | import { Container, Texture, Sprite, Text } from "pixi.js";
4 |
5 | const renderer = createRenderer({
6 | createElement(type) { // 容器 以及 图片
7 | let element;
8 | switch (type) {
9 | case "container":
10 | element = new Container();
11 | break;
12 | case "sprite":
13 | element = new Sprite();
14 | break;
15 | }
16 |
17 | return element;
18 | },
19 |
20 | insert(el, parent) {
21 | if (el) {
22 | parent.addChild(el);
23 | }
24 | },
25 | parentNode(node) {
26 | // 获取当前 node 的父级节点
27 | // parent
28 | return node.parent;
29 | },
30 | remove(el) {
31 | // 当删除一个元素的时候 进行调用
32 | if (el && el.parent) {
33 | // removeChild(el)
34 | el.parent.removeChild(el);
35 | }
36 | },
37 | patchProp(el, key, prevValue, nextValue) {
38 | // props
39 | // console.log(key, nextValue);
40 | switch (key) {
41 | case "texture":
42 | // 给图片 src 的时候
43 | el.texture = Texture.from(nextValue);
44 | break;
45 | case "onClick":
46 | // onClick
47 | el.on("pointertap", nextValue);
48 | break;
49 | default:
50 | el[key] = nextValue;
51 | break;
52 | }
53 | },
54 | // 必须要的
55 | createText(text) {
56 | return new Text(text);
57 | },
58 |
59 | nextSibling() {},
60 | createComment() {},
61 | });
62 |
63 | export function createApp(rootComponent) {
64 | return renderer.createApp(rootComponent);
65 | }
66 |
--------------------------------------------------------------------------------
/9-play-plane/src/utils/index.js:
--------------------------------------------------------------------------------
1 | // 矩形碰撞
2 | export function hitTestObject(rectA, rectB) {
3 | return (
4 | rectA.x + rectA.width >= rectB.x &&
5 | rectB.x + rectB.width >= rectA.x &&
6 | rectA.y + rectA.height >= rectB.y &&
7 | rectB.y + rectB.height >= rectA.y
8 | );
9 | }
10 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | ## 初识 vue - template 基础
2 |
3 | ### 知识点
4 |
5 | 1. mvvm 开发思想
6 | 2. vue 基础知识
7 | 3. 学会看 vue 文档
8 |
9 | ### 任务
10 |
11 | - 实现基于本地数据渲染 table 表格(5 分)
12 |
13 | - 列表数据可删除(5 分)
14 |
15 | - 点击删除按钮的时候,可以删除当前列的数据
16 |
17 | ## 组件化思想 -组件基础
18 |
19 | ### 知识点
20 |
21 | 1. 组件化思想
22 | 2. vue 组件基础知识点
23 |
24 | ### 任务
25 |
26 | - 封装一个 ModifyPanel 的组件(2 分)
27 | - 列表数据可修改(8 分)
28 | - 点击“修改按钮”的时候,可弹出“修改面板”(2 分)
29 | - 修改面板显示当前要修改的数据(2 分)
30 | - 保存(2 分)
31 | - 点击保存按钮后,当前用户数据会修改完成
32 | - 同时关闭“修改面板”
33 | - 取消(2 分)
34 | - 点击取消按钮后,“修改面板”将被关闭
35 |
36 | ## vue-cli 以及 vue 的单元测试
37 |
38 | ### 知识点
39 |
40 | 1. sfc
41 | 2. vue-cli
42 | 3. todo-list
43 | 4. 单元测试
44 |
45 | ### 任务
46 |
47 | - 使用 SFC(单文件组件) 重构之前的逻辑 (6 分)
48 | - 封装成一下两个组件
49 | - UserForm
50 | - ModifyPanel
51 | - 对 ModifyPanel 组件编写单元测试(4 分)
52 | - 点击取消的时候,验证是否发出 cancel 事件(2 分)
53 | - 点击保存的时候,验证是否发出 save 事件(2 分)
54 |
55 | ## vue 单页面应用 - vue-router
56 |
57 | ### 知识点
58 |
59 | 1. SPA
60 | 2. vue-router
61 |
62 | ### 任务
63 |
64 | - 实现登录页面(4 分)
65 |
66 | - 登录成功后跳转到 Home 页
67 | - 不需要验证账号和密码,不为空即可
68 | - 用户账号保存到 localStorage 内
69 |
70 | - 实现编辑页面(6 分)
71 |
72 | - 点击编辑按钮的时候跳转到编辑页面(3)
73 | - 点击“保存”按钮后,跳转到 Home 页面(3)
74 | - 无需保存修改后的数据
75 |
76 | ## vue 组件通信
77 |
78 | ### 知识点
79 |
80 | 1. 组件之间的通信方式
81 | 2. vuex 基础知识
82 |
83 | ### 任务
84 |
85 | - 把之前的数据操作全部重构到 store 内(10 分)
86 | - 编辑(4)
87 | - 登录(3)
88 | - 删除(3)
89 |
90 | ## vue 相册实战
91 |
92 | ### 知识点
93 |
94 | 1. axios 在 vue 中的应用
95 | 2. 路由权限拦截
96 | 3. 前后端交互
97 |
98 | ### 任务
99 |
100 | - 基于接口重构其逻辑,以下 action 全部请求后端完成(10 分)
101 | - 数据获取(4 分)
102 | - 数据编辑(更新)(3 分)
103 | - 数据删除(3 分)
104 |
105 | ## vue3 来袭
106 |
107 | ### 知识点
108 |
109 | 1. 认识 vue3 新特性
110 | 2. 掌握 composition api
111 |
112 | ### 任务
113 |
114 | - 实现完整版 todo-list (10 分)
115 | - 可以通过输入框输入一个 todo(1 分)
116 | - 可以删除一个 todo(1 分)
117 | - 可以完成一个 todo (1 分)
118 | - 点击完成按钮后,当前 todo 的样式画个横线
119 | - all 按钮,显示所有 todo(3 分)
120 | - active 按钮,显示所有处于 active 状态下的所有 todo(2 分)
121 | - completed 按钮,显示所有处于 completed 状态下的所有 todo(2 分)
122 | - 技术要求
123 | - 使用 vue3 的 composition api 方式编写逻辑
124 | - 使用 vuex
125 | - 使用 element3
126 | - 使用 button 组件即可
127 |
128 | ## custom-renderer Vue3 结合 Canvas
129 |
130 | ### 知识点
131 |
132 | 1. 掌握 custom renderer 的使用方式
133 | 2. 掌握 pixijs
134 |
135 | ### 任务
136 |
137 | - 基于 custom renderer 实现小球的移动
138 | - 小球可以左右移动(5 分)
139 | - 碰到屏幕的时候会回弹(5 分)
140 |
141 | ## vue3 实现飞机大战
142 |
143 | ### 知识点
144 |
145 | 1. 基于 pixijs 的游戏实战
146 |
147 | ### 任务
148 |
149 | - 可自动生成敌军飞机(3 分)
150 | - 1 秒创建一个
151 | - 当敌军超出屏幕时,需要销毁(2 分)
152 | - 当子弹超出屏幕时,需要销毁(2 分)
153 | - 敌军需要打击两次才可以销毁(3 分)
154 | - 敌军血量值的概念
155 |
156 | ## 手写 mini-vue
157 |
158 | ### 知识点
159 |
160 | 1. 源码实现
161 |
162 | ### 任务
163 |
164 | - 实现事件功能(5 分)
165 | - 在 props 中给定 onClick 之后,会自动给当前 el 添加 click 事件
166 | - 通过 h 函数 + effect 完成 count double 的逻辑编写(5 分)
167 |
--------------------------------------------------------------------------------