用你的webpack实现vue-cli

本文围绕前端工程化,用webpack从零搭建一个完整项目的过程

本文核心知识点:

  1. webpack的使用
  2. vue组件化思想
  3. Element-UI的使用
别走别走,迫不及待看结果了吧:

想学吗,来俺教你(献丑,哈哈)

实现步骤:

写在前面:此案例用于强化你的webpack使用(须对webpack有一定的了解),若本文有错误以及运行出错,欢迎随时来扰我这只:爱学习的小白

  1. 创建项目文件夹(vue_todo)
  2. 生成项目描述文件(npm init -y)
  3. 在项目根目录下创建index.html(代码后补)
  4. 在项目根目录下创建src文件夹(添加main.js和App.vue)
  • main.js(涵盖全文)
//! 需要导入实例化vue根实例
import Vue from 'vue'
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
import App from './App.vue'; Vue.use(ElementUI); new Vue({
el: '#app',
components: {
App
},
template: '<App/>'
});
  1. 项目根目录下创建build文件夹(添加webpack配置文件),此处用于更好的区分开发环境和生产环境;也可不建,直接在根目录下建立webpack.config.js(名字唯一)

    生成如下:

  2. 安装webpack,webpack-cli
  3. 在build文件夹下建立webpack.dev.js(进行webpack的配置),此处需了解webpack的基本使用webpack基本使用,一般配置有(entry:入口,output:出口,loader:加载器,plugins:插件)
本项目配置为:

写在前面:此处生产环境与开发环境代码冗余度过高,所以抽出公共部分(webpack.base.js)并用第三方模块(webpack-merge)进行合并,此处loader以及plugin的使用随着官网的更新,可能会发生变化,以官网为准,webpack官网

  • webpack.base.js(注释含细节,其中路径相关项切记与自己文件路径保持一致)
// 引入路径处理模块
const path = require('path'); // 引入vue-loader插件(加载vue模板)
const VueloaderPlugin = require('vue-loader/lib/plugin'); // 引入html-webpack-plugin(生成预览的html页)
const HtmlWepackPlugin = require('html-webpack-plugin'); // 引入clean-wenpack-plugin(需进行解构)(每次打包前删除之前dist目录下的js文件)
const { CleanWebpackPlugin } = require('clean-webpack-plugin'); module.exports = {
// 打包入口
entry: './src/main.js',
// 打包出口
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, '../dist')
},
// 配置打包规则
module: {
rules: [{
test: /\.vue$/,
use: 'vue-loader'
}, {
test: /\.(jpg|png|gif|bmp|eot|svg|woff|woff2|ttf)$/,
use: [{
loader: 'url-loader',
query: {
name: '[name].[ext]'
}
}]
}, {
test: /\.css$/,
use: ['style-loader', 'css-loader']
}, {
test: /\.styl(us)?$/,
use: ['vue-style-loader', 'css-loader', 'postcss-loader', 'stylus-loader']
}, {
test: /\.js$/,
exclude: /node_modules/,
loader: "babel-loader"
}]
},
// 插件
plugins: [
new VueloaderPlugin(),
new HtmlWepackPlugin({
template: './index.html'
}),
new CleanWebpackPlugin()
],
resolve: {
alias: {
'vue': 'vue/dist/vue.js'
}
},
performance: {
hints: false
}
}
  • webpack.dev.js
const baseConfig = require('./webpack.base.js');
const merge = require('webpack-merge'); // 引入webpack对象(实现热模块替换)
const webpack = require('webpack');
const devConfig = {
mode: 'development',
// devServer配置
devServer: {
contentBase: '../dist',
// 打包完成自动打开
open: true,
// 模块热替换
hot: true
},
//! 使打包后的js文件与源文件产生映射关系(增加纠错速度,错误定位),官网介绍详细
//! eval一般应用于生产环境(production)
//! devtool: 'eval',
//vue脚手架一般配置(打包速度较慢)
devtool: 'cheap-module-eval-source-map',
// 插件
plugins: [
new webpack.HotModuleReplacementPlugin()
],
} module.exports = merge(baseConfig, devConfig);
  • webpack.prod.js
const baseConfig = require('./webpack.base.js');
const merge = require('webpack-merge'); const prodConfig = {
mode: 'production'
} module.exports = merge(baseConfig, prodConfig)

注意:此处的loader(postcss-loader,babel-loader)需要添加额外配置文件

passcss.config.js

module.exports = {
plugins: [
require('autoprefixer')
]
}

.babelrc

{
"presets": ["@babel/preset-env"]
}
  1. 在项目描述(package.js)中写入脚本(script标签中写),用于打包项目(此处涵盖所有依赖项)
{
"name": "vue_todo",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"dev": "webpack-dev-server --config ./build/webpack.dev.js",
"build": "webpack --config ./build/webpack.prod.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.9.6",
"@babel/preset-env": "^7.9.6",
"autoprefixer": "^9.7.6",
"babel-loader": "^8.1.0",
"clean-webpack-plugin": "^3.0.0",
"css-loader": "^3.5.3",
"file-loader": "^6.0.0",
"html-webpack-plugin": "^4.3.0",
"postcss-loader": "^3.0.0",
"style-loader": "^1.2.1",
"stylus": "^0.54.7",
"stylus-loader": "^3.0.2",
"url-loader": "^4.1.0",
"vue-loader": "^15.9.2",
"vue-template-compiler": "^2.6.11",
"webpack": "^4.43.0",
"webpack-cli": "^3.3.11",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^4.2.2"
},
"dependencies": {
"element-ui": "^2.13.1",
"vue": "^2.6.11"
}
}
配置完成,安心撸vue组件

写在前面:对于组件的认识,可以学习:vue组件化开发

  1. 对项目界面进行组件拆分:App(MainHeader,MainTodo(TodoItem,TodoInfo),MainFooter)
  2. 进行每个组件的编写(注意组件之间的数据传递)
  3. 进行组件样式的编写(此处除css样式外,还演示了stylus样式(未涉及可忽略))
  4. 进行子组件的挂载
  5. 在组件中使用Element-UI

奉上我的vue代码:

  • App.vue
<template>
<div>
<!-- 调用组件时必须用短横线的方式写入标签 -->
<main-header></main-header>
<main-todo></main-todo>
<main-footer></main-footer>
</div>
</template> <script>
//! 引入样式,格式为stylus
import './assets/styles/global.styl'
//! 导入子组件(头部)
import MainHeader from './components/MainHeader.vue'
//! 导入子组件(中间部分)
import MainTodo from './components/MainTodo/MainTodo.vue'
//! 导入子组件(底部)
import MainFooter from './components/MainFooter.vue' export default {
name:'App',
components:{
//! 组件名:组件对象(es6中键和值同名,可简写)
MainHeader:MainHeader,
MainTodo:MainTodo,
MainFooter:MainFooter
}
}
</script> <style lang="css" scoped> </style>
  • MainHeader.vue
<template>
<header>
<h1>ToDoList</h1>
</header>
</template> <script>
export default {
//todo 组件名尽量与文件名一致(思路容易捋顺)
name:'MainHeader'
}
</script> <style lang="stylus" scoped>
header {
height 200px;
width 100%;
text-align center;
}
header h1{
line-height 200px;
font-size 100px;
font-weight 100;
color pink;
text-shadow 1px 1px 1px pink,3px 3px 9px red;
}
</style>
  • MainTodo
<template>
<div class="main-todo">
<input type="text" class="what-todo" placeholder="What do you want to do ?" autofocus @keyup.enter="addTodo" v-model="content">
<todo-item v-for="(item,index) in filterData" :key="index" :todo="item" @delTodo="delThis($event)"></todo-item>
<todo-info :unComplete="unComplete" :AllComplete="AllComplete" @toggleState="handleToggleState($event)" @delComplete="delComplete"></todo-info>
</div>
</template> <script> //todo 导入TodoItem子组件
import TodoItem from './coms/TodoItem.vue'
//todo 导入TodoInfo子插件
import TodoInfo from './coms/TodoInfo.vue' //todo 用id自加模拟计数器
let id = 0
export default {
name:'MainTodo',
data(){
return{
todos:[],
content:'',
filter:'all'
}
},
methods:{
addTodo(){
//todo 如果输入框为空,直接返回
if(this.content === '') return
this.todos.unshift({
id:id++,
content:this.content,
complete:true
})
this.content = ''
},
delThis(id){
const index = this.todos.findIndex(item=>{
return item.id == id
})
this.todos.splice(index,1)
},
handleToggleState(state){
this.filter = state
},
delComplete(){
this.todos = this.todos.filter(item=>item.complete == true)
}
},
computed:{
unComplete(){
const unDone = this.todos.filter(item=>{
return item.complete == true
})
return unDone.length
},
AllComplete(){
const Done = this.todos.filter(item=>{
return item.complete == false
})
return Done.length
},
filterData(){
switch(this.filter){
case 'all':
return this.todos
break;
case 'active':
return this.todos.filter(item=>item.complete == true)
break;
case 'complete':
return this.todos.filter(item=>item.complete == false)
break;
}
}
},
components:{
TodoItem,
TodoInfo,
}
}
</script> <style lang="stylus" scoped>
.main-todo{
width 600px
background-color rgba(0,0,0,.2)
border-radius 18px 18px 0 0
overflow hidden
margin 0 auto
box-sizing border-box
}
.what-todo{
height 45px
width 100%
font-size 20px
font-weight 300
padding-left 16px
border 0
outline 0
background-color rgba(0,0,0,.2)
border-bottom 3px dashed pink
}
::placeholder{
color #ccc
}
</style>
  1. MainTodo子组件TodoItem.vue
<template>
<div class="box">
<span class="switch"><el-switch v-model="todo.complete" active-color="#13ce66" inactive-color="#ff4949"></el-switch></span>
<label :class="['todo',todo.complete?'':'complete']">{{todo.content}}</label>
<button @click="$emit('delTodo',todo.id)"><i class="el-icon-delete active"></i></button>
</div>
</template> <script>
export default {
name:'TodoItem',
props:['todo'],
data(){
return{
value:true
}
}
}
</script> <style lang="stylus" scoped>
.box{
width 600px
height 40px
display flex
justify-content space-between
border-top 1px dashed pink
}
.switch{
padding 0px 9px
}
.box span,
.active{
height 40px
width 40px
text-align center
line-height 40px
}
.active{
color red
font-size 20px
cursor pointer
}
.todo{
flex 1
height 100%
font-size 20px
color red
line-height 40px
padding-left 15px
}
.complete{
color #ccc
text-decoration line-through
}
button{
outline none
border none
background-color rgba(0,0,0,0)
}
</style>
  1. MainTodo子组件TodoInfo
<template>
<div class="todo-info">
<span class="total" v-if="(state == 'all' | state == 'active')">{{unComplete}} item left</span>
<span class="total" v-if="(state == 'complete')">{{AllComplete}} item left</span>
<div class="tabs">
<a :class="state == item ? 'active': ''" v-for="(item,index) in states" :key="index" @click="toggleState(item)">{{item}}</a>
</div>
<el-button type="success" @click="$emit('delComplete')">Clear Complete</el-button>
</div>
</template> <script>
export default {
name:'TodoInfo',
props:['unComplete','AllComplete'],
data(){
return{
states:['all','active','complete'],
state:'all'
}
},
methods:{
toggleState(state){
this.state = state
this.$emit('toggleState',state)
}
}
}
</script> <style lang="css" scoped>
.todo-info{
display: flex;
justify-content: space-between;
padding: 5px 10px;
font-weight: 400;
line-height: 30px;
}
.total{
padding: 5px 0px;
color: red;
font-size: 16px;
font-weight: 700;
}
.tabs{
display: flex;
justify-content: space-between;
width: 200px;
}
.tabs a{
border: 1px solid palevioletred;
padding: 5px 10px;
border-radius: 12px;
cursor: pointer;
}
.active{
background-color: hotpink;
color: #fff;
}
</style>
  • MainFooter
<template>
<footer>Written By A Seeker Of Knowladge</footer>
</template> <script>
export default {
name:'MainFooter'
}
</script> <style lang="css" scoped>
footer{
font-style: 24px;
font-weight: 800;
margin-top: 20px;
text-align: center;
color: pink;
text-shadow: 1px 1px 1px black,3px 3px 9px hotpink;
}
</style>
快在终端输入:npm run dev 跑起来吧

Last:

有小伙伴问我的怪癖,注释后为撒要写('!','?','todo','cwen'),今天统回复下,这是vscode的注释高亮插件。可以让你的注释也能像代码一样招人喜欢。最后附上插件名:Better Comments

  1. 安装插件
  2. 在settings.json里自定义自己的样式
  3. 预览效果

身体and灵魂必须一个在路上(共勉)

用项目强化你的webpack的更多相关文章

  1. Vue项目环境搭建(node+webpack)

    安装node.js 下载地址:https://nodejs.org/en/download/ node -v //查看node.js版本 项目环境配置: 安装vue-cli:npm install - ...

  2. Vue实战Vue-cli项目构建(Vue+webpack系列之一)

    用Vue比较长一段时间了,大大小小做了一些项目,最近想总结一下知识点,出一个Vue+webpack系列,先从项目构建说起--vue-cli. 由于是Vue+webpack这里就不赘述git那些东西,默 ...

  3. React项目构建(利用webpack打包)

    引言 最近React作为当前最为火热的前端框架.最近也相继而出来相关ES7的新语法. 当然,在使用React开发web项目的时候,不得不提到的就是与之配套的相应的打包技术,之前上文已经简单的提到Rea ...

  4. 项目构建分析和 webpack 优化实践

    加入新公司一个月,最近接手在做一个 chrom 浏览器插件的项目,开发过程中发现项目打包的时间很长,足足有30多秒,这是让人很难接受的,而且构建的显示了几条包体积过大的提示信息: 可以看到,打包后有三 ...

  5. 前端项目自动化构建工具——Webpack入门教程

    参考资料:https://www.webpackjs.com/(中文文档)   https://www.webpackjs.com/(官方文档) 首先有必要说明一下,本文侧重讲解webpack基本配置 ...

  6. vue-cli安装以及创建一个简单的项目(一)(Node\npm\webpack简单使用)

    1.关系介绍 1.简单的说 Node.js 就是运行在服务端的 JavaScript. 2.NPM是随同NodeJS一起安装的包管理工具(新版的nodejs已经集成了npm),能解决NodeJS代码部 ...

  7. vue项目构建:vue-cli+webpack常用配置

    1,Webpack-dev-server的proxy用法:https://www.jianshu.com/p/f489e7764cb8 2,vue-cli3搭建项目之webpack配置:https:/ ...

  8. vue项目开发,用webpack配置解决跨域问题

    今天在本地开发时候碰到了跨域的问题,突然觉着跨域问题在所难免啊,之前没有没有碰到总觉着解决跨域很高大上的样纸,其实就是受限于网络的同源策略,跨域前后端都可以进行处理. 1,后端更改header hea ...

  9. vue.js及项目实战[笔记]— 05 WebPack

    一. 历史介绍 1. 规范 AMD Commonjs||CMD UMD 参考:认识AMD.CMD.UMD.CommonJS 2. 工具 npm bower webpack browserify 参考: ...

随机推荐

  1. 测试Thread中的常用方法

    package com.yhqtv.java; /* *测试Thread中的常用方法: * 1.start():启动当前线程:调用当前线程的run() * 2.run():通常需要重写Thread类的 ...

  2. PHP open_basedir配置未包含upload_tmp_dir 导致服务器不能上传文件

    在做一个上传图片的功能时候发现后台接收到的$_FILES['file']['error'] = 6,这个错误意思是找不到临时文件,或者是临时文件夹无权限,需要更改php.ini文件的 upload_t ...

  3. Pascal 字符串

    Dancing with Strings http://baskent.edu.tr/~tkaracay/etudio/ders/prg/pascal/PasHTM1/pas/pasl1007.htm ...

  4. eclipse自动补全导致变量会跟上String后缀的问题解决

    https://blog.csdn.net/feinifi/article/details/103665860

  5. Deep Snake : 基于轮廓调整的SOTA实例分割方法,速度32.3fps | CVPR 2020

    论文提出基于轮廓的实例分割方法Deep snake,轮廓调整是个很不错的方向,引入循环卷积,不仅提升了性能还减少了计算量,保持了实时性,但是Deep snake的大体结构不够优雅,应该还有一些工作可以 ...

  6. 【深入AQS原理】我画了35张图就是为了让你深入 AQS

    申明 本文首发自公众号:程序员cxuan,此文章为本人投稿文章.已经和cxuan沟通,文章投递公众号,博客平台我自己发布可标记为原创. 此文章肝了很久,图片较多,希望大家喜欢. 另外,感兴趣的小伙伴可 ...

  7. (原創) 如何在Nios II顯示8位數的七段顯示器? (SOC) (Nios II) (SOPC Builder) (DE2-70)

    Abstract本文討論如何在Nios II控制8位數的七段顯示器. Introduction使用環境:Quartus II 8.0 + Nios II EDS 8.0 + DE2-70 (Cyclo ...

  8. Jmeter系列(8)- test plam测试计划参数详解

    如果你想从头学习Jmeter,可以看看这个系列的文章哦 https://www.cnblogs.com/poloyy/category/1746599.html 前言 先了解下测试计划的作用:http ...

  9. spark系列-7、spark调优

    官网说明:http://spark.apache.org/docs/2.1.1/tuning.html#data-serialization 一.JVM调优 1.1.Java虚拟机垃圾回收调优的背景 ...

  10. SQLite使用(二)

    sqlite3_exec虽然好用,但是一般不推荐直接使用. 常用的一组操作是: 关于sqlite3_exec和sqlite3_prepare_v2的使用场景,建议如下: 一个小DEMO: #inclu ...