76 |
77 |
78 | ```
79 |
80 | ### css预处理、后处理
81 | 开发过程中使用Sass、Less、Stylus等css预处理
82 | ```javascript
83 | // webpack.config.js
84 | {
85 | // 基本的css loader
86 | test: /\.css$/,
87 | use: [
88 | 'style-loader',
89 | 'css-loader'
90 | ]
91 | },
92 | {
93 | test: /\.styl$/,
94 | use: [
95 | 'style-loader',
96 | 'css-loader',
97 | {
98 | loader: 'postcss-loader',
99 | options: {
100 | sourceMap: true
101 | }
102 | },
103 | 'stylus-loader'
104 | ]
105 | }
106 | ```
107 | 更进一步,加载postcss后处理器
108 | ```javascript
109 | // webpack.config.js
110 | {
111 | test: /\.styl$/,
112 | use: [
113 | 'style-loader',
114 | 'css-loader',
115 | {
116 | loader: 'postcss-loader',
117 | options: {
118 | sourceMap: true
119 | }
120 | },
121 | 'stylus-loader'
122 | ]
123 | }
124 | ```
125 | 根目录新建postcss.config.js配置文件
126 | ```javascript
127 | const autoprefixer = require('autoprefixer') // 加载autoprefixer(浏览器兼容前缀)
128 | module.exports = {
129 | plugins: [
130 | autoprefixer()
131 | ]
132 | }
133 | ```
134 |
135 | ## JSX
136 | > React的核心机制之一就是可以在内存中创建虚拟的DOM元素。React利用虚拟DOM来减少对实际DOM的操作从而提升性能。
137 |
138 | JSX就是Javascript和XML结合的一种格式。React发明了JSX,利用HTML语法来创建虚拟DOM。当遇到<,JSX就当HTML解析,遇到{就当JavaScript解析。
139 |
140 | 如何在vue中使用jsx?
141 | ```javascript
142 | // webpack.config.js
143 | {
144 | test: /\.jsx$/,
145 | loader: 'babel-loader'
146 | }
147 |
148 | // 需要的package
149 | "babel-core": "^6.26.0",
150 | "babel-helper-vue-jsx-merge-props": "^2.0.3",
151 | "babel-loader": "^7.1.2",
152 | "babel-plugin-syntax-jsx": "^6.18.0",
153 | "babel-plugin-transform-vue-jsx": "^3.5.0"
154 |
155 | // .babelrc
156 | {
157 | "presets": [
158 | "env"
159 | ],
160 | "plugins":[
161 | "transform-vue-jsx"
162 | ]
163 | }
164 |
165 | // jsx文件
166 | import '../assets/style/footer.styl'
167 | export default {
168 | data() {
169 | return {
170 | author: 'Ioodu'
171 | }
172 | },
173 | render() {
174 | return (
175 |
178 | )
179 | }
180 | }
181 | ```
182 | facebook.github.io [JSX语法](http://facebook.github.io/jsx/)
183 |
184 | ## vue组件间通信
185 | > 组件实例的作用域是孤立的。这意味着不能 (也不应该) 在子组件的模板内直接引用父组件的数据。父组件的数据需要通过 prop 才能下发到子组件中。
186 |
187 | 父组件
188 | ```vue
189 |
195 |
201 | ```
202 | 父组件业务逻辑处理
203 | ```javascript
204 | // 引入组件
205 | components: {
206 | Item,
207 | Tabs,
208 | },
209 | methods: {
210 | deleteTodo(id) {
211 | this.todos.splice(this.todos.findIndex(todo => todo.id === id), 1)
212 | },
213 | }
214 | ```
215 | 子组件
216 | ```vue
217 |
218 |
219 | ```
220 | ```javascript
221 | props: {
222 | todo: {
223 | type: Object,
224 | required: true
225 | }
226 | },
227 | methods: {
228 | deleteTodo(){
229 | this.$emit('del', this.todo.id) // 触发事件 并且带参数
230 | }
231 | }
232 |
233 | ```
234 | ## webpack打包优化的基本点
235 |
236 | 1. 优化插件
237 | - OccurenceOrderPlugin :为组件分配ID,通过这个插件webpack可以分析和优先考虑使用最多的模块,并为它们分配最小的ID
238 | - UglifyJsPlugin:压缩JS代码;
239 | - ExtractTextPlugin:分离CSS和JS文件
240 | 2. 缓存
241 |
242 | - hash
243 |
244 | - clean-webpack-plugin
245 |
246 | ...
247 |
--------------------------------------------------------------------------------
/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-cayman
--------------------------------------------------------------------------------
/dist/app.762ed07e.js:
--------------------------------------------------------------------------------
1 | webpackJsonp([0],[
2 | /* 0 */
3 | /***/ (function(module, exports) {
4 |
5 | /*
6 | MIT License http://www.opensource.org/licenses/mit-license.php
7 | Author Tobias Koppers @sokra
8 | */
9 | // css base code, injected by the css-loader
10 | module.exports = function(useSourceMap) {
11 | var list = [];
12 |
13 | // return the list of modules as css string
14 | list.toString = function toString() {
15 | return this.map(function (item) {
16 | var content = cssWithMappingToString(item, useSourceMap);
17 | if(item[2]) {
18 | return "@media " + item[2] + "{" + content + "}";
19 | } else {
20 | return content;
21 | }
22 | }).join("");
23 | };
24 |
25 | // import a list of modules into the list
26 | list.i = function(modules, mediaQuery) {
27 | if(typeof modules === "string")
28 | modules = [[null, modules, ""]];
29 | var alreadyImportedModules = {};
30 | for(var i = 0; i < this.length; i++) {
31 | var id = this[i][0];
32 | if(typeof id === "number")
33 | alreadyImportedModules[id] = true;
34 | }
35 | for(i = 0; i < modules.length; i++) {
36 | var item = modules[i];
37 | // skip already imported module
38 | // this implementation is not 100% perfect for weird media query combinations
39 | // when a module is imported multiple times with different media queries.
40 | // I hope this will never occur (Hey this way we have smaller bundles)
41 | if(typeof item[0] !== "number" || !alreadyImportedModules[item[0]]) {
42 | if(mediaQuery && !item[2]) {
43 | item[2] = mediaQuery;
44 | } else if(mediaQuery) {
45 | item[2] = "(" + item[2] + ") and (" + mediaQuery + ")";
46 | }
47 | list.push(item);
48 | }
49 | }
50 | };
51 | return list;
52 | };
53 |
54 | function cssWithMappingToString(item, useSourceMap) {
55 | var content = item[1] || '';
56 | var cssMapping = item[3];
57 | if (!cssMapping) {
58 | return content;
59 | }
60 |
61 | if (useSourceMap && typeof btoa === 'function') {
62 | var sourceMapping = toComment(cssMapping);
63 | var sourceURLs = cssMapping.sources.map(function (source) {
64 | return '/*# sourceURL=' + cssMapping.sourceRoot + source + ' */'
65 | });
66 |
67 | return [content].concat(sourceURLs).concat([sourceMapping]).join('\n');
68 | }
69 |
70 | return [content].join('\n');
71 | }
72 |
73 | // Adapted from convert-source-map (MIT)
74 | function toComment(sourceMap) {
75 | // eslint-disable-next-line no-undef
76 | var base64 = btoa(unescape(encodeURIComponent(JSON.stringify(sourceMap))));
77 | var data = 'sourceMappingURL=data:application/json;charset=utf-8;base64,' + base64;
78 |
79 | return '/*# ' + data + ' */';
80 | }
81 |
82 |
83 | /***/ }),
84 | /* 1 */
85 | /***/ (function(module, exports, __webpack_require__) {
86 |
87 | /*
88 | MIT License http://www.opensource.org/licenses/mit-license.php
89 | Author Tobias Koppers @sokra
90 | Modified by Evan You @yyx990803
91 | */
92 |
93 | var hasDocument = typeof document !== 'undefined'
94 |
95 | if (typeof DEBUG !== 'undefined' && DEBUG) {
96 | if (!hasDocument) {
97 | throw new Error(
98 | 'vue-style-loader cannot be used in a non-browser environment. ' +
99 | "Use { target: 'node' } in your Webpack config to indicate a server-rendering environment."
100 | ) }
101 | }
102 |
103 | var listToStyles = __webpack_require__(16)
104 |
105 | /*
106 | type StyleObject = {
107 | id: number;
108 | parts: Array
109 | }
110 |
111 | type StyleObjectPart = {
112 | css: string;
113 | media: string;
114 | sourceMap: ?string
115 | }
116 | */
117 |
118 | var stylesInDom = {/*
119 | [id: number]: {
120 | id: number,
121 | refs: number,
122 | parts: Array<(obj?: StyleObjectPart) => void>
123 | }
124 | */}
125 |
126 | var head = hasDocument && (document.head || document.getElementsByTagName('head')[0])
127 | var singletonElement = null
128 | var singletonCounter = 0
129 | var isProduction = false
130 | var noop = function () {}
131 |
132 | // Force single-tag solution on IE6-9, which has a hard limit on the # of
46 |
--------------------------------------------------------------------------------
/src/assets/img/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/chinadbo/vue-webpack-start/506e48c37c479e27d48986aef8568207b1a8b3b5/src/assets/img/bg.jpg
--------------------------------------------------------------------------------
/src/assets/style/footer.styl:
--------------------------------------------------------------------------------
1 | #footer
2 | text-align center
3 | margin-top 40px
4 | color #000
5 | font-size 10
6 | text-shadow 0 1px 0 #bfbfbf
--------------------------------------------------------------------------------
/src/assets/style/global.styl:
--------------------------------------------------------------------------------
1 | html,
2 | body
3 | margin 0
4 | padding 0
5 | width 100%
6 | height 100%
7 | body
8 | background-image url('../img/bg.jpg')
9 | background-size cover
10 | background-position center center
11 | font-size 14px
12 | color #4d4d4d
13 | font-weight 300
14 | font-smoothing antialiased
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | import Vue from 'vue'
2 | import App from './app.vue'
3 |
4 | import './assets/style/global.styl'
5 |
6 | const root = document.createElement('div')
7 | document.body.appendChild(root)
8 |
9 | new Vue({
10 | render: (h) => h(App)
11 | }).$mount(root)
--------------------------------------------------------------------------------
/src/todo/footer.jsx:
--------------------------------------------------------------------------------
1 | import '../assets/style/footer.styl'
2 | export default {
3 | data() {
4 | return {
5 | author: 'Ioodu'
6 | }
7 | },
8 | render() {
9 | return (
10 |
13 | )
14 | }
15 | }
--------------------------------------------------------------------------------
/src/todo/header.vue:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 |
15 |
16 |
--------------------------------------------------------------------------------
/src/todo/items.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 |
8 |
9 |
10 |
11 |
12 |
27 |
28 |
65 |
--------------------------------------------------------------------------------
/src/todo/tabs.vue:
--------------------------------------------------------------------------------
1 |
2 |
3 | {{unFinishedTodoLength}} items left
4 |
5 | {{state}}
11 |
12 | Clear All completed
13 |
14 |
15 |
47 |
48 |
84 |
85 |
--------------------------------------------------------------------------------
/src/todo/todo.vue:
--------------------------------------------------------------------------------
1 |
2 |
23 |
24 |
70 |
71 |
91 |
92 |
--------------------------------------------------------------------------------
/webpack.config.js:
--------------------------------------------------------------------------------
1 | const path = require('path')
2 | const isDev = process.env.NODE_ENV === 'development'
3 | const HTMLPlugin = require('html-webpack-plugin')
4 | const ExtractPlugin = require('extract-text-webpack-plugin')
5 |
6 | const webpack = require('webpack')
7 | const config = {
8 | target: 'web',
9 | entry: path.join(__dirname, 'src/index.js'),
10 | output: {
11 | filename: 'bundle.[hash:8].js',
12 | path: path.join(__dirname, 'dist')
13 | },
14 | module: {
15 | rules: [
16 | // {
17 | // test: /\.css$/,
18 | // use: [
19 | // 'style-loader',
20 | // 'css-loader'
21 | // ]
22 | // },
23 | {
24 | test: /\.vue$/,
25 | loader: 'vue-loader'
26 | },
27 | {
28 | test: /\.jsx$/,
29 | loader: 'babel-loader'
30 | },
31 | {
32 | test: /\.(gif|png|jpe?g|svg)$/,
33 | use: [
34 | {
35 | loader: 'url-loader',
36 | options: {
37 | limit: 1024,
38 | name: '[name].urloader.[ext]'
39 | }
40 | }
41 | ]
42 | }
43 | ]
44 | },
45 | plugins: [
46 | new webpack.DefinePlugin({
47 | 'process.env': {
48 | NODE_ENV: isDev ? '"development"' : '"production"'
49 | }
50 | }),
51 | new HTMLPlugin()
52 | ]
53 | }
54 |
55 | if (isDev) {
56 | config.module.rules.push({
57 | test: /\.styl$/,
58 | use: [
59 | 'style-loader',
60 | 'css-loader',
61 | {
62 | loader: 'postcss-loader',
63 | options: {
64 | sourceMap: true
65 | }
66 | },
67 | 'stylus-loader'
68 | ]
69 | })
70 | config.devtool = '#cheap-module-eval-source-map'
71 | config.devServer = {
72 | port: 8000,
73 | host: '0.0.0.0',
74 | overlay: {
75 | errors: true
76 | },
77 | hot: true,
78 | }
79 | config.plugins.push(
80 | new webpack.HotModuleReplacementPlugin(),
81 | new webpack.NoEmitOnErrorsPlugin()
82 | )
83 | } else {
84 | config.entry = {
85 | app: path.join(__dirname, 'src/index.js'),
86 | vendor: ['vue']
87 | }
88 | config.output.filename = '[name].[chunkhash:8].js'
89 | config.module.rules.push({
90 | test: /\.styl$/,
91 | use: ExtractPlugin.extract({
92 | fallback: 'style-loader',
93 | use: [
94 | 'css-loader',
95 | {
96 | loader: 'postcss-loader',
97 | options: {
98 | sourceMap: true
99 | }
100 | },
101 | 'stylus-loader'
102 | ]
103 | })
104 | })
105 | config.plugins.push(
106 | new ExtractPlugin('style.[contentHash:8].css'),
107 | new webpack.optimize.CommonsChunkPlugin({
108 | name: 'vendor'
109 | }),
110 | new webpack.optimize.CommonsChunkPlugin({
111 | name: 'runtime'
112 | })
113 | )
114 | }
115 |
116 | module.exports = config
--------------------------------------------------------------------------------