├── .DS_Store ├── .gitignore ├── README.md ├── _config.yml ├── assets ├── fork.png └── modify.png └── lesson ├── .DS_Store ├── 1.vue基础入门 ├── .DS_Store ├── 1-数据绑定.html ├── 2-计算属性.html ├── 3-Class和Style绑定.html ├── 4-条件渲染.html ├── 5-列表渲染.html ├── 6-事件处理器.html ├── 7-表单控件绑定.html ├── HomeWork │ ├── TODO.css │ ├── TODO.html │ └── TODO.js ├── HomeWorkFinish │ ├── TODO.css │ ├── TODO.html │ └── TODO.js ├── VUE基础入门.pptx └── lesson.css ├── 2.vue组件入门 ├── .DS_Store ├── VUE组件入门.pptx └── src │ ├── 1-vue.js │ ├── 1-注册组件.html │ ├── 2-1-vue.js │ ├── 2-1-数据传递-props.html │ ├── 2-2-vue.js │ ├── 2-2-数据传递-组件通信.html │ ├── 2-3-vue.js │ ├── 2-3-数据传递-slot分发.html │ ├── 3-vue.js │ ├── 3-动态组件.html │ └── 4-生命周期.html ├── 3.vue组件应用之基础篇 ├── VUE组件应用之基础篇.pptx └── 第三次作业详细说明.md ├── 4.vue组件应用之实操篇 ├── .DS_Store ├── VUE组件应用之实操篇.pptx └── lesson-4 │ ├── .babelrc │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .postcssrc.js │ ├── README.md │ ├── build │ ├── build.js │ ├── check-versions.js │ ├── dev-client.js │ ├── dev-server.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ ├── webpack.prod.conf.js │ └── webpack.test.conf.js │ ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js │ ├── index.html │ ├── package.json │ ├── src │ ├── App.vue │ ├── assets │ │ ├── logo.png │ │ └── vux_logo.png │ ├── components │ │ ├── Hello.vue │ │ └── HelloFromVux.vue │ ├── main.js │ ├── pages │ │ └── todo.vue │ └── router │ │ └── index.js │ ├── static │ └── .gitkeep │ └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js ├── 5.vue移动交付之vue-router ├── Vue移动交付之Vue-Router.pptx └── lesson-5 │ ├── .babelrc │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .postcssrc.js │ ├── README.md │ ├── build │ ├── build.js │ ├── check-versions.js │ ├── dev-client.js │ ├── dev-server.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ ├── webpack.prod.conf.js │ └── webpack.test.conf.js │ ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js │ ├── index.html │ ├── package.json │ ├── src │ ├── App.vue │ ├── assets │ │ ├── logo.png │ │ └── vux_logo.png │ ├── main.js │ ├── pages │ │ ├── page1.vue │ │ └── todo.vue │ └── router │ │ └── index.js │ ├── static │ └── .gitkeep │ └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js ├── 6.vue移动交付之axios ├── Vue移动交付之Axios.pptx └── lesson-6 │ ├── .babelrc │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .postcssrc.js │ ├── README.md │ ├── build │ ├── build.js │ ├── check-versions.js │ ├── dev-client.js │ ├── dev-server.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ ├── webpack.prod.conf.js │ └── webpack.test.conf.js │ ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── App.vue │ ├── assets │ │ ├── logo.png │ │ └── vux_logo.png │ ├── main.js │ ├── mock │ │ ├── index.js │ │ └── list.json │ ├── pages │ │ ├── Login.vue │ │ └── Todo.vue │ └── router │ │ └── index.js │ ├── static │ └── .gitkeep │ └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js ├── 7.vue移动交付之vuex ├── Vue移动交付之Vuex.pptx └── lesson-7 │ ├── .babelrc │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .postcssrc.js │ ├── README.md │ ├── build │ ├── build.js │ ├── check-versions.js │ ├── dev-client.js │ ├── dev-server.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ ├── webpack.prod.conf.js │ └── webpack.test.conf.js │ ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── App.vue │ ├── assets │ │ ├── logo.png │ │ └── vux_logo.png │ ├── main.js │ ├── mock │ │ ├── index.js │ │ └── list.json │ ├── pages │ │ ├── Todo1.vue │ │ └── Todo2.vue │ └── router │ │ └── index.js │ ├── static │ └── .gitkeep │ └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js ├── 8.vue拓展之ES6语法解析 ├── Vue拓展之ES6语法解析.pptx └── lesson-8 │ ├── .babelrc │ ├── .editorconfig │ ├── .eslintignore │ ├── .eslintrc.js │ ├── .gitignore │ ├── .postcssrc.js │ ├── README.md │ ├── build │ ├── build.js │ ├── check-versions.js │ ├── dev-client.js │ ├── dev-server.js │ ├── utils.js │ ├── vue-loader.conf.js │ ├── webpack.base.conf.js │ ├── webpack.dev.conf.js │ ├── webpack.prod.conf.js │ └── webpack.test.conf.js │ ├── config │ ├── dev.env.js │ ├── index.js │ ├── prod.env.js │ └── test.env.js │ ├── index.html │ ├── package-lock.json │ ├── package.json │ ├── src │ ├── App.vue │ ├── assets │ │ ├── logo.png │ │ └── vux_logo.png │ ├── main.js │ ├── mock │ │ ├── index.js │ │ └── list.json │ ├── pages │ │ ├── Todo1.vue │ │ └── Todo2.vue │ ├── router │ │ └── index.js │ └── util.js │ ├── static │ └── .gitkeep │ └── test │ ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js │ └── unit │ ├── .eslintrc │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js └── 9.vue拓展之前端调试 ├── Vue拓展之前端调试pptx └── lesson-9 ├── .babelrc ├── .editorconfig ├── .eslintignore ├── .eslintrc.js ├── .gitignore ├── .postcssrc.js ├── README.md ├── build ├── build.js ├── check-versions.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── vue-loader.conf.js ├── webpack.base.conf.js ├── webpack.dev.conf.js ├── webpack.prod.conf.js └── webpack.test.conf.js ├── config ├── dev.env.js ├── index.js ├── prod.env.js └── test.env.js ├── index.html ├── package-lock.json ├── package.json ├── src ├── App.vue ├── assets │ ├── logo.png │ └── vux_logo.png ├── main.js ├── mock │ ├── index.js │ └── list.json ├── pages │ ├── Todo1.vue │ └── Todo2.vue ├── router │ └── index.js └── util.js ├── static └── .gitkeep └── test ├── e2e ├── custom-assertions │ └── elementCount.js ├── nightwatch.conf.js ├── runner.js └── specs │ └── test.js └── unit ├── .eslintrc ├── index.js ├── karma.conf.js └── specs └── Hello.spec.js /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/.DS_Store -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | selenium-debug.log 9 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-architect -------------------------------------------------------------------------------- /assets/fork.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/assets/fork.png -------------------------------------------------------------------------------- /assets/modify.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/assets/modify.png -------------------------------------------------------------------------------- /lesson/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/.DS_Store -------------------------------------------------------------------------------- /lesson/1.vue基础入门/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/1.vue基础入门/.DS_Store -------------------------------------------------------------------------------- /lesson/1.vue基础入门/1-数据绑定.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1-数据绑定 9 | 10 | 11 | 12 | 13 | 14 |
15 |

普通的 {{ message }}

16 |

表达式计算出的 {{ message + 'everyone!' }}

17 |

过滤后的 {{ message | capitalize }}

18 |

绑定了class的 {{ message }}

19 |
20 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/2-计算属性.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 2-计算属性 9 | 10 | 11 | 12 | 13 | 14 |
15 |

这是一个普通的 {{ message }}

16 |

这是一个计算后的 {{ capitalize }}

17 |
18 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/3-Class和Style绑定.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 3-Class和Style绑定 9 | 10 | 11 | 12 | 13 | 14 |
15 |

给class绑定了对象的 {{ message }}

16 |

给class绑定了对象属性的 {{ message }}

17 |

给class绑定了计算属性的 {{ message }}

18 |

给class绑定了数组的 {{ message }}

19 |
20 |

绑定了style的 {{ message }}

21 |

给style绑定了对象属性的 {{ message }}

22 |

给style绑定了计算属性的 {{ message }}

23 |

给style绑定了数组的 {{ message }}

24 |
25 | 65 | 66 | 67 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/4-条件渲染.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 4-条件渲染 9 | 10 | 11 | 12 | 13 | 14 |
15 |

现在你看到我了

16 |

你可以假装看不见我

17 |

现在你真的看不见我了

18 | 19 | 20 | 21 |
22 |

>不带key的条件切换:

23 |
24 | 25 | 26 |
27 |
28 | 29 | 30 |
31 | 32 |
33 |

>带key的条件切换:

34 |
35 | 36 | 37 |
38 |
39 | 40 | 41 |
42 | 43 |
44 | 45 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/5-列表渲染.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 5-列表渲染 9 | 10 | 11 | 12 | 13 | 14 |
15 |

>数组列表

16 | 17 |
    18 |
  1. 19 | {{ todo.text }} 20 |
  2. 21 |
22 | 23 |

>对象列表

24 | 29 | 30 |
31 | 32 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/6-事件处理器.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 6-事件处理器 9 | 10 | 11 | 12 | 13 | 14 |
15 |

{{ message }}

16 |

>方法处理器

17 | 18 |

>内联处理器

19 | 20 |

>事件修饰符

21 |
22 | 父元素 23 | 24 | 25 |
26 |

>按键修饰符

27 | 28 |
29 | 30 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/HomeWork/TODO.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | li { 7 | list-style: none; 8 | } 9 | 10 | label { 11 | display: inline-block; 12 | width: 150px; 13 | margin: 5px; 14 | word-wrap: break-word; 15 | vertical-align: middle; 16 | } 17 | 18 | button { 19 | padding: 3px 10px; 20 | margin: 10px 5px; 21 | background-color: #fff; 22 | border: 1px solid #666; 23 | border-radius: 3px; 24 | } 25 | 26 | button:disabled { 27 | background-color: #999; 28 | color: #eee; 29 | border-color: #999; 30 | } 31 | 32 | input[type="text"] { 33 | border: 0; 34 | border-bottom: 1px solid #ccc; 35 | width: 150px; 36 | margin: 5px; 37 | } 38 | 39 | h2 { 40 | text-align: center; 41 | } 42 | 43 | #todo { 44 | width: 300px; 45 | margin: 10px auto; 46 | } 47 | 48 | .todo-input { 49 | text-align: center; 50 | } 51 | 52 | .completed { 53 | text-decoration: line-through; 54 | color: #666; 55 | } -------------------------------------------------------------------------------- /lesson/1.vue基础入门/HomeWork/TODO.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | TODO 9 | 10 | 11 | 12 | 13 |
14 |

剩余待办:{{'这里需要改下代码显示剩余待办'}}条

15 |
16 | 17 | 18 |
19 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/HomeWork/TODO.js: -------------------------------------------------------------------------------- 1 | var todo = new Vue({ 2 | el: '#todo', 3 | data: { 4 | todoNew: '', 5 | todoList: [] 6 | }, 7 | methods: { 8 | todoAdd: function () { 9 | //添加待办数据对象,包括text内容,completed完成状态,editable编辑状态三个属性 10 | //添加后清空输入框 11 | }, 12 | todoRemove: function (index) { 13 | //删除待办数据 14 | }, 15 | editTodo: function (index) { 16 | //编辑待办数据 17 | } 18 | }, 19 | filters: { 20 | editShow: function (value) { 21 | //按键文字切换,分别是「确认」和「编辑」,编辑中时「删除」按钮的状态为disable 22 | } 23 | }, 24 | computed: { 25 | todoTotal: function () { 26 | //todo:获取剩余待办数量 27 | } 28 | } 29 | }) -------------------------------------------------------------------------------- /lesson/1.vue基础入门/HomeWorkFinish/TODO.css: -------------------------------------------------------------------------------- 1 | * { 2 | padding: 0; 3 | margin: 0; 4 | } 5 | 6 | li { 7 | list-style: none; 8 | } 9 | 10 | label { 11 | display: inline-block; 12 | width: 150px; 13 | margin: 5px; 14 | word-wrap: break-word; 15 | vertical-align: middle; 16 | } 17 | 18 | button { 19 | padding: 3px 10px; 20 | margin: 10px 5px; 21 | background-color: #fff; 22 | border: 1px solid #666; 23 | border-radius: 3px; 24 | } 25 | 26 | button:disabled { 27 | background-color: #999; 28 | color: #eee; 29 | border-color: #999; 30 | } 31 | 32 | input[type="text"] { 33 | border: 0; 34 | border-bottom: 1px solid #ccc; 35 | width: 150px; 36 | margin: 5px; 37 | } 38 | 39 | h2 { 40 | text-align: center; 41 | } 42 | 43 | #todo { 44 | width: 300px; 45 | margin: 10px auto; 46 | } 47 | 48 | .todo-input { 49 | text-align: center; 50 | } 51 | 52 | .completed { 53 | text-decoration: line-through; 54 | color: #666; 55 | } -------------------------------------------------------------------------------- /lesson/1.vue基础入门/HomeWorkFinish/TODO.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | TODO 9 | 10 | 11 | 12 | 13 |
14 |

剩余待办:{{todoTotal}}条

15 |
16 | 17 | 18 |
19 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/HomeWorkFinish/TODO.js: -------------------------------------------------------------------------------- 1 | var active = function (todos) { 2 | return todos.filter(function (todo) { 3 | return !todo.completed 4 | }) 5 | } 6 | 7 | var todo = new Vue({ 8 | el: '#todo', 9 | data: { 10 | todoNew: '', 11 | todoList: [] 12 | }, 13 | methods: { 14 | todoAdd: function () { 15 | if (!!this.todoNew) { 16 | this.todoList.push({ 17 | text: this.todoNew, 18 | completed: false, 19 | editable: false 20 | }); 21 | this.todoNew = ''; 22 | } 23 | }, 24 | todoRemove: function (index) { 25 | this.todoList.splice(index, 1); 26 | }, 27 | editTodo: function (index) { 28 | this.todoList[index].editable = !this.todoList[index].editable; 29 | } 30 | }, 31 | filters: { 32 | editShow: function (value) { 33 | return value ? '确认' : '编辑'; 34 | } 35 | }, 36 | computed: { 37 | todoTotal: function () { 38 | var actives = active(this.todoList); 39 | return actives.length; 40 | } 41 | } 42 | }) 43 | -------------------------------------------------------------------------------- /lesson/1.vue基础入门/VUE基础入门.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/1.vue基础入门/VUE基础入门.pptx -------------------------------------------------------------------------------- /lesson/1.vue基础入门/lesson.css: -------------------------------------------------------------------------------- 1 | body { 2 | font-family: "Microsoft Yahei", "consolas", Arial, sans-serif, "San Francisco"; 3 | } 4 | 5 | .sky { 6 | color: blue; 7 | } 8 | 9 | .active { 10 | color: green; 11 | } 12 | 13 | .danger { 14 | color: #EF3731; 15 | } -------------------------------------------------------------------------------- /lesson/2.vue组件入门/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/2.vue组件入门/.DS_Store -------------------------------------------------------------------------------- /lesson/2.vue组件入门/VUE组件入门.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/2.vue组件入门/VUE组件入门.pptx -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/1-vue.js: -------------------------------------------------------------------------------- 1 | //全局注册 2 | Vue.component('table-title', { 3 | template: '

我是一个全局注册的组件!

' 4 | }) 5 | 6 | Vue.component('table-item', { 7 | template: '{{text}}', 8 | //组件中的data属性要以函数的形式表现 9 | data: function () { 10 | return { 11 | text: '全局注册的表格组件' 12 | } 13 | } 14 | }) 15 | 16 | new Vue({ 17 | el: '#lesson1' 18 | }) 19 | 20 | //局部注册 21 | var Child1 = { 22 | template: '
我是一个局部注册的组件!
' 23 | } 24 | 25 | new Vue({ 26 | el: '#lesson2', 27 | components: { 28 | //驼峰式命名,会转换成'table-comp' 29 | tableChild: Child1 30 | } 31 | }) 32 | 33 | //组件内部局部注册 34 | var Child2 = { 35 | template: '
我是一个组件内的局部组件!
' 36 | } 37 | 38 | //在组件内部引用其他子组件 39 | Vue.component('table-father', { 40 | //此处的子组件必须包在父组件内,因为template内仅能包含一个根节点 41 | template: '
我是另一个全局注册的组件!
', 42 | components: { 43 | 'table-child': Child2 44 | } 45 | }) 46 | 47 | new Vue({ 48 | el: '#lesson3' 49 | }) -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/1-注册组件.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 1-注册组件 9 | 10 | 11 | 12 | 13 | 14 |
15 |

vue实例1:全局注册

16 | 17 | 18 | 19 | 20 | 21 |
22 |
23 |
24 |

vue实例2:局部注册

25 | 26 | 27 |
28 |
29 |

vue实例3:组件内部的局部注册

30 | 31 |
32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/2-1-vue.js: -------------------------------------------------------------------------------- 1 | //字面量语法 2 | Vue.component('table-item', { 3 | //驼峰式命名,会转换成'another-text' 4 | props: ['text', 'anotherText'], 5 | template: '{{text}}-{{anotherText}}' 6 | }) 7 | 8 | new Vue({ 9 | el: '#lesson1', 10 | data: { 11 | people: [ 12 | { name: '侯亮平', birth: 1970 }, 13 | { name: '陈岩石', birth: 1940 }, 14 | { name: '李达康', birth: 1961 }, 15 | { name: '高小琴', birth: 1976 } 16 | ] 17 | } 18 | }) 19 | 20 | //动态语法 21 | Vue.component('child', { 22 | props: ['myMessage'], 23 | template: '

{{myMessage}}

' 24 | }) 25 | 26 | new Vue({ 27 | el: '#lesson2', 28 | data: { 29 | parentMsg: 'Hello World!' 30 | } 31 | }) 32 | 33 | //prop验证 34 | Vue.component('table-type', { 35 | props: { 36 | sn: Number, 37 | text: String, 38 | 'another-text': { 39 | type: String, 40 | required: true 41 | } 42 | }, 43 | template: '{{sn}}.{{text}} {{anotherText}}' 44 | }) 45 | 46 | new Vue({ 47 | el: '#lesson3' 48 | }) -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/2-1-数据传递-props.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 2-1-数据传递-props 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

vue实例1:字面量语法

17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 |
26 | 27 |
28 |

vue实例2:动态语法

29 | 30 | 31 |
32 | 33 |
34 |

vue实例3:prop验证

35 | 36 | 37 | 38 | 39 | 40 | 41 |
42 |
43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/2-2-vue.js: -------------------------------------------------------------------------------- 1 | Vue.component('table-item', { 2 | props: ['text', 'anotherText'], 3 | template: '{{text}}-{{anotherText}}' 4 | }) 5 | 6 | Vue.component('table-add', { 7 | props: ['addName', 'addBirth'], 8 | template: '', 9 | methods: { 10 | tableAdd: function () { 11 | var p = { name: this.addName, birth: this.addBirth } 12 | this.$emit('table-add', p) 13 | } 14 | } 15 | }) 16 | 17 | Vue.component('table-del', { 18 | template: '', 19 | methods: { 20 | tableDelete: function () { 21 | this.$emit('t-delete'); 22 | } 23 | } 24 | }) 25 | 26 | new Vue({ 27 | el: '#lesson1', 28 | data: { 29 | people: [ 30 | { name: '侯亮平', birth: 1970 }, 31 | { name: '陈岩石', birth: 1940 }, 32 | { name: '李达康', birth: 1961 }, 33 | { name: '高小琴', birth: 1976 } 34 | ], 35 | newName: '', 36 | newBirth: '' 37 | }, 38 | methods: { 39 | peopleAdd: function (data) { 40 | this.people.push(data); 41 | }, 42 | peopleDel: function () { 43 | this.people.pop(); 44 | } 45 | } 46 | }) 47 | -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/2-2-数据传递-组件通信.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 2-2-数据传递-组件间通信 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

vue实例:自定义事件

17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 |
30 | 31 | 32 | 33 | 34 | -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/2-3-vue.js: -------------------------------------------------------------------------------- 1 | Vue.component('lesson-content',{ 2 | template: '\ 3 |
\ 4 |
\ 5 | \ 6 | \ 7 |
\ 8 | \ 9 | \ 10 |
\ 11 | ' 12 | }) 13 | 14 | Vue.component('table-item', { 15 | props: ['text', 'anotherText'], 16 | template: '{{text}}-{{anotherText}}' 17 | }) 18 | 19 | Vue.component('table-add', { 20 | props: ['addName', 'addBirth'], 21 | template: '', 22 | methods: { 23 | tableAdd: function () { 24 | var p = { name: this.addName, birth: this.addBirth } 25 | this.$emit('table-add', p) 26 | } 27 | } 28 | }) 29 | 30 | Vue.component('table-del', { 31 | template: '', 32 | methods: { 33 | tableDelete: function () { 34 | this.$emit('table-delete'); 35 | } 36 | } 37 | }) 38 | 39 | new Vue({ 40 | el: '#lesson1', 41 | data: { 42 | people: [ 43 | { name: '侯亮平', birth: 1970 }, 44 | { name: '陈岩石', birth: 1940 }, 45 | { name: '李达康', birth: 1961 }, 46 | { name: '高小琴', birth: 1976 } 47 | ], 48 | newName: '', 49 | newBirth: '' 50 | }, 51 | computed: { 52 | lastName: function () { 53 | if (this.people.length > 0) { 54 | var last = this.people[this.people.length - 1]; 55 | return last.name; 56 | } 57 | } 58 | }, 59 | methods: { 60 | peopleAdd: function (data) { 61 | this.people.push(data); 62 | }, 63 | peopleDel: function () { 64 | this.people.pop(); 65 | } 66 | } 67 | }) 68 | -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/2-3-数据传递-slot分发.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 2-3-数据传递-slot分发 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 |

vue实例:slot分发

19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 | {{lastName}} 32 | 33 | 34 | 35 |
36 |
37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/3-vue.js: -------------------------------------------------------------------------------- 1 | Vue.component('lesson-content',{ 2 | template: '\ 3 |
\ 4 |
\ 5 | \ 6 | \ 7 |
\ 8 | \ 9 | \ 10 |
\ 11 | ' 12 | }) 13 | 14 | // Vue.component('table-item', { 15 | // props: ['text', 'anotherText'], 16 | // template: '{{text}}-{{anotherText}}' 17 | // }) 18 | 19 | var itemTable = { 20 | props: ['text', 'anotherText'], 21 | template: '{{text}}-{{anotherText}}
' 22 | } 23 | 24 | var itemList = { 25 | props: ['text', 'anotherText'], 26 | template: '
  • {{text}}-{{anotherText}}
  • ' 27 | } 28 | 29 | Vue.component('table-add', { 30 | props: ['addName', 'addBirth'], 31 | template: '', 32 | methods: { 33 | tableAdd: function () { 34 | var p = { name: this.addName, birth: this.addBirth } 35 | this.$emit('table-add', p) 36 | } 37 | } 38 | }) 39 | 40 | Vue.component('table-del', { 41 | template: '', 42 | methods: { 43 | tableDelete: function () { 44 | this.$emit('table-delete'); 45 | } 46 | } 47 | }) 48 | 49 | new Vue({ 50 | el: '#lesson1', 51 | data: { 52 | people: [ 53 | { name: '侯亮平', birth: 1970 }, 54 | { name: '陈岩石', birth: 1940 }, 55 | { name: '李达康', birth: 1961 }, 56 | { name: '高小琴', birth: 1976 } 57 | ], 58 | newName: '', 59 | newBirth: '', 60 | viewComp: 'child-list' 61 | }, 62 | components:{ 63 | childList: itemList, 64 | childTable: itemTable 65 | }, 66 | computed: { 67 | lastName: function () { 68 | if (this.people.length > 0) { 69 | var last = this.people[this.people.length - 1]; 70 | return last.name; 71 | } 72 | } 73 | }, 74 | methods: { 75 | peopleAdd: function (data) { 76 | this.people.push(data); 77 | }, 78 | peopleDel: function () { 79 | this.people.pop(); 80 | }, 81 | changeComp: function(){ 82 | this.viewComp = this.tableComp = this.tableComp === 'child-list' ? 'child-table' : 'child-list'; 83 | } 84 | } 85 | }) 86 | -------------------------------------------------------------------------------- /lesson/2.vue组件入门/src/3-动态组件.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 3-动态组件 9 | 10 | 11 | 12 | 13 | 14 | 15 |
    16 | 17 |

    vue实例

    18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | {{lastName}} 32 | 33 | 34 | 35 |
    36 |
    37 | 38 | 39 | 40 | 41 | -------------------------------------------------------------------------------- /lesson/3.vue组件应用之基础篇/VUE组件应用之基础篇.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/3.vue组件应用之基础篇/VUE组件应用之基础篇.pptx -------------------------------------------------------------------------------- /lesson/3.vue组件应用之基础篇/第三次作业详细说明.md: -------------------------------------------------------------------------------- 1 | ## 第三次作业详细说明: 2 | 3 | ### 作业内容: 4 | 使用VUX组件库完成一个【待办事项】应用,必须用到的组件有Group,Cell,XInput 5 | 6 | ### 作业基本流程: 7 | 8 | 1. `npm install -g vue-cli` 9 | > 安装vue命令行工具 10 | 11 | 2. `vue init whkfzyx/cli my-project` 12 | > 创建项目,my-project替换为你自己的项目名称,运行之后根据提示输入相应信息 13 | 14 | 3. `cd my-project` 15 | > 跳转到你自己的项目文件夹,my-project替换为你自己的项目名称 16 | 17 | 4. `npm install` 18 | > 安装项目依赖包,如果安装速度太慢就安装cnpm命令 19 | > `npm install -g cnpm --registry=https://registry.npm.taobao.org` 20 | > 然后通过cnpm install来安装,因为cnpm是走的淘宝镜像,速度会快一些,建议大家在家里安装,公司的网络对于npm和cnpm都不是特别友好,任何依赖包的安装不全都会导致程序运行失败 21 | 22 | 5. `npm run dev` 23 | > 在开发环境下运行程序 24 | 25 | 6. 在项目的src文件夹中创建各自的项目文件进行开发。 -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/4.vue组件应用之实操篇/.DS_Store -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/VUE组件应用之实操篇.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/4.vue组件应用之实操篇/VUE组件应用之实操篇.pptx -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | selenium-debug.log 9 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/README.md: -------------------------------------------------------------------------------- 1 | # lesson4 2 | 3 | > 第四次作业 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | var config = require('../config') 4 | if (!process.env.NODE_ENV) { 5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 6 | } 7 | 8 | var opn = require('opn') 9 | var path = require('path') 10 | var express = require('express') 11 | var webpack = require('webpack') 12 | var proxyMiddleware = require('http-proxy-middleware') 13 | var webpackConfig = process.env.NODE_ENV === 'testing' 14 | ? require('./webpack.prod.conf') 15 | : require('./webpack.dev.conf') 16 | 17 | // default port where dev server listens for incoming traffic 18 | var port = process.env.PORT || config.dev.port 19 | // automatically open browser, if not set will be false 20 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 21 | // Define HTTP proxies to your custom API backend 22 | // https://github.com/chimurai/http-proxy-middleware 23 | var proxyTable = config.dev.proxyTable 24 | 25 | var app = express() 26 | var compiler = webpack(webpackConfig) 27 | 28 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 29 | publicPath: webpackConfig.output.publicPath, 30 | quiet: true 31 | }) 32 | 33 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 34 | log: () => {} 35 | }) 36 | // force page reload when html-webpack-plugin template changes 37 | compiler.plugin('compilation', function (compilation) { 38 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 39 | hotMiddleware.publish({ action: 'reload' }) 40 | cb() 41 | }) 42 | }) 43 | 44 | // proxy api requests 45 | Object.keys(proxyTable).forEach(function (context) { 46 | var options = proxyTable[context] 47 | if (typeof options === 'string') { 48 | options = { target: options } 49 | } 50 | app.use(proxyMiddleware(options.filter || context, options)) 51 | }) 52 | 53 | // handle fallback for HTML5 history API 54 | app.use(require('connect-history-api-fallback')()) 55 | 56 | // serve webpack bundle output 57 | app.use(devMiddleware) 58 | 59 | // enable hot-reload and state-preserving 60 | // compilation error display 61 | app.use(hotMiddleware) 62 | 63 | // serve pure static assets 64 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 65 | app.use(staticPath, express.static('./static')) 66 | 67 | var uri = 'http://localhost:' + port 68 | 69 | devMiddleware.waitUntilValid(function () { 70 | console.log('> Listening at ' + uri + '\n') 71 | }) 72 | 73 | module.exports = app.listen(port, function (err) { 74 | if (err) { 75 | console.log(err) 76 | return 77 | } 78 | 79 | // when env is testing, don't need open it 80 | 81 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 82 | opn(uri) 83 | } 84 | }) 85 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | postcss: [ 13 | require('autoprefixer')({ 14 | browsers: ['iOS >= 7', 'Android >= 4.1'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | 4 | var projectRoot = path.resolve(__dirname, '../') 5 | const vuxLoader = require('vux-loader') 6 | 7 | var config = require('../config') 8 | var vueLoaderConfig = require('./vue-loader.conf') 9 | 10 | function resolve (dir) { 11 | return path.join(__dirname, '..', dir) 12 | } 13 | 14 | let webpackConfig = { 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.(js|vue)$/, 36 | loader: 'eslint-loader', 37 | enforce: "pre", 38 | include: [resolve('src'), resolve('test')], 39 | options: { 40 | formatter: require('eslint-friendly-formatter') 41 | } 42 | }, 43 | { 44 | test: /\.vue$/, 45 | loader: 'vue-loader', 46 | options: vueLoaderConfig 47 | }, 48 | { 49 | test: /\.js$/, 50 | loader: 'babel-loader', 51 | include: [resolve('src'), resolve('test')] 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url-loader', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url-loader', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | } 71 | } 72 | 73 | 74 | module.exports = vuxLoader.merge(webpackConfig, { 75 | plugins: ['vux-ui', 'progress-bar', 'duplicate-style'] 76 | }) 77 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8080, 27 | autoOpenBrowser: false, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | lesson4 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/4.vue组件应用之实操篇/lesson-4/src/assets/logo.png -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/src/assets/vux_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/4.vue组件应用之实操篇/lesson-4/src/assets/vux_logo.png -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/src/components/Hello.vue: -------------------------------------------------------------------------------- 1 | 22 | 23 | 33 | 34 | 35 | 54 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/src/components/HelloFromVux.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 32 | 33 | 42 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import FastClick from 'fastclick' 5 | // import VueRouter from 'vue-router' 6 | import App from './App' 7 | // import Todo from './pages/todo.vue' 8 | // import Hello from '@/components/Hello' 9 | import router from './router' 10 | 11 | // Vue.use(VueRouter) 12 | 13 | // const routes = [{ 14 | // path: '/', 15 | // component: Todo 16 | // }, { 17 | // path: '/hello', 18 | // component: Hello 19 | // }] 20 | 21 | // const router = new VueRouter({ 22 | // routes 23 | // }) 24 | 25 | FastClick.attach(document.body) 26 | 27 | Vue.config.productionTip = false 28 | 29 | /* eslint-disable no-new */ 30 | new Vue({ 31 | router, 32 | render: h => h(App) 33 | }).$mount('#app-box') 34 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Todo from '../pages/todo.vue' 4 | 5 | Vue.use(Router) 6 | 7 | export default new Router({ 8 | routes: [ 9 | { 10 | path: '/', 11 | name: 'todo', 12 | component: Todo 13 | } 14 | ] 15 | }) 16 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/4.vue组件应用之实操篇/lesson-4/static/.gitkeep -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/getingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /lesson/4.vue组件应用之实操篇/lesson-4/test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/Vue移动交付之Vue-Router.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/5.vue移动交付之vue-router/Vue移动交付之Vue-Router.pptx -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | selenium-debug.log 9 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/README.md: -------------------------------------------------------------------------------- 1 | # lesson5 2 | 3 | > 第五次课程演示DEMO 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | postcss: [ 13 | require('autoprefixer')({ 14 | browsers: ['iOS >= 7', 'Android >= 4.1'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | 4 | var projectRoot = path.resolve(__dirname, '../') 5 | const vuxLoader = require('vux-loader') 6 | 7 | var config = require('../config') 8 | var vueLoaderConfig = require('./vue-loader.conf') 9 | 10 | function resolve (dir) { 11 | return path.join(__dirname, '..', dir) 12 | } 13 | 14 | let webpackConfig = { 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.(js|vue)$/, 36 | loader: 'eslint-loader', 37 | enforce: "pre", 38 | include: [resolve('src'), resolve('test')], 39 | options: { 40 | formatter: require('eslint-friendly-formatter') 41 | } 42 | }, 43 | { 44 | test: /\.vue$/, 45 | loader: 'vue-loader', 46 | options: vueLoaderConfig 47 | }, 48 | { 49 | test: /\.js$/, 50 | loader: 'babel-loader', 51 | include: [resolve('src'), resolve('test')] 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url-loader', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url-loader', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | } 71 | } 72 | 73 | 74 | module.exports = vuxLoader.merge(webpackConfig, { 75 | plugins: ['vux-ui', 'progress-bar', 'duplicate-style'] 76 | }) 77 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8000, 27 | autoOpenBrowser: false, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | lesson5 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 21 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/5.vue移动交付之vue-router/lesson-5/src/assets/logo.png -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/src/assets/vux_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/5.vue移动交付之vue-router/lesson-5/src/assets/vux_logo.png -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import FastClick from 'fastclick' 5 | // import VueRouter from 'vue-router' 6 | import App from './App' 7 | // import Todo from './pages/todo.vue' 8 | // import Page1 from './pages/page1.vue' 9 | import router from './router' 10 | 11 | // Vue.use(VueRouter) 12 | 13 | // const routes = [{ 14 | // path: '/', 15 | // component: Todo 16 | // }, { 17 | // path: '/page1', 18 | // component: Page1 19 | // }] 20 | 21 | // const router = new VueRouter({ 22 | // routes 23 | // }) 24 | 25 | FastClick.attach(document.body) 26 | 27 | Vue.config.productionTip = false 28 | 29 | // router.beforeEach((to, from, next) => { 30 | // // console.log(to) 31 | // // console.log(from) 32 | // next({path: '/page1'}) 33 | // }) 34 | 35 | /* eslint-disable no-new */ 36 | new Vue({ 37 | router, 38 | render: h => h(App) 39 | }).$mount('#app-box') 40 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/src/pages/page1.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 34 | 35 | 38 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Todo from '@/pages/todo.vue' 4 | import Page1 from '@/pages/page1.vue' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'index', 13 | component: Page1, 14 | meta: { 15 | title: '首页' 16 | } 17 | }, 18 | { 19 | path: '/todo/:id?', 20 | name: 'todo', 21 | component: Todo, 22 | meta: { 23 | title: '待办' 24 | }, 25 | beforeEnter: (to, from, next) => { 26 | console.log(to) 27 | next() 28 | } 29 | } 30 | ] 31 | }) 32 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/5.vue移动交付之vue-router/lesson-5/static/.gitkeep -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/getingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /lesson/5.vue移动交付之vue-router/lesson-5/test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/Vue移动交付之Axios.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/6.vue移动交付之axios/Vue移动交付之Axios.pptx -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | selenium-debug.log 9 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/README.md: -------------------------------------------------------------------------------- 1 | # lesson5 2 | 3 | > 第五次课程演示DEMO 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | postcss: [ 13 | require('autoprefixer')({ 14 | browsers: ['iOS >= 7', 'Android >= 4.1'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | 4 | var projectRoot = path.resolve(__dirname, '../') 5 | const vuxLoader = require('vux-loader') 6 | 7 | var config = require('../config') 8 | var vueLoaderConfig = require('./vue-loader.conf') 9 | 10 | function resolve (dir) { 11 | return path.join(__dirname, '..', dir) 12 | } 13 | 14 | let webpackConfig = { 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.(js|vue)$/, 36 | loader: 'eslint-loader', 37 | enforce: "pre", 38 | include: [resolve('src'), resolve('test')], 39 | options: { 40 | formatter: require('eslint-friendly-formatter') 41 | } 42 | }, 43 | { 44 | test: /\.vue$/, 45 | loader: 'vue-loader', 46 | options: vueLoaderConfig 47 | }, 48 | { 49 | test: /\.js$/, 50 | loader: 'babel-loader', 51 | include: [resolve('src'), resolve('test')] 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url-loader', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url-loader', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | } 71 | } 72 | 73 | 74 | module.exports = vuxLoader.merge(webpackConfig, { 75 | plugins: ['vux-ui', 'progress-bar', 'duplicate-style'] 76 | }) 77 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8000, 27 | autoOpenBrowser: false, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | lesson6 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 32 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/6.vue移动交付之axios/lesson-6/src/assets/logo.png -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/src/assets/vux_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/6.vue移动交付之axios/lesson-6/src/assets/vux_logo.png -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import FastClick from 'fastclick' 5 | import App from './App' 6 | import router from './router' 7 | import Axios from 'axios' 8 | import './mock' 9 | import { ToastPlugin, LoadingPlugin } from 'vux' 10 | 11 | Vue.use(ToastPlugin) 12 | Vue.use(LoadingPlugin) 13 | 14 | FastClick.attach(document.body) 15 | 16 | Vue.config.productionTip = false 17 | 18 | // Vue.prototype.$axios = Axios 19 | 20 | // 带配置的Axios 21 | Vue.prototype.$axios = Axios.create({ 22 | baseURL: 'http://localhost:8000/' 23 | }) 24 | 25 | /* eslint-disable no-new */ 26 | new Vue({ 27 | router, 28 | render: h => h(App) 29 | }).$mount('#app-box') 30 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/src/mock/index.js: -------------------------------------------------------------------------------- 1 | import Axios from 'axios' 2 | import MockAdapter from 'axios-mock-adapter' 3 | 4 | const mock = new MockAdapter(Axios) 5 | 6 | mock.onGet('/todo-list').reply(200, require('./list.json')) 7 | mock.onPost('/login').reply(config => { 8 | console.log(config) 9 | return new Promise((resolve, reject) => { 10 | setTimeout(() => { 11 | // promise拒绝请求 12 | if (config.data.username === 'error') { 13 | reject({error: '网络错误!'}) 14 | } 15 | // promise通过请求 16 | if (config.data.username === 'admin' && config.data.password === '123456') { 17 | resolve([200, { success: true }]) 18 | } else { 19 | resolve([200, { 20 | success: false, 21 | errorMsg: '账号密码错误!' 22 | }]) 23 | } 24 | }, 1000) 25 | }) 26 | }) 27 | // 请求失败测试 28 | mock.onPost().reply(500) 29 | 30 | export default mock 31 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/src/mock/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | { 4 | "todo": "待办1", 5 | "done": false 6 | }, 7 | { 8 | "todo": "待办2", 9 | "done": false 10 | }, 11 | { 12 | "todo": "待办3", 13 | "done": false 14 | }, 15 | { 16 | "todo": "待办4", 17 | "done": false 18 | }, 19 | { 20 | "todo": "待办5", 21 | "done": false 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Todo from '@/pages/Todo.vue' 4 | import Login from '@/pages/Login.vue' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'index', 13 | component: Todo 14 | }, 15 | { 16 | path: '/login', 17 | name: 'login', 18 | component: Login 19 | } 20 | ] 21 | }) 22 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/6.vue移动交付之axios/lesson-6/static/.gitkeep -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/getingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /lesson/6.vue移动交付之axios/lesson-6/test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/Vue移动交付之Vuex.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/7.vue移动交付之vuex/Vue移动交付之Vuex.pptx -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | selenium-debug.log 9 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/README.md: -------------------------------------------------------------------------------- 1 | # lesson5 2 | 3 | > 第五次课程演示DEMO 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | postcss: [ 13 | require('autoprefixer')({ 14 | browsers: ['iOS >= 7', 'Android >= 4.1'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | 4 | var projectRoot = path.resolve(__dirname, '../') 5 | const vuxLoader = require('vux-loader') 6 | 7 | var config = require('../config') 8 | var vueLoaderConfig = require('./vue-loader.conf') 9 | 10 | function resolve (dir) { 11 | return path.join(__dirname, '..', dir) 12 | } 13 | 14 | let webpackConfig = { 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.(js|vue)$/, 36 | loader: 'eslint-loader', 37 | enforce: "pre", 38 | include: [resolve('src'), resolve('test')], 39 | options: { 40 | formatter: require('eslint-friendly-formatter') 41 | } 42 | }, 43 | { 44 | test: /\.vue$/, 45 | loader: 'vue-loader', 46 | options: vueLoaderConfig 47 | }, 48 | { 49 | test: /\.js$/, 50 | loader: 'babel-loader', 51 | include: [resolve('src'), resolve('test')] 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url-loader', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url-loader', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | } 71 | } 72 | 73 | 74 | module.exports = vuxLoader.merge(webpackConfig, { 75 | plugins: ['vux-ui', 'progress-bar', 'duplicate-style'] 76 | }) 77 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8000, 27 | autoOpenBrowser: false, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | lesson7 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 12 | 13 | 32 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/7.vue移动交付之vuex/lesson-7/src/assets/logo.png -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/src/assets/vux_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/7.vue移动交付之vuex/lesson-7/src/assets/vux_logo.png -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import FastClick from 'fastclick' 5 | import App from './App' 6 | import router from './router' 7 | import Axios from 'axios' 8 | import './mock' 9 | import Vuex from 'vuex' 10 | import { ToastPlugin, LoadingPlugin } from 'vux' 11 | 12 | Vue.use(Vuex) // 在vue实例中加入vuex插件 13 | Vue.use(ToastPlugin) 14 | Vue.use(LoadingPlugin) 15 | 16 | FastClick.attach(document.body) 17 | 18 | Vue.config.productionTip = false 19 | 20 | // Vue.prototype.$axios = Axios 21 | 22 | // 带配置的Axios 23 | Vue.prototype.$axios = Axios.create({ 24 | baseURL: 'http://localhost:8000/' 25 | }) 26 | 27 | const store = new Vuex.Store({ 28 | state: { 29 | todoList: [{ 30 | 'todo': '待办1', 31 | 'done': false 32 | }, 33 | { 34 | 'todo': '待办2', 35 | 'done': false 36 | }, 37 | { 38 | 'todo': '待办3', 39 | 'done': false 40 | }, 41 | { 42 | 'todo': '待办4', 43 | 'done': false 44 | }, 45 | { 46 | 'todo': '待办5', 47 | 'done': false 48 | }] 49 | }, 50 | getters: { 51 | undos (state) { 52 | return state.todoList.filter(todo => !todo.done) 53 | } 54 | }, 55 | mutations: { 56 | TODO_ADD (state, payload) { 57 | state.todoList.push(payload.todo) 58 | }, 59 | TODO_DONE (state, payload) { 60 | state.todoList[payload.index].done = true 61 | }, 62 | TODO_DEL (state, payload) { 63 | state.todoList.splice(payload.index, 1) 64 | } 65 | }, 66 | actions: { 67 | todoAdd ({ commit }, todo) { 68 | commit({ 69 | type: 'TODO_ADD', 70 | todo: todo, 71 | done: todo.done 72 | }) 73 | }, 74 | todoControl ({ commit }, payload) { 75 | switch (payload.cmd) { 76 | case 'done': 77 | commit({ 78 | type: 'TODO_DONE', 79 | index: payload.index 80 | }) 81 | break 82 | case 'delete': 83 | commit({ 84 | type: 'TODO_DEL', 85 | index: payload.index 86 | }) 87 | break 88 | default: 89 | break 90 | } 91 | } 92 | } 93 | }) 94 | /* eslint-disable no-new */ 95 | new Vue({ 96 | router, 97 | store, 98 | render: h => h(App) 99 | }).$mount('#app-box') 100 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/src/mock/index.js: -------------------------------------------------------------------------------- 1 | import Axios from 'axios' 2 | import MockAdapter from 'axios-mock-adapter' 3 | 4 | const mock = new MockAdapter(Axios) 5 | 6 | mock.onGet('/todo-list').reply(200, require('./list.json')) 7 | mock.onPost('/login').reply(config => { 8 | console.log(config) 9 | return new Promise((resolve, reject) => { 10 | setTimeout(() => { 11 | // promise拒绝请求 12 | if (config.data.username === 'error') { 13 | reject({error: '网络错误!'}) 14 | } 15 | // promise通过请求 16 | if (config.data.username === 'admin' && config.data.password === '123456') { 17 | resolve([200, { success: true }]) 18 | } else { 19 | resolve([200, { 20 | success: false, 21 | errorMsg: '账号密码错误!' 22 | }]) 23 | } 24 | }, 1000) 25 | }) 26 | }) 27 | // 请求失败测试 28 | mock.onPost().reply(500) 29 | 30 | export default mock 31 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/src/mock/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | { 4 | "todo": "待办1", 5 | "done": false 6 | }, 7 | { 8 | "todo": "待办2", 9 | "done": false 10 | }, 11 | { 12 | "todo": "待办3", 13 | "done": false 14 | }, 15 | { 16 | "todo": "待办4", 17 | "done": false 18 | }, 19 | { 20 | "todo": "待办5", 21 | "done": false 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Todo1 from '@/pages/Todo1.vue' 4 | import Todo2 from '@/pages/Todo2.vue' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'index', 13 | component: Todo1 14 | }, 15 | { 16 | path: '/todo', 17 | name: 'todo', 18 | component: Todo2 19 | } 20 | ] 21 | }) 22 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/7.vue移动交付之vuex/lesson-7/static/.gitkeep -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/getingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /lesson/7.vue移动交付之vuex/lesson-7/test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/Vue拓展之ES6语法解析.pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/8.vue拓展之ES6语法解析/Vue拓展之ES6语法解析.pptx -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | selenium-debug.log 9 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/README.md: -------------------------------------------------------------------------------- 1 | # lesson5 2 | 3 | > 第五次课程演示DEMO 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | postcss: [ 13 | require('autoprefixer')({ 14 | browsers: ['iOS >= 7', 'Android >= 4.1'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | 4 | var projectRoot = path.resolve(__dirname, '../') 5 | const vuxLoader = require('vux-loader') 6 | 7 | var config = require('../config') 8 | var vueLoaderConfig = require('./vue-loader.conf') 9 | 10 | function resolve (dir) { 11 | return path.join(__dirname, '..', dir) 12 | } 13 | 14 | let webpackConfig = { 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.(js|vue)$/, 36 | loader: 'eslint-loader', 37 | enforce: "pre", 38 | include: [resolve('src'), resolve('test')], 39 | options: { 40 | formatter: require('eslint-friendly-formatter') 41 | } 42 | }, 43 | { 44 | test: /\.vue$/, 45 | loader: 'vue-loader', 46 | options: vueLoaderConfig 47 | }, 48 | { 49 | test: /\.js$/, 50 | loader: 'babel-loader', 51 | include: [resolve('src'), resolve('test')] 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url-loader', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url-loader', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | } 71 | } 72 | 73 | 74 | module.exports = vuxLoader.merge(webpackConfig, { 75 | plugins: ['vux-ui', 'progress-bar', 'duplicate-style'] 76 | }) 77 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8000, 27 | autoOpenBrowser: false, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | lesson7 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 33 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/8.vue拓展之ES6语法解析/lesson-8/src/assets/logo.png -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/assets/vux_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/8.vue拓展之ES6语法解析/lesson-8/src/assets/vux_logo.png -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import FastClick from 'fastclick' 5 | import App from './App' 6 | import router from './router' 7 | import Axios from 'axios' 8 | import './mock' 9 | import Vuex from 'vuex' 10 | import { ToastPlugin, LoadingPlugin } from 'vux' 11 | import * as util from './util.js' 12 | // import {foo} from './util.js' 13 | console.log(util) 14 | // foo() 15 | // util.fun() 16 | 17 | Vue.use(Vuex) // 在vue实例中加入vuex插件 18 | Vue.use(ToastPlugin) 19 | Vue.use(LoadingPlugin) 20 | 21 | FastClick.attach(document.body) 22 | 23 | Vue.config.productionTip = false 24 | 25 | // Vue.prototype.$axios = Axios 26 | 27 | // 带配置的Axios 28 | Vue.prototype.$axios = Axios.create({ 29 | baseURL: 'http://localhost:8000/' 30 | }) 31 | 32 | const store = new Vuex.Store({ 33 | state: { 34 | todoList: [{ 35 | 'todo': '待办1', 36 | 'done': false 37 | }, 38 | { 39 | 'todo': '待办2', 40 | 'done': false 41 | }, 42 | { 43 | 'todo': '待办3', 44 | 'done': false 45 | }, 46 | { 47 | 'todo': '待办4', 48 | 'done': false 49 | }, 50 | { 51 | 'todo': '待办5', 52 | 'done': false 53 | }] 54 | }, 55 | getters: { 56 | undos (state) { 57 | return state.todoList.filter(todo => !todo.done) 58 | } 59 | }, 60 | mutations: { 61 | TODO_ADD (state, payload) { 62 | state.todoList.push(payload.todo) 63 | }, 64 | TODO_DONE (state, payload) { 65 | state.todoList[payload.index].done = true 66 | }, 67 | TODO_DEL (state, payload) { 68 | state.todoList.splice(payload.index, 1) 69 | } 70 | }, 71 | actions: { 72 | todoAdd ({ commit }, todo) { 73 | commit({ 74 | type: 'TODO_ADD', 75 | todo: todo, 76 | done: todo.done 77 | }) 78 | }, 79 | todoControl ({ commit }, payload) { 80 | switch (payload.cmd) { 81 | case 'done': 82 | commit({ 83 | type: 'TODO_DONE', 84 | index: payload.index 85 | }) 86 | break 87 | case 'delete': 88 | commit({ 89 | type: 'TODO_DEL', 90 | index: payload.index 91 | }) 92 | break 93 | default: 94 | break 95 | } 96 | } 97 | } 98 | }) 99 | /* eslint-disable no-new */ 100 | new Vue({ 101 | router, 102 | store, 103 | render: h => h(App) 104 | }).$mount('#app-box') 105 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/mock/index.js: -------------------------------------------------------------------------------- 1 | import Axios from 'axios' 2 | import MockAdapter from 'axios-mock-adapter' 3 | 4 | const mock = new MockAdapter(Axios) 5 | 6 | mock.onGet('/todo-list').reply(200, require('./list.json')) 7 | mock.onPost('/login').reply(config => { 8 | console.log(config) 9 | return new Promise((resolve, reject) => { 10 | setTimeout(() => { 11 | // promise拒绝请求 12 | if (config.data.username === 'error') { 13 | reject({error: '网络错误!'}) 14 | } 15 | // promise通过请求 16 | if (config.data.username === 'admin' && config.data.password === '123456') { 17 | resolve([200, { success: true }]) 18 | } else { 19 | resolve([200, { 20 | success: false, 21 | errorMsg: '账号密码错误!' 22 | }]) 23 | } 24 | }, 1000) 25 | }) 26 | }) 27 | // 请求失败测试 28 | mock.onPost().reply(500) 29 | 30 | export default mock 31 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/mock/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | { 4 | "todo": "待办1", 5 | "done": false 6 | }, 7 | { 8 | "todo": "待办2", 9 | "done": false 10 | }, 11 | { 12 | "todo": "待办3", 13 | "done": false 14 | }, 15 | { 16 | "todo": "待办4", 17 | "done": false 18 | }, 19 | { 20 | "todo": "待办5", 21 | "done": false 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Todo1 from '@/pages/Todo1.vue' 4 | import Todo2 from '@/pages/Todo2.vue' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'index', 13 | component: Todo1 14 | }, 15 | { 16 | path: '/todo', 17 | name: 'todo', 18 | component: Todo2 19 | } 20 | ] 21 | }) 22 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/src/util.js: -------------------------------------------------------------------------------- 1 | const foo = () => { 2 | console.log('foo') 3 | } 4 | 5 | const boo = () => { 6 | console.log('boo') 7 | } 8 | 9 | export {foo as fun, boo as bun, boo as cun} 10 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/8.vue拓展之ES6语法解析/lesson-8/static/.gitkeep -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/getingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /lesson/8.vue拓展之ES6语法解析/lesson-8/test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/Vue拓展之前端调试pptx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/9.vue拓展之前端调试/Vue拓展之前端调试pptx -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["env", { "modules": false }], 4 | "stage-2" 5 | ], 6 | "plugins": ["transform-runtime"], 7 | "comments": false, 8 | "env": { 9 | "test": { 10 | "presets": ["env", "stage-2"], 11 | "plugins": [ "istanbul" ] 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | 3 | [*] 4 | charset = utf-8 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | insert_final_newline = true 9 | trim_trailing_whitespace = true 10 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/.eslintignore: -------------------------------------------------------------------------------- 1 | build/*.js 2 | config/*.js 3 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/.eslintrc.js: -------------------------------------------------------------------------------- 1 | // http://eslint.org/docs/user-guide/configuring 2 | 3 | module.exports = { 4 | root: true, 5 | parser: 'babel-eslint', 6 | parserOptions: { 7 | sourceType: 'module' 8 | }, 9 | env: { 10 | browser: true, 11 | }, 12 | // https://github.com/feross/standard/blob/master/RULES.md#javascript-standard-style 13 | extends: 'standard', 14 | // required to lint *.vue files 15 | plugins: [ 16 | 'html' 17 | ], 18 | // add your custom rules here 19 | 'rules': { 20 | // allow paren-less arrow functions 21 | 'arrow-parens': 0, 22 | // allow async-await 23 | 'generator-star-spacing': 0, 24 | // allow debugger during development 25 | 'no-debugger': process.env.NODE_ENV === 'production' ? 2 : 0 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log 5 | yarn-error.log 6 | test/unit/coverage 7 | test/e2e/reports 8 | selenium-debug.log 9 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/.postcssrc.js: -------------------------------------------------------------------------------- 1 | // https://github.com/michael-ciniawsky/postcss-load-config 2 | 3 | module.exports = { 4 | "plugins": { 5 | // to edit target browsers: use "browserlist" field in package.json 6 | "autoprefixer": {} 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/README.md: -------------------------------------------------------------------------------- 1 | # lesson5 2 | 3 | > 第九次课程演示DEMO 4 | 5 | ## Build Setup 6 | 7 | ``` bash 8 | # install dependencies 9 | npm install 10 | 11 | # serve with hot reload at localhost:8080 12 | npm run dev 13 | 14 | # build for production with minification 15 | npm run build 16 | 17 | # build for production and view the bundle analyzer report 18 | npm run build --report 19 | 20 | # run unit tests 21 | npm run unit 22 | 23 | # run e2e tests 24 | npm run e2e 25 | 26 | # run all tests 27 | npm test 28 | ``` 29 | 30 | For detailed explanation on how things work, checkout the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader). 31 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | { 16 | name: 'npm', 17 | currentVersion: exec('npm --version'), 18 | versionRequirement: packageConfig.engines.npm 19 | } 20 | ] 21 | 22 | module.exports = function () { 23 | var warnings = [] 24 | for (var i = 0; i < versionRequirements.length; i++) { 25 | var mod = versionRequirements[i] 26 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 27 | warnings.push(mod.name + ': ' + 28 | chalk.red(mod.currentVersion) + ' should be ' + 29 | chalk.green(mod.versionRequirement) 30 | ) 31 | } 32 | } 33 | 34 | if (warnings.length) { 35 | console.log('') 36 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 37 | console.log() 38 | for (var i = 0; i < warnings.length; i++) { 39 | var warning = warnings[i] 40 | console.log(' ' + warning) 41 | } 42 | console.log() 43 | process.exit(1) 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // http://vuejs.github.io/vue-loader/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }), 12 | postcss: [ 13 | require('autoprefixer')({ 14 | browsers: ['iOS >= 7', 'Android >= 4.1'] 15 | }) 16 | ] 17 | } 18 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | 4 | var projectRoot = path.resolve(__dirname, '../') 5 | const vuxLoader = require('vux-loader') 6 | 7 | var config = require('../config') 8 | var vueLoaderConfig = require('./vue-loader.conf') 9 | 10 | function resolve (dir) { 11 | return path.join(__dirname, '..', dir) 12 | } 13 | 14 | let webpackConfig = { 15 | entry: { 16 | app: './src/main.js' 17 | }, 18 | output: { 19 | path: config.build.assetsRoot, 20 | filename: '[name].js', 21 | publicPath: process.env.NODE_ENV === 'production' 22 | ? config.build.assetsPublicPath 23 | : config.dev.assetsPublicPath 24 | }, 25 | resolve: { 26 | extensions: ['.js', '.vue', '.json'], 27 | alias: { 28 | 'vue$': 'vue/dist/vue.esm.js', 29 | '@': resolve('src'), 30 | } 31 | }, 32 | module: { 33 | rules: [ 34 | { 35 | test: /\.(js|vue)$/, 36 | loader: 'eslint-loader', 37 | enforce: "pre", 38 | include: [resolve('src'), resolve('test')], 39 | options: { 40 | formatter: require('eslint-friendly-formatter') 41 | } 42 | }, 43 | { 44 | test: /\.vue$/, 45 | loader: 'vue-loader', 46 | options: vueLoaderConfig 47 | }, 48 | { 49 | test: /\.js$/, 50 | loader: 'babel-loader', 51 | include: [resolve('src'), resolve('test')] 52 | }, 53 | { 54 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 55 | loader: 'url-loader', 56 | query: { 57 | limit: 10000, 58 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 59 | } 60 | }, 61 | { 62 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 63 | loader: 'url-loader', 64 | query: { 65 | limit: 10000, 66 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 67 | } 68 | } 69 | ] 70 | } 71 | } 72 | 73 | 74 | module.exports = vuxLoader.merge(webpackConfig, { 75 | plugins: ['vux-ui', 'progress-bar', 'duplicate-style'] 76 | }) 77 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8000, 27 | autoOpenBrowser: false, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | lesson9 7 | 8 | 9 |
    10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 13 | 14 | 33 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/9.vue拓展之前端调试/lesson-9/src/assets/logo.png -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/assets/vux_logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/9.vue拓展之前端调试/lesson-9/src/assets/vux_logo.png -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import FastClick from 'fastclick' 5 | import App from './App' 6 | import router from './router' 7 | import Axios from 'axios' 8 | import './mock' 9 | import Vuex from 'vuex' 10 | import { ToastPlugin, LoadingPlugin } from 'vux' 11 | import * as util from './util.js' 12 | // import {foo} from './util.js' 13 | console.log(util) 14 | // foo() 15 | // util.fun() 16 | 17 | Vue.use(Vuex) // 在vue实例中加入vuex插件 18 | Vue.use(ToastPlugin) 19 | Vue.use(LoadingPlugin) 20 | 21 | FastClick.attach(document.body) 22 | 23 | Vue.config.productionTip = false 24 | 25 | // Vue.prototype.$axios = Axios 26 | 27 | // 带配置的Axios 28 | Vue.prototype.$axios = Axios.create({ 29 | baseURL: 'http://localhost:8000/' 30 | }) 31 | 32 | const store = new Vuex.Store({ 33 | state: { 34 | todoList: [{ 35 | 'todo': '待办1', 36 | 'done': false 37 | }, 38 | { 39 | 'todo': '待办2', 40 | 'done': false 41 | }, 42 | { 43 | 'todo': '待办3', 44 | 'done': false 45 | }, 46 | { 47 | 'todo': '待办4', 48 | 'done': false 49 | }, 50 | { 51 | 'todo': '待办5', 52 | 'done': false 53 | }] 54 | }, 55 | getters: { 56 | undos (state) { 57 | return state.todoList.filter(todo => !todo.done) 58 | } 59 | }, 60 | mutations: { 61 | TODO_ADD (state, payload) { 62 | state.todoList.push(payload.todo) 63 | }, 64 | TODO_DONE (state, payload) { 65 | state.todoList[payload.index].done = true 66 | }, 67 | TODO_DEL (state, payload) { 68 | state.todoList.splice(payload.index, 1) 69 | } 70 | }, 71 | actions: { 72 | todoAdd ({ commit }, todo) { 73 | commit({ 74 | type: 'TODO_ADD', 75 | todo: todo, 76 | done: todo.done 77 | }) 78 | }, 79 | todoControl ({ commit }, payload) { 80 | switch (payload.cmd) { 81 | case 'done': 82 | commit({ 83 | type: 'TODO_DONE', 84 | index: payload.index 85 | }) 86 | break 87 | case 'delete': 88 | commit({ 89 | type: 'TODO_DEL', 90 | index: payload.index 91 | }) 92 | break 93 | default: 94 | break 95 | } 96 | } 97 | } 98 | }) 99 | /* eslint-disable no-new */ 100 | new Vue({ 101 | router, 102 | store, 103 | render: h => h(App) 104 | }).$mount('#app-box') 105 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/mock/index.js: -------------------------------------------------------------------------------- 1 | import Axios from 'axios' 2 | import MockAdapter from 'axios-mock-adapter' 3 | 4 | const mock = new MockAdapter(Axios) 5 | 6 | mock.onGet('/todo-list').reply(200, require('./list.json')) 7 | mock.onPost('/login').reply(config => { 8 | console.log(config) 9 | return new Promise((resolve, reject) => { 10 | setTimeout(() => { 11 | // promise拒绝请求 12 | if (config.data.username === 'error') { 13 | reject({error: '网络错误!'}) 14 | } 15 | // promise通过请求 16 | if (config.data.username === 'admin' && config.data.password === '123456') { 17 | resolve([200, { success: true }]) 18 | } else { 19 | resolve([200, { 20 | success: false, 21 | errorMsg: '账号密码错误!' 22 | }]) 23 | } 24 | }, 1000) 25 | }) 26 | }) 27 | // 请求失败测试 28 | mock.onPost().reply(500) 29 | 30 | export default mock 31 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/mock/list.json: -------------------------------------------------------------------------------- 1 | { 2 | "list": [ 3 | { 4 | "todo": "待办1", 5 | "done": false 6 | }, 7 | { 8 | "todo": "待办2", 9 | "done": false 10 | }, 11 | { 12 | "todo": "待办3", 13 | "done": false 14 | }, 15 | { 16 | "todo": "待办4", 17 | "done": false 18 | }, 19 | { 20 | "todo": "待办5", 21 | "done": false 22 | } 23 | ] 24 | } -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import Todo1 from '@/pages/Todo1.vue' 4 | import Todo2 from '@/pages/Todo2.vue' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'index', 13 | component: Todo1 14 | }, 15 | { 16 | path: '/todo', 17 | name: 'todo', 18 | component: Todo2 19 | } 20 | ] 21 | }) 22 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/src/util.js: -------------------------------------------------------------------------------- 1 | const foo = () => { 2 | console.log('foo') 3 | } 4 | 5 | const boo = () => { 6 | console.log('boo') 7 | } 8 | 9 | export {foo as fun, boo as bun, boo as cun} 10 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/static/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/whkfzyx/how-to-learn/e6b5fa6741bf571611c3d41157f7a5919f3f087f/lesson/9.vue拓展之前端调试/lesson-9/static/.gitkeep -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/getingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | // 2. run the nightwatch test suite against it 6 | // to run in additional browsers: 7 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 8 | // 2. add it to the --env flag below 9 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 10 | // For more information on Nightwatch's config file, see 11 | // http://nightwatchjs.org/guide#settings-file 12 | var opts = process.argv.slice(2) 13 | if (opts.indexOf('--config') === -1) { 14 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 15 | } 16 | if (opts.indexOf('--env') === -1) { 17 | opts = opts.concat(['--env', 'chrome']) 18 | } 19 | 20 | var spawn = require('cross-spawn') 21 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 22 | 23 | runner.on('exit', function (code) { 24 | server.close() 25 | process.exit(code) 26 | }) 27 | 28 | runner.on('error', function (err) { 29 | server.close() 30 | throw err 31 | }) 32 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/unit/.eslintrc: -------------------------------------------------------------------------------- 1 | { 2 | "env": { 3 | "mocha": true 4 | }, 5 | "globals": { 6 | "expect": true, 7 | "sinon": true 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | Vue.config.productionTip = false 3 | 4 | // Polyfill fn.bind() for PhantomJS 5 | /* eslint-disable no-extend-native */ 6 | Function.prototype.bind = require('function-bind') 7 | 8 | // require all test files (files that ends with .spec.js) 9 | const testsContext = require.context('./specs', true, /\.spec$/) 10 | testsContext.keys().forEach(testsContext) 11 | 12 | // require all src files except main.js for coverage. 13 | // you can also change this to match only the subset of files that 14 | // you want coverage for. 15 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 16 | srcContext.keys().forEach(srcContext) 17 | -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } -------------------------------------------------------------------------------- /lesson/9.vue拓展之前端调试/lesson-9/test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | --------------------------------------------------------------------------------