Merge pull request #7 from allan2coder/dev2

大升级
This commit is contained in:
xsf 2020-05-22 17:55:43 +08:00 committed by GitHub
commit a39cb1c687
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
34 changed files with 9012 additions and 841 deletions

View File

@ -1,5 +1,10 @@
{ {
"presets": ["es2015", "stage-2"], "presets": [
"plugins": ["transform-runtime"], ["env", {
"comments": false "modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}]
]
} }

View File

@ -1,9 +0,0 @@
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

1
.gitignore vendored
View File

@ -2,4 +2,3 @@
node_modules/ node_modules/
dist/ dist/
npm-debug.log npm-debug.log
.idea/

View File

@ -1,4 +1,6 @@
# Vue2-SPA # Vue2-SPA
> 可能是全网最干净的 `vue` 仓库
> A Vue.js project with axios/vue-router/webpack > A Vue.js project with axios/vue-router/webpack
@ -103,29 +105,25 @@ const app = new Vue({
// 现在,应用已经启动了! // 现在,应用已经启动了!
``` ```
### 生产环境要注意的地方: ### 有关打包优化
第三方库单独打包
```
npm i autodll-webpack-plugin -D
```
webpack 配置:
```
new AutoDllPlugin({
inject: true, // will inject the DLL bundle to index.html
debug: true,
filename: '[name]_[hash].js',
path: './dll',
entry: {
vendor: ['vue', 'vue-router'] // webpack 会去 `node_modules` 去找
}
})
```
每次打包,这个插件都会检查注册在 `entry` 中的第三方库。如果没有变化,插件就会使用缓存中的打包文件,减少了打包的时间,这时 Hash 也不会变化。
> 1、生产环境下若项目不是放在服务器的根目录下会访问不到静态资源此时你只需要修改下config文件夹内index.js的build中的assetsPublicPath即可
```
before
assetsPublicPath: '/',
```
```
after:
assetsPublicPath: '/wx/otherPath/static',
```
> 2、在写静态资源的时候最好使用相对路径
```
error:
background: url(../assets/img/icon.png);
```
```
right:
background: url(./../assets/img/icon.png);
```
## Other SPA(其他单页) ## Other SPA(其他单页)

View File

@ -1 +0,0 @@
theme: jekyll-theme-cayman

View File

@ -1,36 +1,15 @@
// https://github.com/shelljs/shelljs const webpack = require('webpack');
require('./check-versions')() const config = require('./webpack.prod.conf');
require('shelljs/global')
env.NODE_ENV = 'production'
var path = require('path') webpack(config, (err, stats) => {
var config = require('../config') if (err || stats.hasErrors()) {
var ora = require('ora') // 在这里处理错误
var webpack = require('webpack') console.error(err);
var webpackConfig = require('./webpack.prod.conf') return;
}
console.log( // 处理完成
' Tip:\n' + console.log(stats.toString({
' Built files are meant to be served over an HTTP server.\n' + chunks: false, // 使构建过程更静默无输出
' Opening index.html over file:// won\'t work.\n' colors: true // 在控制台展示颜色
) }));
});
var spinner = ora('building for production...')
spinner.start()
var assetsPath = path.join(config.build.assetsRoot, config.build.assetsSubDirectory)
rm('-rf', assetsPath)
mkdir('-p', assetsPath)
cp('-R', 'static/*', assetsPath)
webpack(webpackConfig, function (err, stats) {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false,
chunks: false,
chunkModules: false
}) + '\n')
})

View File

@ -1,45 +0,0 @@
var semver = require('semver')
var chalk = require('chalk')
var packageConfig = require('../package.json')
var exec = function (cmd) {
return require('child_process')
.execSync(cmd).toString().trim()
}
var versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
},
{
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
}
]
module.exports = function () {
var warnings = []
for (var i = 0; i < versionRequirements.length; i++) {
var mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (var i = 0; i < warnings.length; i++) {
var warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}

View File

@ -1,9 +0,0 @@
/* eslint-disable */
require('eventsource-polyfill')
var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true')
hotClient.subscribe(function (event) {
if (event.action === 'reload') {
window.location.reload()
}
})

View File

@ -1,72 +0,0 @@
require('./check-versions')()
var config = require('../config')
if (!process.env.NODE_ENV) process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV)
var path = require('path')
var express = require('express')
var webpack = require('webpack')
var opn = require('opn')
var proxyMiddleware = require('http-proxy-middleware')
var webpackConfig = require('./webpack.dev.conf')
// default port where dev server listens for incoming traffic
var port = process.env.PORT || config.dev.port
// Define HTTP proxies to your custom API backend
// https://github.com/chimurai/http-proxy-middleware
var proxyTable = config.dev.proxyTable
var app = express()
var compiler = webpack(webpackConfig)
var devMiddleware = require('webpack-dev-middleware')(compiler, {
publicPath: webpackConfig.output.publicPath,
stats: {
colors: true,
chunks: false
}
})
var hotMiddleware = require('webpack-hot-middleware')(compiler)
// force page reload when html-webpack-plugin template changes
compiler.plugin('compilation', function (compilation) {
compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) {
hotMiddleware.publish({ action: 'reload' })
cb()
})
})
// proxy api requests
Object.keys(proxyTable).forEach(function (context) {
var options = proxyTable[context]
if (typeof options === 'string') {
options = { target: options }
}
app.use(proxyMiddleware(context, options))
})
// handle fallback for HTML5 history API
app.use(require('connect-history-api-fallback')())
// serve webpack bundle output
app.use(devMiddleware)
// enable hot-reload and state-preserving
// compilation error display
app.use(hotMiddleware)
// serve pure static assets
var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory)
app.use(staticPath, express.static('./static'))
module.exports = app.listen(port, function (err) {
if (err) {
console.log(err)
return
}
var uri = 'http://localhost:' + port
console.log('Listening at ' + uri + '\n')
// when env is testing, don't need open it
if (process.env.NODE_ENV !== 'testing') {
opn(uri)
}
})

View File

@ -1,61 +0,0 @@
var path = require('path')
var config = require('../config')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
exports.assetsPath = function (_path) {
var assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
// generate loader string to be used with extract text plugin
function generateLoaders (loaders) {
var sourceLoader = loaders.map(function (loader) {
var extraParamChar
if (/\?/.test(loader)) {
loader = loader.replace(/\?/, '-loader?')
extraParamChar = '&'
} else {
loader = loader + '-loader'
extraParamChar = '?'
}
return loader + (options.sourceMap ? extraParamChar + 'sourceMap' : '')
}).join('!')
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract('vue-style-loader', sourceLoader)
} else {
return ['vue-style-loader', sourceLoader].join('!')
}
}
// http://vuejs.github.io/vue-loader/en/configurations/extract-css.html
return {
css: generateLoaders(['css']),
postcss: generateLoaders(['css']),
less: generateLoaders(['css', 'less']),
sass: generateLoaders(['css', 'sass?indentedSyntax']),
scss: generateLoaders(['css', 'sass']),
stylus: generateLoaders(['css', 'stylus']),
styl: generateLoaders(['css', 'stylus'])
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
var output = []
var loaders = exports.cssLoaders(options)
for (var extension in loaders) {
var loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
loader: loader
})
}
return output
}

View File

@ -1,77 +1,55 @@
var path = require('path') const path = require('path');
var config = require('../config') const HtmlWebpackPlugin = require('html-webpack-plugin');
var utils = require('./utils') const AutoDllPlugin = require('autodll-webpack-plugin');
var projectRoot = path.resolve(__dirname, '../') const VueLoaderPlugin = require('vue-loader/lib/plugin');
var env = process.env.NODE_ENV
// check env & config/index.js to decide weither to enable CSS Sourcemaps for the
// various preprocessor loaders added to vue-loader at the end of this file
var cssSourceMapDev = (env === 'development' && config.dev.cssSourceMap)
var cssSourceMapProd = (env === 'production' && config.build.productionSourceMap)
var useCssSourceMap = cssSourceMapDev || cssSourceMapProd
module.exports = { module.exports = {
entry: { entry: {
app: './src/main.js' bundle: path.resolve(__dirname, '../src/index.js')
}, },
output: { output: {
path: config.build.assetsRoot, path: path.resolve(__dirname, '../dist'),
publicPath: process.env.NODE_ENV === 'production' ? config.build.assetsPublicPath : config.dev.assetsPublicPath, filename: '[name].[hash].js'
filename: '[name].js'
}, },
resolve: { resolve: {
extensions: ['', '.js', '.vue'], extensions: ['*', '.js', '.json', '.vue'],
fallback: [path.join(__dirname, '../node_modules')],
alias: { alias: {
'vue$': 'vue/dist/vue.common.js', 'vue$': 'vue/dist/vue.esm.js',
'src': path.resolve(__dirname, '../src'), '@': path.resolve(__dirname, '../src'),
'assets': path.resolve(__dirname, '../src/assets'),
'components': path.resolve(__dirname, '../src/components')
} }
}, },
resolveLoader: {
fallback: [path.join(__dirname, '../node_modules')]
},
module: { module: {
loaders: [ rules: [
{ {
test: /\.vue$/, test: /\.vue$/,
loader: 'vue' loader: 'vue-loader'
}, },
{ {
test: /\.js$/, test: /\.js$/,
loader: 'babel', use: 'babel-loader',
include: projectRoot,
exclude: /node_modules/ exclude: /node_modules/
}, },
{ {
test: /\.json$/, test: /\.css$/,
loader: 'json' use: ['vue-style-loader', 'css-loader']
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url',
query: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url',
query: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
} }
] ]
}, },
vue: { plugins: [
loaders: utils.cssLoaders({ sourceMap: useCssSourceMap }), new HtmlWebpackPlugin({
postcss: [ template: path.resolve(__dirname, '../index.html')
require('autoprefixer')({ }),
browsers: ['last 2 versions'] // Dll 优化,需要的时候可以打开
}) // new AutoDllPlugin({
// inject: true, // will inject the DLL bundle to index.html
// debug: true,
// filename: '[name]_[hash].js',
// path: './dll',
// entry: {
// vendor: ['vue', 'vue-router']
// }
// }),
new VueLoaderPlugin(),
// new webpack.optimize.SplitChunksPlugin()
] ]
} };
}

View File

@ -1,34 +1,20 @@
var config = require('../config') const merge = require("webpack-merge");
var webpack = require('webpack') const path = require("path");
var merge = require('webpack-merge') const baseConfig = require("./webpack.base.conf");
var utils = require('./utils')
var baseWebpackConfig = require('./webpack.base.conf')
var HtmlWebpackPlugin = require('html-webpack-plugin')
// add hot-reload related code to entry chunks module.exports = merge(baseConfig, {
Object.keys(baseWebpackConfig.entry).forEach(function (name) { mode: "development",
baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) devtool: "inline-source-map",
})
module.exports = merge(baseWebpackConfig, {
module: { module: {
loaders: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) rules: [ // 自己拓展着玩呀
// {
// test: /\.css$/,
// use: ["vue-style-loader", "css-loader", "postcss-loader"],
// },
],
}, },
// eval-source-map is faster for development devServer: {
devtool: '#eval-source-map', contentBase: path.resolve(__dirname, "../dist"),
plugins: [ open: true,
new webpack.DefinePlugin({ },
'process.env': config.dev.env });
}),
// https://github.com/glenjamin/webpack-hot-middleware#installation--usage
new webpack.optimize.OccurenceOrderPlugin(),
new webpack.HotModuleReplacementPlugin(),
new webpack.NoErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
})
]
})

View File

@ -1,98 +1,27 @@
var path = require('path') const merge = require("webpack-merge");
var config = require('../config') const path = require("path");
var utils = require('./utils') const baseConfig = require("./webpack.base.conf");
var webpack = require('webpack') const { CleanWebpackPlugin } = require("clean-webpack-plugin");
var merge = require('webpack-merge')
var baseWebpackConfig = require('./webpack.base.conf')
var ExtractTextPlugin = require('extract-text-webpack-plugin')
var HtmlWebpackPlugin = require('html-webpack-plugin')
var env = config.build.env
var webpackConfig = merge(baseWebpackConfig, { module.exports = merge(baseConfig, {
mode: "production",
devtool: "source-map",
module: { module: {
loaders: utils.styleLoaders({ sourceMap: config.build.productionSourceMap, extract: true }) rules: [ // 自己拓展着玩呀
}, // {
devtool: config.build.productionSourceMap ? '#source-map' : false, // test: /\.css$/,
output: { // use: [
path: config.build.assetsRoot, // 'css-loader',
filename: utils.assetsPath('js/[name].[chunkhash].js'), // 'postcss-loader',
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') // ]
}, // },
vue: { ],
loaders: utils.cssLoaders({
sourceMap: config.build.productionSourceMap,
extract: true
})
}, },
plugins: [ plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html new CleanWebpackPlugin({
new webpack.DefinePlugin({ root: path.resolve(__dirname, "../"),
'process.env': env verbose: true,
dry: false,
}), }),
new webpack.optimize.UglifyJsPlugin({ ],
compress: { });
warnings: false
}
}),
new webpack.optimize.OccurrenceOrderPlugin(),
// extract css into its own file
new ExtractTextPlugin(utils.assetsPath('css/[name].[contenthash].css')),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks: function (module, count) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
chunks: ['vendor']
})
]
})
if (config.build.productionGzip) {
var CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
module.exports = webpackConfig

View File

@ -10,7 +10,6 @@
<meta name="format-detection" content="telephone=no"> <meta name="format-detection" content="telephone=no">
<meta name="format-detection" content="address=no"> <meta name="format-detection" content="address=no">
<title>vue2spa</title> <title>vue2spa</title>
<link rel="stylesheet" href="./static/reset.css">
</head> </head>
<body> <body>
<div id="app"></div> <div id="app"></div>

8622
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,53 +1,44 @@
{ {
"name": "vue2spa", "name": "vue2-spa-tutorial",
"version": "1.0.0", "version": "1.0.0",
"description": "A Vue.js project", "author": "Allan",
"author": "xsf <416175716@qq.com>", "description": "最干净的脚手架",
"private": true, "main": "index.js",
"scripts": { "scripts": {
"start": "node build/dev-server.js", "dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"build": "node build/build.js" "build": "node build/build.js"
}, },
"dependencies": { "dependencies": {
"axios": "^0.15.3", "vue": "^2.6.11",
"vue": "^2.1.0", "vue-router": "^3.2.0"
"vue-router": "^2.1.1"
}, },
"devDependencies": { "devDependencies": {
"autoprefixer": "^6.4.0", "autodll-webpack-plugin": "^0.4.2",
"babel-core": "^6.0.0", "autoprefixer": "^6.7.7",
"babel-loader": "^6.0.0", "babel-core": "^6.26.3",
"babel-plugin-transform-runtime": "^6.0.0", "babel-loader": "^7.1.5",
"babel-preset-es2015": "^6.0.0", "babel-preset-env": "^1.7.0",
"babel-preset-stage-2": "^6.0.0", "clean-webpack-plugin": "^3.0.0",
"babel-register": "^6.0.0", "css-loader": "^3.5.3",
"chalk": "^1.1.3", "file-loader": "^6.0.0",
"connect-history-api-fallback": "^1.1.0", "html-webpack-plugin": "^4.0.0-beta.14",
"css-loader": "^0.25.0", "mini-css-extract-plugin": "^0.9.0",
"eventsource-polyfill": "^0.9.6", "postcss-loader": "^3.0.0",
"express": "^4.13.3", "vue-loader": "^15.9.2",
"extract-text-webpack-plugin": "^1.0.1", "vue-style-loader": "^4.1.2",
"file-loader": "^0.9.0", "vue-template-compiler": "^2.6.11",
"function-bind": "^1.0.2", "webpack": "^4.43.0",
"html-webpack-plugin": "^2.8.1", "webpack-cli": "^3.3.11",
"http-proxy-middleware": "^0.17.2", "webpack-dev-server": "^3.11.0"
"json-loader": "^0.5.4",
"semver": "^5.3.0",
"opn": "^4.0.2",
"ora": "^0.3.0",
"shelljs": "^0.7.4",
"url-loader": "^0.5.7",
"vue-loader": "^10.0.0",
"vue-router": "^2.0.3",
"vue-style-loader": "^1.0.0",
"vue-template-compiler": "^2.1.0",
"webpack": "^1.13.2",
"webpack-dev-middleware": "^1.8.3",
"webpack-hot-middleware": "^2.12.2",
"webpack-merge": "^0.14.1"
}, },
"engines": { "repository": {
"node": ">= 4.0.0", "type": "git",
"npm": ">= 3.0.0" "url": "git+https://github.com/allan2coder/VUE2-SPA-Tutorial.git"
} },
"keywords": [
"webpack4",
"vue2",
"vue3"
],
"license": "ISC"
} }

5
postcss.config.js Normal file
View File

@ -0,0 +1,5 @@
module.exports = {
plugins: [
require('autoprefixer')
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 68 KiB

View File

@ -1,30 +1,26 @@
<!-- 首页内容渲染 -->
<template> <template>
<div> <div>
<!-- 删除试试 顶部 -->
<!-- 可以删掉 顶部 -->
<HeaderCompontent></HeaderCompontent> <HeaderCompontent></HeaderCompontent>
<!-- 渲染出口 --> <!-- 渲染出口 -->
<router-view></router-view> <router-view></router-view>
<!-- 删除试试 底部菜单 -->
<!-- 可以删除 底部菜单 -->
<FootComponent></FootComponent> <FootComponent></FootComponent>
</div> </div>
</template> </template>
<script> <script>
import HeaderCompontent from './components/header.vue' import HeaderCompontent from './components/header.vue'
import FootComponent from './components/footer.vue' import FootComponent from './components/footer.vue'
export default{ export default{
data(){
return{
msg:'Hello vue',
}
},
components:{ components:{
HeaderCompontent, HeaderCompontent,
FootComponent FootComponent
} }
} }
</script> </script>
<style>
body, ul, h4{
margin: 0;
text-align: center;
}
</style>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.7 KiB

View File

@ -3,9 +3,6 @@
<div class="col4"> <div class="col4">
<router-link to="/index">index</router-link> <router-link to="/index">index</router-link>
</div> </div>
<div class="col4">
<router-link to="/news">news</router-link>
</div>
<div class="col4"> <div class="col4">
<router-link to="/second">menu3</router-link> <router-link to="/second">menu3</router-link>
</div> </div>
@ -31,11 +28,9 @@
bottom: 0; bottom: 0;
z-index: 99; z-index: 99;
border-top: 1px solid #ccc; border-top: 1px solid #ccc;
} display: grid;
.fixed-bottom div {
display: inline-block;
float: left;
text-align: center; text-align: center;
grid-template-columns: 33% 33% 33%;
} }
.fixed-bottom a { .fixed-bottom a {
width: 100%; width: 100%;

View File

@ -1,17 +1,8 @@
<template> <template>
<div class="header"> <div class="header">
<img src="../assets/logo.png"> <img src="https://png2.cleanpng.com/sh/9f5efd7936dbbc0513a929a7809ebd10/L0KzQYm3V8E5N5pnR91yc4Pzfri0lwVmNZt4RdxqdnH2c8PwkQQudJpnitN7eT3kfrj8jPFzcqQyitdqY4SwhsbsTfp0NWZnTNdrZUHmQIq4Wck0NmkATaI7OEK8QYa6Ucg5P2I4SqI8N0OxgLBu/kisspng-vue-js-javascript-library-angularjs-react-vue-js-5b4ebe1c091993.8950282915318871320373.png" />
</div> </div>
</template> </template>
<script>
export default{
data(){
return{
msg: 'Hello vue'
}
}
}
</script>
<style> <style>
.header{ .header{
width: 100%; width: 100%;
@ -19,7 +10,7 @@
} }
.header img{ .header img{
width: 50%; width: 50%;
margin: 30px auto 0; margin: 30px auto 30px;
display: block; display: block;
} }
</style> </style>

View File

@ -1,5 +1,5 @@
<template> <template>
<div class="hello"> <div class="second-wrap">
<h4>这是子组件</h4> <h4>这是子组件</h4>
<p>这是<span>来自父组件</span>的数据{{myMessage}}</p> <p>这是<span>来自父组件</span>的数据{{myMessage}}</p>
</div> </div>
@ -10,20 +10,17 @@ export default {
name: 'child', name: 'child',
props: [ props: [
'myMessage', 'myMessage',
], ]
// mounted(){
// console.log(":",this.myMessage);
// }
} }
</script> </script>
<style scoped> <style scoped>
.hello{ .second-wrap{
margin-top: 30px; margin-top: 30px;
text-align: center;
} }
h4,p{ h4,p{
color: #41b883;; color: #41b883;;
text-align: left;
font-size: 20px; font-size: 20px;
} }
p{ p{

View File

@ -7,11 +7,9 @@
<script> <script>
export default { export default {
name: 'button-counter', name: 'button-counter',
data () { data: () => ({
return { counter: 0,
counter: 0 }),
}
},
methods: { methods: {
increment: function () { increment: function () {
this.counter += 1 this.counter += 1

9
src/index.js Normal file
View File

@ -0,0 +1,9 @@
// 项目启动
import Vue from "vue";
import App from "./App";
import router from "./router";
new Vue({
router: router, // 注册路由
render: (h) => h(App),
}).$mount("#app"); // 渲染挂载

View File

@ -1,10 +0,0 @@
/* 项目启动 */
import Vue from 'vue'
import App from './App'
import router from './router'
new Vue({
router: router,
render: h => h(App)
// components: { firstcomponent, secondcomponent }
}).$mount('#app')

17
src/mock/index.js Normal file
View File

@ -0,0 +1,17 @@
// mock data
export const data = {
success: true,
data: [{
name: "React",
id: 1,
},{
name: "Vue",
id: 2,
},{
name: "Angular",
id: 3,
},{
name: "Flutter",
id: 4,
}]
};

View File

@ -1,67 +1,38 @@
<template> <template>
<div> <div>
<button v-on:click="loadMore">click me</button> <button v-on:click="loadMore">click me</button>
<div>
<ul> <ul>
<li v-for="(item, index) in listArr"> <li v-for="(item, index) in listArr" :key="index">
<a href="https://github.com/allan2coder/VUE2-SPA-Tutorial">{{index}} {{item.name}}</a> <a href="">{{ index }} {{ item.name }}</a>
</li> </li>
</ul> </ul>
</div> </div>
<div class="loading" v-if="loading">
Loading...
</div>
</div>
</template> </template>
<script> <script>
// ajax 使 axios let mock = require('../mock'); //
import axios from 'axios'
export default { export default {
data () { data: () => ({
return{
loading: false,
listArr: [], listArr: [],
} page: 1,
}, }),
created() { created() {
this.loadList(); this.loadList();
}, },
methods: { methods: {
loadList: function() { loadList(page) {
console.log("初始化加载数据开始..."); const {data, success} = mock.data;
var _this = this; if (this.page > 1) {
_this.loading = true; console.log("page is:", this.page);
axios.get('https://api.github.com/search/code?q=addClass+in:file+language:js+repo:jquery/jquery', { return this.listArr = this.listArr.concat(data);
params: {
} }
}) this.listArr = data;
.then(function (response) {
_this.loading = false;
_this.listArr = response.data.items;
console.log(_this.listArr,"加载完成");
})
.catch(function (error) {
console.log(error);
});
}, },
loadMore: function(){ loadMore() {
console.log("load more") this.loadList(this.page++);
var _this = this; },
_this.loading = true; },
axios.get('https://api.github.com/search/code?q=addClass+in:file+language:js+repo:jquery/jquery', { };
params: {
}
})
.then(function (response) {
_this.loading = false;
_this.listArr = _this.listArr.concat(response.data.items);
})
}
}
}
</script> </script>
<style> <style>
@ -75,14 +46,18 @@
a { a {
color: #35495e; color: #35495e;
font-size: 16px; font-size: 16px;
text-decoration: none;
} }
ul { ul {
margin-bottom: 60px; margin-bottom: 60px;
padding: 20px;
} }
li { li {
line-height: 32px; line-height: 32px;
border-bottom: 1px solid #ddd; border-bottom: 1px solid #ddd;
padding: 0 10px; padding: 0 10px;
text-align: left;
list-style: none;
} }
b { b {
font-size: 12px; font-size: 12px;

View File

@ -1,11 +0,0 @@
<template>
<h4 class="news-tit">啥玩意儿</h4>
</template>
<style>
.news-tit{
font-size: 18px;
margin-top: 60px;
text-align: center;
}
</style>

View File

@ -4,25 +4,23 @@
<!-- 父组件内容 --> <!-- 父组件内容 -->
<h4>这是父组件</h4> <h4>这是父组件</h4>
<p>这是父组件正在渲染的数据{{parentMsg}}</p> <p>这是父组件正在渲染的数据{{parentMsg}}</p>
<input type="" v-model="parentMsg" autofocus="autofocus" placeholder="type something"> <input type="" v-model="parentMsg" autofocus="autofocus" placeholder="type something" />
<!-- 子组件内容 --> <!-- 子组件内容 -->
<tochild :my-message="parentMsg"></tochild> <child :my-message="parentMsg"></child>
</div> </div>
</template> </template>
<script> <script>
import tochild from '../components/secondcomponent.vue' import Child from '../components/secondcomponent.vue'
export default { export default {
data () { data: () => ({
return { parentMsg: '',
parentMsg: '' }),
}
},
components: { // components: { //
tochild Child
} }
} }
</script> </script>
@ -30,7 +28,6 @@
<style scoped> <style scoped>
h4,p{ h4,p{
color: #35495e; color: #35495e;
text-align: left;
font-size: 20px; font-size: 20px;
} }
p{ p{

View File

@ -4,7 +4,8 @@
<!-- 这是父组件内容 --> <!-- 这是父组件内容 -->
<h4>子组件数据传递给父组件</h4> <h4>子组件数据传递给父组件</h4>
<p>方式用自定义事件</p> <p>方式用自定义事件</p>
<p class="text-center parent-tit">这是父组件</p> <p class="parent-title">这是父组件</p>
<!-- 父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件 --> <!-- 父组件可以在使用子组件的地方直接用 v-on 来监听子组件触发的事件 -->
<h2 class="text-center">{{ total }}</h2> <h2 class="text-center">{{ total }}</h2>
@ -23,12 +24,10 @@
import buttonCounter from '../components/thirdcomponent.vue' import buttonCounter from '../components/thirdcomponent.vue'
export default { export default {
data () { data: () => ({
return {
parentMsg: '子组件传递信息给父元素', parentMsg: '子组件传递信息给父元素',
total: 0 total: 0,
} }),
},
methods: { methods: {
incrementTotal: function () { incrementTotal: function () {
this.total += 1 this.total += 1
@ -41,7 +40,7 @@
</script> </script>
<style scoped> <style scoped>
.parent-tit{ .parent-title{
margin-top: 30px; margin-top: 30px;
} }
h4{ h4{

View File

@ -1,4 +1,3 @@
/* 路由配置全写这里 */
import Vue from 'vue' import Vue from 'vue'
import VueRouter from 'vue-router' import VueRouter from 'vue-router'
@ -6,30 +5,25 @@ import VueRouter from 'vue-router'
Vue.config.debug = true Vue.config.debug = true
Vue.use(VueRouter); Vue.use(VueRouter);
import Index from '../pages/index.vue' import Index from '../pages/index'
import News from '../pages/news.vue' import SecondComponent from '../pages/otherPages'
import secondcomponent from '../pages/otherPages.vue' import ThirdComponent from '../pages/otherPages2'
import thirdcomponent from '../pages/otherPages2.vue'
export default new VueRouter({ export default new VueRouter({
mode: 'history', mode: 'hash', // 还有 history 等
base: __dirname, base: __dirname,
routes: [ routes: [
{ {
path: '/index', path: '/index',
component: Index component: Index,
},
{
path: '/news',
component: News
}, },
{ {
path: '/second', path: '/second',
component: secondcomponent component: SecondComponent,
}, },
{ {
path: '/third', path: '/third',
component: thirdcomponent component: ThirdComponent,
} }
] ]
}) })

View File

View File

@ -1,70 +0,0 @@
@charset "utf-8";
/*清零*/
body,div,dl,dt,dd,ul,ol,li,h1,h2,h3,h4,h5,h6,pre,form,fieldset,input,textarea,p,blockquote,th,td { margin:0; padding:0;}
fieldset,img { border:0;}
ol,ul { list-style:none; }
h1,h2,h3,h4,h5,h6,button,input,select,textarea { font-size:100%;
font-weight: normal; }
button::-moz-focus-inner,input::-moz-focus-inner{ padding:0; border:0; }
table{ border-collapse: collapse; border-spacing: 0; }
i, cite, em, var, dfn, address { font-style: normal; }
body{ font:14px "方正兰亭细黑简体","微软雅黑","宋体",Arial;}
a{ text-decoration:none; outline: none;}
a:hover{ text-decoration: none; }
a:active, a:focus{ outline:none; }
b{ font-weight: normal; }
input:not([type="radio"]){appearance:none;-webkit-appearance:none;-o-appearance:none;-moz-appearance:none;}
button:active{
transform:scale(0.9);
-webkit-transform: scale(0.9);
-moz-transform: scale(0.9);
-ms-transform: scale(0.9);
-o-transform: scale(0.9);
}
textarea{
appearance: none;
-webkit-appearance: none;
-moz-appearance: none;
-o-appearance: none;
resize: none;
}
input{
border-radius: 0;
}
*{
box-sizing: border-box;
}
a{
color: #232323;
}
button{
background: none;
}
.text-center{
text-align: center;
}
.container{
padding: 0 10px;
}
[v-cloak] {
display: none;
}
/* common css */
.col2{
width: 50%;
}
.col3{
width: 33.33%;
}
.col4{
width: 25%;
}
.col6{
width: 16.66%;
}