├── src ├── style │ └── common │ │ ├── less │ │ ├── base.less │ │ ├── README.md │ │ ├── _utils.less │ │ └── _mixin.less │ │ └── scss │ │ ├── base.scss │ │ ├── _utils.scss │ │ └── _mixin.scss ├── assets │ └── favicon │ │ └── favicon.ico ├── index.ts ├── test.ts ├── style.less └── exp.ts ├── .gitignore ├── .gitattributes ├── tsconfig.json ├── .babelrc ├── webpack.dev.js ├── README.md ├── index.html ├── webpack.config.js ├── package.json ├── webpack.prod.js └── webpack.common.js /src/style/common/less/base.less: -------------------------------------------------------------------------------- 1 | @import "./_utils.less"; -------------------------------------------------------------------------------- /src/style/common/less/README.md: -------------------------------------------------------------------------------- 1 | 这里是less的通用样式,mixin,和一些方法,同scss 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules/ 3 | dist/ 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* -------------------------------------------------------------------------------- /src/assets/favicon/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/IFmiss/webpack-tpl/master/src/assets/favicon/favicon.ico -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | *.js linguist-language=javascript 2 | *.css linguist-language=javascript 3 | *.html linguist-language=javascript -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import '@/style.less'; 2 | import Dutils from 'd-utils'; 3 | Dutils.LogUtils.logInfo('WEBPACK-TPL', 'HELLO') 4 | -------------------------------------------------------------------------------- /src/style/common/scss/base.scss: -------------------------------------------------------------------------------- 1 | @import "node_modules/compass-mixins/lib/compass/css3"; 2 | @import './_utils'; 3 | @import './_mixin'; -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "sourceMap": true, 5 | "noImplicitAny": true, 6 | "module": "commonjs", 7 | "target": "es5", 8 | "jsx": "react", 9 | "allowJs": true 10 | } 11 | } -------------------------------------------------------------------------------- /src/test.ts: -------------------------------------------------------------------------------- 1 | class Shape { 2 | area: number; 3 | color: string; 4 | constructor ( name: string, width: number, height: number ) { 5 | this.area = width * height; 6 | this.color = "pink"; 7 | }; 8 | 9 | shoutout() { 10 | return "I'm " + this.color + " with an area of " + this.area + " cm squared."; 11 | } 12 | } 13 | 14 | var square = new Shape("square", 30, 30); 15 | console.log( square.shoutout() ); 16 | console.log( 'Area of Shape: ' + square.area ); 17 | console.log( 'Color of Shape: ' + square.color ); 18 | -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | ["@babel/preset-env", { 4 | "modules": "false", 5 | }], 6 | ], 7 | "plugins":[ 8 | ["@babel/plugin-proposal-decorators", { "legacy": true }], 9 | ["@babel/plugin-proposal-class-properties", { "loose" : true }], 10 | [ 11 | "@babel/plugin-transform-runtime", 12 | { 13 | "absoluteRuntime": false, 14 | "corejs": false, 15 | "helpers": true, 16 | "regenerator": true, 17 | "useESModules": false 18 | } 19 | ] 20 | ] 21 | } 22 | -------------------------------------------------------------------------------- /webpack.dev.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | const common = require('./webpack.common.js'); 3 | const webpackPromptPlugin = require('@dw/webpack-prompt-plugin') 4 | 5 | module.exports = merge(common, { 6 | devtool: 'inline-source-map', 7 | plugins: [ 8 | new webpackPromptPlugin() 9 | ], 10 | devServer: { 11 | // 当使用 HTML5 History API 时,任意的 404 响应都可能需要被替代为 index.html。通过传入以下启用: 12 | contentBase: "./", 13 | host: '0.0.0.0', 14 | // 端口号 15 | port: 2006, 16 | //当有编译器错误或警告时,在浏览器中显示全屏覆盖。默认禁用。如果您只想显示编译器错误: 17 | noInfo: true, 18 | // 配置端口号 19 | overlay: true, 20 | } 21 | }); -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # webpack-tpl 2 | 3 | ![](https://img.shields.io/badge/webpack-4.29.0-00a1fb.svg) ![](https://img.shields.io/badge/webpack_cli-3.2.1-fbc2eb.svg) 4 | ![](https://img.shields.io/badge/typescript-3.2.4-fda085.svg) ![](https://img.shields.io/badge/stylus-0.54.5-8fd3f4.svg) ![](https://img.shields.io/badge/less-3.9.0-4facfe.svg) ![](https://img.shields.io/badge/d-js-utils-1.0.8-8fd3f4.svg) 5 | 6 | 一个通用的webpack模板,配置基本的内容,可满足项目的基本的使用 7 | - less, sass, stylus支持 8 | - d-utils-js通用js的支持 9 | - webpack版本4.0+, 支持热更新 10 | - 支持typescript 11 | 12 | ![](https://github.com/IFmiss/webpack-tpl/blob/master/static/demo.png) 13 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | webpack 6 | 7 | 8 |
9 |

Webpack 通用模板

10 | 基于wenpack 4.0 11 | 配置d-js-utils通用方法 12 | 支持 less(sass, stylus需自行安装依赖) 13 | 支持 typescript 14 |
15 |
16 | 17 | 未曾遗忘的青春 18 |
19 |
20 | 21 | -------------------------------------------------------------------------------- /src/style.less: -------------------------------------------------------------------------------- 1 | @import "./style/common/less/base.less"; 2 | body,html{ 3 | margin: 0; 4 | padding: 0; 5 | height:100%; 6 | background: #111010; 7 | } 8 | body{ 9 | // background: red; 10 | display: flex; 11 | width: 100%; 12 | height: 100%; 13 | align-items: center; 14 | justify-content: center; 15 | flex-direction: column; 16 | .title{ 17 | font-size: 42px; 18 | .colortext-l(#4facfe, #00f2fe); 19 | display: inline-block; 20 | margin-top: 0; 21 | } 22 | .disc{ 23 | font-size: 14px; 24 | padding: 6px 0; 25 | color: #f1f1f1; 26 | } 27 | .github-info{ 28 | margin-top: 40px; 29 | text-align: center; 30 | display: flex; 31 | justify-content: center; 32 | span{ 33 | color: #fff; 34 | font: 14px; 35 | font-size:14px; 36 | } 37 | } 38 | } -------------------------------------------------------------------------------- /src/style/common/less/_utils.less: -------------------------------------------------------------------------------- 1 | @import "./_mixin.less"; 2 | // 浮动 3 | .right{ 4 | float: right; 5 | } 6 | 7 | .left{ 8 | float: left; 9 | } 10 | 11 | .center{ 12 | margin: 0 auto; 13 | float: none; 14 | } 15 | 16 | // 清除浮动 17 | .clear-both{ 18 | clear: both; 19 | height:1px; 20 | margin-top:-1px; 21 | overflow:hidden; 22 | &:before{ 23 | display:none; 24 | } 25 | &:after{ 26 | display:none; 27 | } 28 | } 29 | 30 | .block_area{ 31 | margin: 0 auto; 32 | position: relative; 33 | font-size: 14px; 34 | } 35 | 36 | // inline-block对齐 或者文本对齐 37 | .text-left{ 38 | text-align:left; 39 | } 40 | 41 | .text-right{ 42 | text-align:right; 43 | } 44 | 45 | .text-center{ 46 | text-align:center; 47 | } 48 | 49 | .text-bold{ 50 | font-weight:bold; 51 | } 52 | 53 | .activeB{ 54 | display: block; 55 | } 56 | 57 | .activeF{ 58 | display: flex; 59 | } 60 | 61 | .activeN{ 62 | display:none; 63 | } 64 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | const dev = require('./webpack.dev') 2 | const prod = require('./webpack.prod') 3 | const chalk = require('chalk'); 4 | var os = require('os'); 5 | 6 | switch (process.env.NODE_ENV) { 7 | case 'development': 8 | module.exports = dev 9 | break 10 | case 'production': 11 | module.exports = prod 12 | break 13 | } 14 | 15 | // 获取Ip 16 | function getIPAdress() { 17 | let localIPAddress = ""; 18 | let interfaces = os.networkInterfaces(); 19 | for (let devName in interfaces) { 20 | let iface = interfaces[devName]; 21 | for (let i = 0; i < iface.length; i++) { 22 | let alias = iface[i]; 23 | if (alias.family === 'IPv4' && alias.address !== '127.0.0.1' && !alias.internal) { 24 | localIPAddress = alias.address; 25 | } 26 | } 27 | } 28 | localIp = localIPAddress; 29 | return localIPAddress; 30 | } 31 | 32 | // 打印返回信息 33 | // if (process.env.NODE_ENV === 'development') { 34 | // let host = dev.devServer.host ? dev.devServer.host : 'localhost' 35 | // // getIPAdress 36 | // if (host === '0.0.0.0') host = getIPAdress() 37 | // const text = `server will start at: http://${host}:${dev.devServer.port}` 38 | // console.log(chalk.green(text)) 39 | // } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webpack-tpl", 3 | "version": "1.0.0", 4 | "description": "webpack-tpl", 5 | "main": "webpack.config.js", 6 | "dependencies": { 7 | "@dw/webpack-prompt-plugin": "^1.0.8", 8 | "autodll-webpack-plugin": "^0.4.2", 9 | "cache-loader": "^4.1.0", 10 | "d-utils": "^3.0.0", 11 | "extract-text-webpack-plugin": "^4.0.0-beta.0", 12 | "happypack": "^5.0.1", 13 | "sha1": "^1.1.1" 14 | }, 15 | "scripts": { 16 | "test": "echo \"Error: no test specified\" && exit 1", 17 | "build": "cross-env NODE_ENV=production webpack --progress --profile --mode production", 18 | "dev": "cross-env NODE_ENV=development webpack-dev-server --mode development --progress --colors", 19 | "watch": "webpack --colors --watch" 20 | }, 21 | "keywords": [ 22 | "webpack", 23 | "webpack template", 24 | "template", 25 | "config" 26 | ], 27 | "author": "daiwei", 28 | "license": "ISC", 29 | "devDependencies": { 30 | "@babel/core": "^7.4.3", 31 | "@babel/plugin-proposal-class-properties": "^7.4.0", 32 | "@babel/plugin-proposal-decorators": "^7.4.0", 33 | "@babel/plugin-transform-runtime": "^7.4.3", 34 | "@babel/preset-env": "^7.4.3", 35 | "@babel/runtime": "^7.4.3", 36 | "@types/node": "^11.13.2", 37 | "atob": ">=2.1.0", 38 | "babel-loader": "^8.0.5", 39 | "babel-polyfill": "^6.26.0", 40 | "clean-webpack-plugin": "^1.0.0", 41 | "compass-mixins": "^0.12.10", 42 | "cross-env": "^5.2.0", 43 | "css-loader": "^0.28.10", 44 | "deep-extend": ">=0.5.1", 45 | "html-webpack-plugin": "^3.0.6", 46 | "less": "^3.9.0", 47 | "less-loader": "^4.1.0", 48 | "mini-css-extract-plugin": "^0.5.0", 49 | "optimize-css-assets-webpack-plugin": "^5.0.1", 50 | "postcss-loader": "^3.0.0", 51 | "randomatic": ">=3.0.0", 52 | "style-loader": "^0.20.3", 53 | "ts-loader": "^6.2.1", 54 | "typescript": "^3.2.4", 55 | "uglifyjs-webpack-plugin": "^2.1.1", 56 | "url-loader": "^1.0.1", 57 | "url-parse": ">=1.4.3", 58 | "webpack": "^4.29.0", 59 | "webpack-cli": "^3.2.1", 60 | "webpack-dev-server": ">=3.1.11", 61 | "webpack-merge": "^4.2.1" 62 | } 63 | } 64 | -------------------------------------------------------------------------------- /webpack.prod.js: -------------------------------------------------------------------------------- 1 | const merge = require('webpack-merge'); 2 | const path = require('path'); 3 | const common = require('./webpack.common.js'); 4 | const HappyPack = require('happypack') 5 | const AutoDllPlugin = require('autodll-webpack-plugin') 6 | // css压缩打包相关 7 | var OptimizeCssAssetsPlugin = require('optimize-css-assets-webpack-plugin'); 8 | 9 | // 打包清除dist目录 10 | const CleanWebpackPlugin = require('clean-webpack-plugin'); 11 | 12 | const resolve = function (dir) { 13 | return path.resolve(__dirname, dir); 14 | } 15 | module.exports = merge(common, { 16 | entry: { 17 | app: './src/index.ts' 18 | }, 19 | output: { 20 | path: resolve('dist'), 21 | publicPath: '', 22 | filename: '[name]-[hash].js' 23 | }, 24 | module: { 25 | rules: [ 26 | { 27 | test: /\.js$/, 28 | use: [ 29 | 'happypack/loader?id=js' 30 | ] 31 | }, 32 | { 33 | test: /\.ts$/, 34 | use: [ 35 | 'happypack/loader?id=js', 36 | 'happypack/loader?id=ts' 37 | ] 38 | }, 39 | ], 40 | }, 41 | plugins: [ 42 | // 清除 43 | new CleanWebpackPlugin(['dist'], { 44 | verbose: false 45 | }), 46 | 47 | // css 压缩 48 | new OptimizeCssAssetsPlugin({ 49 | assetNameRegExp: /\.optimize\.css$/g, 50 | cssProcessor: require('cssnano'), 51 | cssProcessorPluginOptions: { 52 | preset: ['default', { discardComments: { removeAll: true } }], 53 | }, 54 | canPrint: true 55 | }), 56 | 57 | // happyPack 58 | new HappyPack({ 59 | id: 'js', 60 | loaders: [ 61 | 'cache-loader', 62 | { 63 | loader: 'babel-loader', 64 | options: { 65 | presets: ["@babel/preset-env"], 66 | cacheDirectory: true, 67 | }, 68 | exclude: /node_modules/, 69 | } 70 | ], 71 | verbose: true, 72 | }), 73 | 74 | new HappyPack({ 75 | id: 'ts', 76 | loaders: [ 77 | 'cache-loader', 78 | "ts-loader?" + JSON.stringify({happyPackMode: true}) 79 | ], 80 | verbose: true, 81 | }), 82 | 83 | new AutoDllPlugin({ 84 | inject: true, 85 | filename: '[name][hash:8].js', 86 | entry: { 87 | vendor: [ 88 | 'd-utils' 89 | ] 90 | } 91 | }) 92 | ] 93 | }); -------------------------------------------------------------------------------- /src/style/common/scss/_utils.scss: -------------------------------------------------------------------------------- 1 | // 浮动 2 | .right{ 3 | float: right; 4 | } 5 | 6 | .left{ 7 | float: left; 8 | } 9 | 10 | .center{ 11 | margin: 0 auto; 12 | float: none; 13 | } 14 | 15 | // 清除浮动 16 | .clear-both{ 17 | clear: both; 18 | height:1px; 19 | margin-top:-1px; 20 | overflow:hidden; 21 | &:before{ 22 | display:none; 23 | } 24 | &:after{ 25 | display:none; 26 | } 27 | } 28 | 29 | .border-box{ 30 | @include box-sizing(border-box); 31 | } 32 | 33 | .content-wrap{ 34 | @include box-sizing(content-wrap); 35 | } 36 | 37 | .block_area{ 38 | margin: 0 auto; 39 | position: relative; 40 | font-size: 14px; 41 | } 42 | 43 | // inline-block对齐 或者文本对齐 44 | .text-left{ 45 | text-align:left; 46 | } 47 | 48 | .text-right{ 49 | text-align:right; 50 | } 51 | 52 | .text-center{ 53 | text-align:center; 54 | } 55 | 56 | .text-bold{ 57 | font-weight:bold; 58 | } 59 | 60 | .activeB{ 61 | display: block; 62 | } 63 | 64 | .activeF{ 65 | display: flex; 66 | } 67 | 68 | .activeN{ 69 | display:none; 70 | } 71 | 72 | 73 | @for $i from 0 through 30 { 74 | .padding-top-#{$i}{ 75 | padding-top: $i * 1px; 76 | } 77 | .padding-left-#{$i}{ 78 | padding-left: $i * 1px; 79 | } 80 | .padding-right-#{$i}{ 81 | padding-right: $i * 1px; 82 | } 83 | .padding-bottom-#{$i}{ 84 | padding-bottom: $i * 1px; 85 | } 86 | .padding-#{$i}{ 87 | padding: $i * 1px; 88 | } 89 | 90 | //-------------------- 91 | 92 | .margin-top-#{$i}{ 93 | margin-top: $i * 1px; 94 | } 95 | .margin-left-#{$i}{ 96 | margin-left: $i * 1px; 97 | } 98 | .margin-right-#{$i}{ 99 | margin-right: $i * 1px; 100 | } 101 | .margin-bottom-#{$i}{ 102 | margin-bottom: $i * 1px; 103 | } 104 | .margin-#{$i}{ 105 | padding: $i * 1px; 106 | } 107 | 108 | 109 | // ------------------- 110 | 111 | .text-indent-#{$i}{ 112 | text-indent: $i * 1px; 113 | } 114 | 115 | .border-r-#{$i}{ 116 | @include border-radius($i * 1px) 117 | } 118 | 119 | .m-padding-top-#{$i}{ 120 | padding-top: px75rem($i); 121 | } 122 | .m-padding-left-#{$i}{ 123 | padding-left: px75rem($i); 124 | } 125 | .m-padding-right-#{$i}{ 126 | padding-right: px75rem($i); 127 | } 128 | .m-padding-bottom-#{$i}{ 129 | padding-bottom: px75rem($i); 130 | } 131 | .m-padding-#{$i}{ 132 | padding: px75rem($i); 133 | } 134 | 135 | //-------------------- 136 | 137 | .m-margin-top-#{$i}{ 138 | margin-top: px75rem($i); 139 | } 140 | .m-margin-left-#{$i}{ 141 | margin-left: px75rem($i); 142 | } 143 | .m-margin-right-#{$i}{ 144 | margin-right: px75rem($i); 145 | } 146 | .m-margin-bottom-#{$i}{ 147 | margin-bottom: px75rem($i); 148 | } 149 | .m-margin-#{$i}{ 150 | padding: px75rem($i); 151 | } 152 | 153 | 154 | // ------------------- 155 | 156 | .m-text-indent-#{$i}{ 157 | text-indent: px75rem($i); 158 | } 159 | 160 | .m-border-r-#{$i}{ 161 | @include border-radius(px75rem($i)) 162 | } 163 | } 164 | 165 | @for $i from 10 through 50 { 166 | @if ($i % 2 == 0) { 167 | .m-size-#{$i}{ 168 | font-size: px75rem($i); 169 | } 170 | } 171 | } 172 | -------------------------------------------------------------------------------- /webpack.common.js: -------------------------------------------------------------------------------- 1 | const path = require('path'); 2 | const UglifyJsPlugin = require('uglifyjs-webpack-plugin'); 3 | // MiniCssExtractPlugin 4 | const MiniCssExtractPlugin = require("mini-css-extract-plugin"); 5 | 6 | // HtmlWebpackPlugin 7 | const HtmlWebpackPlugin = require('html-webpack-plugin'); 8 | 9 | const resolve = function (dir) { 10 | return path.resolve(__dirname, dir); 11 | } 12 | 13 | const devMode = process.env.NODE_ENV === "development" 14 | 15 | module.exports = { 16 | plugins: [ 17 | new HtmlWebpackPlugin ({ 18 | filename: 'index.html', 19 | template: 'index.html', 20 | inject: true, 21 | favicon: 'src/assets/favicon/favicon.ico' 22 | }), 23 | 24 | new MiniCssExtractPlugin ({ 25 | filename: "css/[name]-[hash].css", 26 | chunkFilename: "css/[id].css" 27 | }) 28 | ], 29 | module: { 30 | unknownContextCritical : false, 31 | rules: [ 32 | { 33 | test: /\.(c)ss$/, 34 | use: [ 35 | 'cache-loader', 36 | devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 37 | "css-loader", 38 | { 39 | loader:"postcss-loader", 40 | options: { 41 | plugins: (loader) => [ 42 | require('autoprefixer')() 43 | ] 44 | } 45 | }, 46 | "less-loader" 47 | ] 48 | }, 49 | { 50 | test: /\.less$/, 51 | use: [ 52 | 'cache-loader', 53 | devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 54 | "css-loader", 55 | { 56 | loader:"postcss-loader", 57 | options: { 58 | plugins: (loader) => [ 59 | require('autoprefixer')() 60 | ] 61 | } 62 | }, 63 | "less-loader" 64 | ], 65 | }, 66 | { 67 | test: /\.styl$/, 68 | use: [ 69 | 'cache-loader', 70 | devMode ? 'style-loader' : MiniCssExtractPlugin.loader, 71 | "css-loader", 72 | { 73 | loader:"postcss-loader", 74 | options: { 75 | plugins: (loader) => [ 76 | require('autoprefixer')() 77 | ] 78 | } 79 | }, 80 | "stylus-loader" 81 | ] 82 | }, 83 | { 84 | test: /\.(ttf|eot|svg|woff|woff2)$/, 85 | use: [ 86 | 'cache-loader', 87 | { 88 | loader: 'url-loader' 89 | } 90 | ] 91 | }, 92 | { 93 | test: /\.ts$/, 94 | use: [ 95 | 'cache-loader', 96 | {loader: 'babel-loader',}, 97 | { 98 | loader: 'ts-loader', 99 | options: { 100 | // 加快编译速度 101 | transpileOnly: true, 102 | // 指定特定的ts编译配置,为了区分脚本的ts配置 103 | configFile: path.resolve(__dirname, './tsconfig.json') 104 | } 105 | } 106 | ] 107 | }, 108 | { 109 | test: /\.(png|jpg|gif)$/, 110 | use: [ 111 | 'cache-loader', 112 | { 113 | loader: 'url-loader', 114 | options: { 115 | limit: 8192 116 | } 117 | } 118 | ] 119 | }, 120 | ] 121 | }, 122 | resolve: { 123 | alias: { 124 | '@': resolve('src'), 125 | assets: resolve('src/assets'), 126 | style: resolve('src/style') 127 | }, 128 | extensions: ['.ts', '.tsx', '.js'], 129 | modules: ['src' ,'node_modules'] 130 | }, 131 | optimization: { 132 | splitChunks: { 133 | chunks: "all", 134 | minSize: 30000, 135 | minChunks: 3, 136 | maxAsyncRequests: 5, 137 | maxInitialRequests: 3, 138 | name: true, 139 | cacheGroups: { 140 | default: { 141 | minChunks: 2, 142 | priority: -20, 143 | reuseExistingChunk: true, 144 | }, 145 | vendors: { 146 | test: /[\\/]node_modules[\\/]/, 147 | priority: -10 148 | } 149 | } 150 | }, 151 | minimizer: [ 152 | new UglifyJsPlugin({ 153 | test: /\.js(\?.*)?$/i, 154 | parallel: true 155 | }), 156 | ] 157 | } 158 | }; -------------------------------------------------------------------------------- /src/style/common/less/_mixin.less: -------------------------------------------------------------------------------- 1 | .lineclamp (@height, @count) { 2 | height: @height; 3 | line-height: @height / @count; 4 | overflow:hidden; 5 | text-overflow:ellipsis; 6 | display:-webkit-box; 7 | -webkit-box-orient:vertical; 8 | -webkit-line-clamp: @count; 9 | word-wrap: break-word; 10 | } 11 | 12 | .textoneline(@height) when (@height = auto) { 13 | height: @height; 14 | line-height: initial; 15 | text-overflow: ellipsis; 16 | white-space: nowrap; 17 | overflow: hidden; 18 | } 19 | 20 | .textoneline(@height) when (@height = height) { 21 | height: @height; 22 | line-height: @height; 23 | text-overflow: ellipsis; 24 | white-space: nowrap; 25 | overflow: hidden; 26 | } 27 | 28 | // top left = > right bottom 29 | .colortext-lt (@color1, @color2) { 30 | position: relative; 31 | background: -webkit-linear-gradient(left top, @color1 , @color2); /* Safari 5.1 - 6.0 */ 32 | background: -o-linear-gradient(bottom right, @color1, @color2); /* Opera 11.1 - 12.0 */ 33 | background: -moz-linear-gradient(bottom right, @color1, @color2); /* Firefox 3.6 - 15 */ 34 | background: linear-gradient(to bottom right, @color1 , @color2); /* 标准的语法 */ 35 | -webkit-background-clip: text; 36 | -webkit-text-fill-color: transparent; 37 | } 38 | 39 | // left = > right 40 | .colortext-l (@color1, @color2) { 41 | position: relative; 42 | background: -webkit-linear-gradient(left, @color1 , @color2); /* Safari 5.1 - 6.0 */ 43 | background: -o-linear-gradient(right, @color1, @color2); /* Opera 11.1 - 12.0 */ 44 | background: -moz-linear-gradient(right, @color1, @color2); /* Firefox 3.6 - 15 */ 45 | background: linear-gradient(to right, @color1 , @color2); /* 标准的语法 */ 46 | -webkit-background-clip: text; 47 | -webkit-text-fill-color: transparent; 48 | } 49 | 50 | // 添加blur模糊效果 51 | // 如果不是绝对定位,父元素需要设置相对定位 52 | // @blur 为模糊的数值 53 | // @height 区域的高度 54 | // @position 为位置 默认50% 55 | .blur(@blur, @height, @position: 50%, @scale: 1.5) { 56 | position: absolute; 57 | top: 0; 58 | left: 0; 59 | right: 0; 60 | height: @height; 61 | background-repeat: no-repeat; 62 | background-size: cover; 63 | background-position: @position; 64 | -webkit-filter: blur(@blur); 65 | filter: blur(@blur); 66 | -webkit-transform: scale(@scale); 67 | transform: scale(@scale); 68 | overflow: hidden; 69 | &::before{ 70 | content: ''; 71 | position: absolute; 72 | left: 0; 73 | top: 0; 74 | right: 0; 75 | bottom: 0; 76 | z-index: 1; 77 | background: rgba(0,0,0,0.1); 78 | transition: all 0.3s; 79 | } 80 | &.draken{ 81 | &::before{ 82 | background: rgba(0,0,0,0.3); 83 | } 84 | } 85 | } 86 | 87 | .blur(@blur, @height, @position: 50%, @scale: 1.5) when (@height = auto) { 88 | bottom: 0; 89 | height: unset; 90 | } 91 | 92 | // 固定底部 93 | .fixfooterflex () { 94 | html{ 95 | height: 100%; 96 | } 97 | 98 | body{ 99 | display: flex; 100 | flex-direction: column; 101 | min-height: 100%; 102 | font-family: "Hiragino Sans GB","Century Gothic",system, Arial, Verdana, Tahoma,"微软雅黑"; 103 | position: relative; 104 | width: 100%; 105 | overflow-x: hidden; 106 | } 107 | 108 | header{ 109 | /* 我们希望 header 采用固定的高度,只占用必须的空间 */ 110 | /* 0 flex-grow, 0 flex-shrink, auto flex-basis */ 111 | flex: 0 0 auto; 112 | } 113 | 114 | .main_content{ 115 | /* 将 flex-grow 设置为1,该元素会占用所有的可使用空间 116 | 而其他元素该属性值为0,因此不会得到多余的空间*/ 117 | /* 1 flex-grow, 0 flex-shrink, auto flex-basis */ 118 | flex: 1 1 auto; 119 | background-color: #fff; 120 | position:relative; 121 | } 122 | 123 | footer{ 124 | /* 和 header 一样,footer 也采用固定高度*/ 125 | /* 0 flex-grow, 0 flex-shrink, auto flex-basis */ 126 | flex: 0 0 auto; 127 | } 128 | } 129 | 130 | // hr 线条和颜色 131 | .hr(@color, @name) { 132 | .hr-@{color} { 133 | width: 100%; 134 | height: 1px; 135 | background: @color; 136 | font-size: 0; 137 | margin: 0 auto; 138 | } 139 | @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2) { 140 | transform: translate(0, 1 / 2 * 100'px'); 141 | } 142 | @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3) { 143 | transform: translate(0, 1 / 2 * 100'px'); 144 | } 145 | } 146 | -------------------------------------------------------------------------------- /src/style/common/scss/_mixin.scss: -------------------------------------------------------------------------------- 1 | //移动端通用样式 1rem 相当于100px算的 也就是 宽度 / 7.5的比例 2 | @function px75rem($px){ 3 | $rem : 100px; 4 | @return ($px * 1px / $rem) + rem; 5 | } 6 | 7 | // 多少行限制超出省略 8 | @mixin lineclamp($height, $count, $isrem: false) { 9 | @if($isrem == false) { 10 | height: px75rem($height); 11 | line-height: px75rem($height / $count); 12 | } @else { 13 | height: $height; 14 | line-height: $height / $count; 15 | } 16 | overflow:hidden; 17 | text-overflow:ellipsis; 18 | display:-webkit-box; 19 | -webkit-box-orient:vertical; 20 | -webkit-line-clamp: $count; 21 | word-wrap: break-word; 22 | } 23 | 24 | @mixin textoneline ($height: auto) { 25 | height: $height; 26 | @if($height == auto) { 27 | line-height: initial; 28 | } else { 29 | line-height:$height; 30 | } 31 | @include ellipsis(); 32 | } 33 | 34 | 35 | @mixin colortext-lt ($color1, $color2) { 36 | position: relative; 37 | @include background(linear-gradient(to bottom right, $color1, $color2)); 38 | -webkit-background-clip: text; 39 | -webkit-text-fill-color: transparent; 40 | } 41 | 42 | @mixin colortext-l ($color1, $color2) { 43 | position: relative; 44 | @include background(linear-gradient(to right, $color1, $color2)); 45 | -webkit-background-clip: text; 46 | -webkit-text-fill-color: transparent; 47 | } 48 | 49 | // 计算属性 50 | @mixin ccalc($pro, $all, $reduce) { 51 | #{$pro}: calc(#{$all} - #{$reduce}); 52 | } 53 | 54 | // footer header content充满body 55 | @mixin fixfooter($headerH, $footerH) { 56 | body,html{ 57 | min-height: unset!important; 58 | height: 100%!important; 59 | } 60 | .custom_header{ 61 | height: $headerH; 62 | @include box-sizing(border-box); 63 | position: relative; 64 | } 65 | .custom_footer{ 66 | height: $footerH; 67 | @include box-sizing(border-box); 68 | position: relative; 69 | } 70 | .custom_content{ 71 | position: relative; 72 | background-color: #f0f0f0; 73 | min-height: calc(100% - #{$headerH} - #{$footerH}); 74 | } 75 | } 76 | 77 | @mixin fixfooterflex () { 78 | html{ 79 | height: 100%; 80 | } 81 | 82 | body{ 83 | display: flex; 84 | flex-direction: column; 85 | min-height: 100%; 86 | // font-family: "Hiragino Sans GB","Century Gothic",system, Arial, Verdana, Tahoma,"微软雅黑"; 87 | font-family: $font; 88 | position: relative; 89 | width: 100%; 90 | overflow-x: hidden; 91 | } 92 | 93 | header{ 94 | /* 我们希望 header 采用固定的高度,只占用必须的空间 */ 95 | /* 0 flex-grow, 0 flex-shrink, auto flex-basis */ 96 | flex: 0 0 auto; 97 | } 98 | 99 | .main_content{ 100 | /* 将 flex-grow 设置为1,该元素会占用所有的可使用空间 101 | 而其他元素该属性值为0,因此不会得到多余的空间*/ 102 | /* 1 flex-grow, 0 flex-shrink, auto flex-basis */ 103 | flex: 1 1 auto; 104 | background-color: $color_bg; 105 | position:relative; 106 | } 107 | 108 | footer{ 109 | /* 和 header 一样,footer 也采用固定高度*/ 110 | /* 0 flex-grow, 0 flex-shrink, auto flex-basis */ 111 | flex: 0 0 auto; 112 | } 113 | } 114 | 115 | @mixin colorplaceholder($color) { 116 | ::-webkit-input-placeholder { /* WebKit browsers */ 117 | color: $color; 118 | } 119 | :-moz-placeholder { /* Mozilla Firefox 4 to 18 */ 120 | color: $color; 121 | opacity: 1; 122 | } 123 | ::-moz-placeholder { /* Mozilla Firefox 19+ */ 124 | color: $color; 125 | opacity: 1; 126 | } 127 | :-ms-input-placeholder { /* Internet Explorer 10+ */ 128 | color: $color; 129 | } 130 | } 131 | 132 | // 字体文字颜色的mixin 133 | @mixin colortext($color, $name) { 134 | .color-#{$name}{ 135 | color: $color; 136 | } 137 | } 138 | 139 | // hr 线条和颜色 140 | @mixin hr($color, $name) { 141 | .hr-#{$name}{ 142 | width: 100%; 143 | height: 1px; 144 | background: $color; 145 | font-size: 0; 146 | margin: 0 auto; 147 | } 148 | @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2) { 149 | @include translate(0, 1 / 2 * 100'px'); 150 | } 151 | @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3) { 152 | @include translate(0, 1 / 2 * 100'px'); 153 | } 154 | } 155 | 156 | // fixed布局铺面全屏 157 | @mixin fixedfull() { 158 | position: fixed; 159 | right: 0; 160 | top: 0; 161 | left: 0; 162 | bottom: 0; 163 | } 164 | 165 | // 不同背景图片使用不同的尺寸 166 | @mixin bgimage($url, $type: png, $hasmedia: false){ 167 | @if($hasmedia == true){ 168 | @media (-webkit-min-device-pixel-ratio: 2),(min-device-pixel-ratio: 2) { 169 | background-image: url($url + "@2x." + $type) 170 | } 171 | @media (-webkit-min-device-pixel-ratio: 3),(min-device-pixel-ratio: 3) { 172 | background-image: url($url + "@3x." + $type) 173 | } 174 | } 175 | background-image: url($url + "." + $type) 176 | } 177 | 178 | -------------------------------------------------------------------------------- /src/exp.ts: -------------------------------------------------------------------------------- 1 | import { LogUtils } from '@dw/d-utils' 2 | const Exp1 = /\bhi\b/ 3 | // \b 匹配单词的开始或结束 4 | LogUtils.logInfo(Exp1.test('hi')) 5 | LogUtils.logInfo(Exp1.test('hi2')) 6 | LogUtils.logError('', '--------------------------------------') 7 | const Exp2 = /\bhi\b.\bLucy\b/ 8 | LogUtils.logInfo(Exp2.test('hi Lucy')) 9 | LogUtils.logInfo(Exp2.test('hi aaa Lucy')) 10 | 11 | // 匹配字符长度 12 | // ^匹配你 要用来查找的字符串的开头,$匹配结尾。 13 | LogUtils.logInfo(/^\d{5,12}$/.test('11111')) 14 | LogUtils.logError('', '--------------------------------------') 15 | // w 匹配一个单字字符(字母、数字或者下划线)等价于[A-Za-z0-9_] 16 | LogUtils.logInfo(/\w/.test('aaaaa')) // true 17 | LogUtils.logInfo(/\w/.test('111')) // true 18 | LogUtils.logInfo(/\w/.test('z')) // true 19 | LogUtils.logInfo(/\w/.test('_')) // true 20 | // 匹配一个非单字字符。等价于[^A-Za-z0-9_] 21 | LogUtils.logInfo(/\W/.test('_')) // false 22 | LogUtils.logError('', '--------------------------------------') 23 | // 匹配字符串的开始用在[]括号里面表示排除,/^A/ 并不会匹配 "an A" 中的 'A',但是会匹配 "An E" 中的 'A'。 24 | LogUtils.logInfo(/\W/.test('a&&')) // true 25 | LogUtils.logInfo(/^\W/.test('a&&')) // false 26 | LogUtils.logInfo(/^\W/.test('&a&&')) // true 27 | LogUtils.logError('', '--------------------------------------') 28 | LogUtils.logInfo(/[^\w]/.test('a')) // true 相当于 /\W/ 29 | LogUtils.logInfo(/[^\W]/.test('a')) // true 30 | // $ 匹配字符串的结束。例如,/t$/ 并不会匹配 "eater" 中的 't',但是会匹配 "eat" 中的 't'。 QQ号必须为5位到12位数字时,可以使用:^\d{5,12}$ 31 | LogUtils.logInfo(/[^\W]$/.test('a_&')) // false 32 | LogUtils.logInfo(/[^\W]$/.test('a&_')) // true 33 | 34 | LogUtils.logError('', '--------------------------------------') 35 | // s 代表任意空白符(换行符,制表符,空格) 36 | LogUtils.logInfo(/\s/.test(' ')) // true 37 | 38 | 39 | // d 匹配一个数字,等价于[0-9] 40 | LogUtils.logInfo(/\d/.test(' ')) // false 41 | LogUtils.logInfo(/\d/.test('1111')) // true 42 | // D 匹配一个数字,等价于[^0-9] 43 | LogUtils.logInfo(/\d/.test('1111')) // false 44 | LogUtils.logError('', '--------------------------------------') 45 | 46 | // () 代表一个组 如果想要重复多个字符该怎么办?你可以用小括号来指定子表达式(也叫做分组) 47 | LogUtils.logInfo(/(\d{1,3}\.){3}\d{1,3}/.test('222.222.222.1')) // true 48 | LogUtils.logInfo([/\w.+/.test('test.i.ng'), /[a-z.]+/.test('test.i.ng')]) // true 49 | LogUtils.logInfo(/\w{3,5}/.test('___')) // true 50 | LogUtils.logInfo(/\d{3,5}/.test('___')) // true 51 | LogUtils.logError('', '--------------------------------------') 52 | // i 忽略大小写 53 | LogUtils.logInfo(/a/.test('aaaaaa')) // true 54 | LogUtils.logInfo(/a/.test('AAAAAA')) // false 55 | LogUtils.logInfo(/a/i.test('AAAAAA')) // true 56 | LogUtils.logError('', '--------------------------------------') 57 | // g 执行全局匹配 58 | LogUtils.logInfo(/a/.test('vvvvva')) // true 59 | const Exp3 = /a/g 60 | const str = 'aaaaaaaa' 61 | LogUtils.logInfo(Exp3.test(str)) // true 62 | LogUtils.logWarning(Exp3.lastIndex) 63 | LogUtils.logInfo(Exp3.test(str)) // true 64 | LogUtils.logWarning(Exp3.lastIndex) 65 | LogUtils.logInfo(Exp3.test(str)) // true 66 | LogUtils.logWarning(Exp3.lastIndex) 67 | LogUtils.logInfo(Exp3.test(str)) // true 68 | LogUtils.logWarning(Exp3.lastIndex) 69 | LogUtils.logError('', '--------------------------------------') 70 | // 71 | const str1 = 'daiwei' 72 | LogUtils.logInfo(/d(?=a)/.test(str1)) 73 | LogUtils.logInfo(/d(?=i|a)/.test(str1)) 74 | 75 | const num = '021-121121' 76 | LogUtils.logInfo(/\(?0\d{2}[)-]?\d{6}/.test(num)) 77 | 78 | // 6-12 数字 字母 下划线 79 | const pwd = 'Daiwei__12' 80 | LogUtils.logInfo(/^\w{6,12}$/.test(pwd)) 81 | LogUtils.logError('', '--------------------------------------') 82 | const str2 = 'Hi RegExp I love you so much Hi Hi hi' 83 | const Exp4 = /\bhi\b/gi 84 | const Exp5 = /\bhi\b.*\bmuch\b/gi 85 | LogUtils.logInfo(Exp4.test(str2)) 86 | LogUtils.logInfo(Exp4.lastIndex) 87 | LogUtils.logInfo(Exp4.test(str2)) 88 | LogUtils.logInfo(Exp4.lastIndex) 89 | LogUtils.logInfo(Exp4.test(str2)) 90 | LogUtils.logInfo(Exp4.lastIndex) 91 | LogUtils.logInfo(Exp4.test(str2)) 92 | LogUtils.logInfo(Exp4.lastIndex) 93 | LogUtils.logInfo(str2.match(Exp4)) 94 | LogUtils.logInfo(Exp5.test(str2)) 95 | LogUtils.logInfo(str2.match(Exp5)) 96 | LogUtils.logError('', '--------------------------------------') 97 | 98 | // 匹配手机号 0123-88752314 99 | const Exp6 = /^0\d{3}-\d{8}$/g 100 | LogUtils.logInfo(Exp6.test('0123-45678910')) 101 | LogUtils.logInfo(Exp6.test('0123-456789101')) 102 | LogUtils.logInfo(Exp6.test('10123-456789101')) 103 | LogUtils.logInfo('0123-45678910'.match(Exp6)) 104 | LogUtils.logInfo('0123-456789101'.match(Exp6)) 105 | LogUtils.logInfo('10123-456789101'.match(Exp6)) 106 | LogUtils.logError('', '--------------------------------------') 107 | 108 | // 清除字符串首尾表达式 109 | const str3 = ' this is space ' 110 | const Exp7 = /(^\s*) | (\s*$)/g 111 | // 去除所有空格 112 | const Exp8 = /(\s)/g 113 | LogUtils.logInfo(str3) 114 | LogUtils.logInfo(str3.replace(Exp7, '')) 115 | LogUtils.logInfo(str3.replace(Exp8, '')) 116 | LogUtils.logError('', '--------------------------------------') 117 | 118 | // 匹配一个邮箱。 185098535@qq.com 119 | const Exp9 = /\S*@\S*\.\S*/ 120 | const str4 = '18509535@qq.com' 121 | LogUtils.logInfo(Exp9.test(str4)) 122 | LogUtils.logError('', '--------------------------------------') 123 | 124 | // 练习只能是汉字 125 | const Exp10 = /^[\u4e00-\u9fa5]*$/g 126 | const str5 = '戴伟' 127 | LogUtils.logInfo(Exp10.test(str5)) 128 | LogUtils.logInfo('JavaScript'.search(/a(.)a/)) 129 | 130 | --------------------------------------------------------------------------------