├── .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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 29 | 30 |
id用户名邮箱性别爱好操作
{{ item.id }}{{ item.username }}{{ item.email }}{{ item.gender }}{{ item.hobby.join(' | ') }} 27 | 28 |
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 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 30 | 31 |
id用户名邮箱性别爱好操作
{{ item.id }}{{ item.username }}{{ item.email }}{{ item.gender }}{{ item.hobby.join(' | ') }} 27 | 28 | 29 |
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 | 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 | 68 | 69 | 113 | 114 | 115 | -------------------------------------------------------------------------------- /3-vue-cli-unit-test/src/components/UserForm.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 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 | 6 | 7 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /4-vue-router/src/pages/Login.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 52 | 53 | 92 | -------------------------------------------------------------------------------- /4-vue-router/src/pages/ModifyPanel.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 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 | 6 | 7 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /5-vuex/src/pages/Login.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 52 | 53 | 92 | -------------------------------------------------------------------------------- /5-vuex/src/pages/ModifyPanel.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 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 | 6 | 7 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /6-practice/src/pages/Login.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 52 | 53 | 92 | -------------------------------------------------------------------------------- /6-practice/src/pages/ModifyPanel.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 8 | 9 | 34 | 35 | 40 | -------------------------------------------------------------------------------- /7-vue3-todo-list/src/components/TodoList.vue: -------------------------------------------------------------------------------- 1 | 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 | 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 | 6 | 7 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /9-play-plane/src/components/EnemyPlane.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 86 | -------------------------------------------------------------------------------- /9-play-plane/src/components/HelloWorld.vue: -------------------------------------------------------------------------------- 1 | 32 | 33 | 41 | 42 | 43 | 59 | -------------------------------------------------------------------------------- /9-play-plane/src/components/Map.vue: -------------------------------------------------------------------------------- 1 | 7 | 8 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /9-play-plane/src/components/Plane.vue: -------------------------------------------------------------------------------- 1 | 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 | 13 | 14 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /9-play-plane/src/pages/GamePage.vue: -------------------------------------------------------------------------------- 1 | 20 | 21 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /9-play-plane/src/pages/StartPage.vue: -------------------------------------------------------------------------------- 1 | 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 | --------------------------------------------------------------------------------