├── src ├── assets │ ├── styles │ │ ├── style.styl │ │ ├── test-stylus.styl │ │ ├── footer.styl │ │ └── global.styl │ └── images │ │ ├── a.jpg │ │ ├── bg.png │ │ ├── beijing.jpg │ │ ├── unChecked.svg │ │ └── checked.svg ├── index.js ├── todo │ ├── header.vue │ ├── footer.jsx │ ├── tabs.vue │ ├── item.vue │ └── todo.vue └── app.vue ├── .gitignore ├── .babelrc ├── postcss.config.js ├── package.json ├── webpack.config.js ├── README.md └── yarn.lock /src/assets/styles/style.styl: -------------------------------------------------------------------------------- 1 | body 2 | font-size: 30 -------------------------------------------------------------------------------- /src/assets/styles/test-stylus.styl: -------------------------------------------------------------------------------- 1 | body 2 | font-size 20px -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | node_modules/ 3 | node_modules/ 4 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": ["env"], 3 | "plugins": [ 4 | "transform-vue-jsx" 5 | ] 6 | } -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [ 3 | require('autoprefixer') 4 | ] 5 | } -------------------------------------------------------------------------------- /src/assets/images/a.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carrieguo/vue.js-todolist/HEAD/src/assets/images/a.jpg -------------------------------------------------------------------------------- /src/assets/images/bg.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carrieguo/vue.js-todolist/HEAD/src/assets/images/bg.png -------------------------------------------------------------------------------- /src/assets/images/beijing.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/carrieguo/vue.js-todolist/HEAD/src/assets/images/beijing.jpg -------------------------------------------------------------------------------- /src/assets/styles/footer.styl: -------------------------------------------------------------------------------- 1 | #footer 2 | margin-top 40px 3 | text-align center 4 | color #bfbfbf 5 | font-size 10px 6 | text-shadow 0 1px 0 #ffffff 7 | -------------------------------------------------------------------------------- /src/assets/styles/global.styl: -------------------------------------------------------------------------------- 1 | html, body 2 | margin 0 3 | padding 0 4 | width 100% 5 | height 100% 6 | 7 | body 8 | background-image url('../images/beijing.jpg') 9 | background-size cover 10 | background-position center 11 | font 14px 'microsoft yahei' 12 | color '#4d4d4d' 13 | font-weight 300 -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue'; 2 | import App from './app.vue'; 3 | 4 | //import './assets/styles/test.css'; 5 | import './assets/styles/style.styl' 6 | import './assets/styles/global.styl'; 7 | 8 | const root = document.createElement('div'); 9 | document.body.appendChild(root); 10 | 11 | new Vue({ 12 | render: (h) => h(App) 13 | }).$mount(root) -------------------------------------------------------------------------------- /src/todo/header.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 16 | -------------------------------------------------------------------------------- /src/todo/footer.jsx: -------------------------------------------------------------------------------- 1 | import '../assets/styles/footer.styl' 2 | 3 | export default { 4 | data() { 5 | return { 6 | author: 'no one' 7 | } 8 | }, 9 | render() { 10 | return( 11 | 14 | ) 15 | } 16 | } -------------------------------------------------------------------------------- /src/assets/images/unChecked.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/app.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 22 | 23 | -------------------------------------------------------------------------------- /src/assets/images/checked.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "vue.js-learn", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1", 8 | "build": "cross-env NODE_ENV=production webpack", 9 | "dev": "cross-env NODE_ENV=development webpack-dev-server --open" 10 | }, 11 | "repository": { 12 | "type": "git", 13 | "url": "git+https://github.com/carrieguo/vue.js-learn.git" 14 | }, 15 | "author": "", 16 | "license": "ISC", 17 | "bugs": { 18 | "url": "https://github.com/carrieguo/vue.js-learn/issues" 19 | }, 20 | "homepage": "https://github.com/carrieguo/vue.js-learn#readme", 21 | "dependencies": { 22 | "autoprefixer": "^9.6.1", 23 | "babel-loader": "^8.0.6", 24 | "babel-plugin-transform-vue-jsx": "^3.7.0", 25 | "cross-env": "^5.2.0", 26 | "css-loader": "^3.0.0", 27 | "file-loader": "^4.1.0", 28 | "postcss": "^7.0.17", 29 | "postcss-loader": "^3.0.0", 30 | "stylus": "^0.54.5", 31 | "stylus-loader": "^3.0.2", 32 | "url-loader": "^2.0.1", 33 | "vue": "^2.6.10", 34 | "vue-loader": "^15.7.0", 35 | "vue-template-compiler": "^2.6.10" 36 | }, 37 | "devDependencies": { 38 | "@babel/core": "^7.0.0", 39 | "babel-helper-vue-jsx-merge-props": "^2.0.3", 40 | "babel-plugin-syntax-jsx": "^6.18.0", 41 | "babel-preset-env": "^1.7.0", 42 | "clean-webpack-plugin": "^3.0.0", 43 | "html-webpack-plugin": "^3.2.0", 44 | "mini-css-extract-plugin": "^0.8.0", 45 | "webpack": "^4.36.1", 46 | "webpack-cli": "^3.3.6", 47 | "webpack-dev-server": "^3.7.2" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /src/todo/tabs.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 45 | 46 | 78 | 79 | -------------------------------------------------------------------------------- /src/todo/item.vue: -------------------------------------------------------------------------------- 1 | 12 | 13 | 28 | 29 | 84 | 85 | 86 | -------------------------------------------------------------------------------- /src/todo/todo.vue: -------------------------------------------------------------------------------- 1 | 24 | 25 | 75 | 76 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const VueLoaderPlugin = require('vue-loader/lib/plugin'); 3 | const HTMLPlugin = require('html-webpack-plugin'); 4 | const { CleanWebpackPlugin } = require('clean-webpack-plugin'); 5 | 6 | const isDev = process.env.NODE_ENV === 'development'; 7 | 8 | const webpack = require('webpack'); 9 | const MiniCssExtractPlugin = require('mini-css-extract-plugin'); 10 | 11 | const config = { 12 | //入口, __dirname 是当前文件所在目录 13 | entry: path.join(__dirname, 'src/index.js'), 14 | //输出 15 | output: { 16 | filename: 'bundle.[hash:8].js', 17 | path: path.join(__dirname, 'dist') 18 | }, 19 | //webpack原生只支持js文件类型,只支持ES5语法,我们使用以.vue文件名结尾的文件时,需要为其指定loader 20 | module: { 21 | rules: [ 22 | { 23 | test: /\.vue$/, 24 | loader: 'vue-loader' 25 | }, 26 | { 27 | test: /\.jsx$/, 28 | loader: 'babel-loader' 29 | }, 30 | //将小于1024d的图片转为base64,减少http请求 31 | { 32 | test: /\.(gif|jpg|jpeg|png|svg)$/, 33 | use: [ 34 | { 35 | loader: 'url-loader', 36 | options: { 37 | limit: 1024, 38 | name: '[name].[ext]', 39 | outputPath: 'assets/img/' 40 | } 41 | } 42 | ] 43 | } 44 | ] 45 | }, 46 | plugins: [ 47 | new CleanWebpackPlugin(), 48 | // 请确保引入这个插件! 49 | new VueLoaderPlugin(), 50 | new HTMLPlugin(), 51 | //new webpack.HotModuleReplacementPlugin(), 52 | new MiniCssExtractPlugin({ 53 | // Options similar to the same options in webpackOptions.output 54 | // all options are optional 55 | filename: '[name].css', 56 | chunkFilename: '[id].css', 57 | ignoreOrder: false, // Enable to remove warnings about conflicting order 58 | }), 59 | ], 60 | 61 | optimization: { 62 | splitChunks: { 63 | chunks (chunk) { 64 | // exclude `my-excluded-chunk` 65 | return chunk.name !== 'my-excluded-chunk'; 66 | } 67 | } 68 | } 69 | } 70 | 71 | if(isDev) { 72 | config.module.rules.push({ 73 | //css预处理器,使用模块化的方式写css代码 74 | //stylus-loader专门用来处理stylus文件,处理完成后变成css文件,交给css-loader.webpack的loader就是这样一级一级向上传递,每一层loader只处理自己关心的部分 75 | test: /\.styl/, 76 | use: [ 77 | 'vue-style-loader', 78 | 'css-loader', 79 | { 80 | loader: 'postcss-loader', 81 | options: { sourceMap: true } 82 | }, 83 | 'stylus-loader' 84 | ] 85 | }); 86 | config.devServer = { 87 | overlay: { 88 | errors: true 89 | }, 90 | hot: true 91 | } 92 | } else { 93 | config.output.filename = '[name].[chunkhash:8].js'; 94 | config.module.rules.push( 95 | //css预处理器,使用模块化的方式写css代码 96 | //stylus-loader专门用来处理stylus文件,处理完成后变成css文件,交给css-loader.webpack的loader就是这样一级一级向上传递,每一层loader只处理自己关心的部分 97 | { 98 | test: /\.styl/, 99 | use: [ 100 | { 101 | loader: MiniCssExtractPlugin.loader, 102 | options: { 103 | // you can specify a publicPath here 104 | // by default it uses publicPath in webpackOptions.output 105 | publicPath: './', 106 | hmr: process.env.NODE_ENV === 'development', 107 | }, 108 | }, 109 | 'css-loader', 110 | { 111 | loader: 'postcss-loader', 112 | options: { sourceMap: true } 113 | }, 114 | 'stylus-loader' 115 | ] 116 | }, 117 | ); 118 | 119 | config.plugins.push( 120 | new MiniCssExtractPlugin({ 121 | // Options similar to the same options in webpackOptions.output 122 | // all options are optional 123 | filename: 'styles.[chunkhash].[name].css', 124 | chunkFilename: '[id].css', 125 | ignoreOrder: false, // Enable to remove warnings about conflicting order 126 | }) 127 | ); 128 | } 129 | 130 | module.exports = config; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## 关于项目 2 | 3 | 这是一个为了学习vue和webpack实现的一个todo-list demo。 4 | 5 | ### 本项目webpack的版本为4.36.1 6 | 7 | 因为教程中很多知识都比较老了,很多包现在都被弃用。为了与时俱进,我用了最新版本的webpack,并使用了官方文档推荐的新npm包,来代替已经被弃用的包,具体包的配置,请大家参考[package.json](https://github.com/carrieguo/vue.js-todolist/blob/master/package.json) 8 | 9 | 将项目克隆到本地之后,可通过以下三种方式下载项目依赖的包 10 | 1. 通过npm 命令,但是由于国内网速限制,很容易失败(在国外或者有VPN的同学可以使用) 11 | ```sh 12 | npm install 13 | ``` 14 | 2. 通过cnpm命令, 需要安装淘宝镜像 http://npm.taobao.org/ 15 | ```sh 16 | cnpm install 17 | ``` 18 | 3. yarn (推荐使用yarn,需要先安装yarn https://yarnpkg.com/lang/zh-hans/docs/install/#windows-stable) 19 | ```sh 20 | yarn 21 | ``` 22 | 23 | 运行命令 24 | ```sh 25 | npm run dev 26 | ``` 27 | 28 | 如果遇到问题,欢迎给我留言。 29 | 30 | 31 | 以下是我的学习笔记,欢迎大家参考: 32 | 33 | # vue 34 | 35 | vue相对于react,使用起来会更简单,因为vuex, vue router都是官方在维护,比react第三方维护要好很多。 36 | ### 学习目标 37 | 1. 重点学习核心实用方法 38 | 2. 配置开发时前端工程 39 | 3. webpack优化配置,网络优化,减少http请求,压缩静态资源文件,实用浏览器的长缓存让应用的流量变小,加快加载速度。 40 | 41 | ### 前端的价值: 42 | 学习一门技术,考虑工程化问题, 43 | 1. 搭建前端工程 44 | 2. 网络优化 http的理解,缓存http请求 45 | 3. API定制,前后端分离之后,与后端的交流借助于api接口 46 | 4. nodejs层 前端工程的搭建,基本上都是围绕nodejs, webpack, grunt, gulp 工具都是在nodejs环境中去运行;很多公司在前端和后端的api层之间加一个node js层,用node做转发或数据处理。 47 | 48 | ### 作为初学者要了解vue架构,自己手动搭建项目 49 | 因为vue-cli生成的项目,没有办法直接投入到生产环境中,它是一个广泛适用的模板,不同的项目有不同的定制需求,vue-cli是基于webpack的前端工程。 50 | 51 | webpack 用于打包前端资源, 前端资源有很多不同的类型 js, css, img, font 通过http请求加载,开发webapp时都是一整个js加载到浏览器端之后再把所有的内容渲染出来,很多时候都可以以js文件作为入口 52 | vscode 打开命令行 ctrl+` 53 | 54 | ### 目录结构 55 | ``` 56 | vue todo project 57 | │ README.md 58 | │ package.json 59 | | package-lock.json 60 | | webpack.config.json 61 | | yarn.lock 62 | | .babelrc 63 | | .gitignore 64 | │ 65 | └───dist 66 | │ bundle.js 67 | │ 68 | └───node_modules 69 | | 70 | | 71 | └───src 72 | | app.vue 73 | │ index.js 74 | | 75 | └───assests 76 | │ 77 | └───images 78 | │ a.jpg 79 | │ b.jpg 80 | └───styles 81 | | a.css 82 | | style.styl 83 | └────todo 84 | footer.jsx 85 | header.vue 86 | item.vue 87 | tabs.vue 88 | todo.vue 89 | ``` 90 | 91 | ### 初始化项目 92 | ```sh 93 | npm init 94 | ``` 95 | ### 安装依赖包 96 | ```sh 97 | npm install webpack vue vue-loader 98 | ``` 99 | `WARN 提示, vue-loader需要peer第三方依赖 css-loader vue-template-compiler` 100 | ```sh 101 | npm install css-loader vue-template-compiler 102 | ``` 103 | 104 | ### `app.vue` 105 | ```js 106 | //.vue文件是vue的开发方式,位于根目录src文件夹下 107 | //vue要显示出来的模板 108 | 111 | 112 | //控制显示内容如何变化 113 | 122 | 123 | 128 | ``` 129 | 130 | ### `index.js 入口文件` 131 | ```js 132 | import Vue from 'vue'; 133 | import App from './app.vue'; 134 | 135 | import './assests/styles/test.css'; 136 | import './assests/image/bg.jpeg' 137 | 138 | const root = document.createElement('div'); 139 | document.body.appendChild(root); 140 | 141 | new Vue({ 142 | render: (h) => h(App) 143 | }).$mount(root) 144 | ``` 145 | 146 | ### `webpack.config.js` 147 | ```js 148 | const path = require('path'); 149 | 150 | module.exports = { 151 | target: 'web', 152 | //入口, __dirname 是当前文件所在目录 153 | entry: path.join(__dirname, 'src/index.js'), 154 | //输出 155 | output: { 156 | filename: 'bundle.js', 157 | path: path.join(__dirname, 'dist'); 158 | }, 159 | //webpack原生只支持js文件类型,只支持ES5语法,我们使用以.vue文件名结尾的文件时,需要为其指定loader 160 | module: { 161 | rules: [ 162 | { 163 | test: /\.vue$/, 164 | loader: 'vue-loader' 165 | }, 166 | //将css写入到HTML 167 | { 168 | test: /\.css$/, 169 | use: [ 170 | 'vue-style-loader', 171 | 'css-loader' 172 | ] 173 | }, 174 | //stylus-loader专门用来处理stylus文件,处理完成后变成css文件,交给css-loader.webpack的loader就是这样一级一级向上传递,每一层loader只处理自己关心的部分 175 | { 176 | test: /\.styl/, 177 | use: [ 178 | 'vue-style-loader', 179 | 'css-loader', 180 | 'stylus-loader' 181 | ] 182 | }, 183 | //将小于1024d的图片转为base64,减少http请求 184 | { 185 | test: /\.(gif|jpg|jpeg|png|svg)$/, 186 | use: [ 187 | { 188 | loader: 'url-loader', 189 | options: { 190 | limit: 1024, 191 | name: '[name].[ext]' 192 | } 193 | } 194 | ] 195 | } 196 | ] 197 | } 198 | } 199 | 200 | 201 | ``` 202 | 203 | ### `安装相应的loader, url-loader 依赖 file-loader` 204 | ```sh 205 | npm i style-loader url-loader file-loader 206 | ``` 207 | 208 | ### `package.json` 209 | ```json 210 | //调用项目下的webpack, 如果不设置,运行webpack命令会调用全局环境的webpack 211 | "scripts": { 212 | "build": "cross-env NODE_ENV=production webpack --config webpack.config.js", 213 | "dev": "cross-env NODE_ENV=development webpack-dev-server --config webpack.config.js" 214 | } 215 | ``` 216 | 217 | ```sh 218 | npm run build 219 | ``` 220 | 221 | webpack 帮我们 生成一个dist目录,里面生成 bundle.js,前端项目希望把一些零碎的js打包到一起,减少http请求。使用模块依赖,可复用。 222 | 223 | webpack 配置中需要添加 Vue Loader 的插件 224 | 参考 https://vue-loader.vuejs.org/zh/guide/#vue-cli 225 | 226 | ## webpack-dev-server cross-env 227 | webpack-dev-server 是一个webpack的包 228 | cross-env 在不同的环境上设置不同的环境变量不一样,cross-env解决了这个问题 229 | `安装` 230 | 231 | ```sh 232 | npm install webpack-dev-server 233 | npm install cross-env 234 | ``` 235 | 236 | ## html-webpack-plugin 237 | 238 | 239 | ## vue2 240 | 241 | `数据绑定框架` 将js数据绑定到html中 242 | 243 | `vue文件开发方式` vue是一个组件化的框架。react有jsx,它很好的处理了在JavaScript中去书写HTML,html是通过render方法动态生成的,每次数据变化都回去执行render方法。vue对jsx支持不好,所以自创了这种.vue文件,直观,方便 244 | 245 | `render方法` 组件中有数据变化,都会重新执行render方法,产生新的HTML,并更新。 246 | .vue 文件中的`