这篇随笔会陆续地更新下去,用于汇集一些关于Webpack的初学跳坑总结还有VueJS的基础知识。

Webpack部分

① 快速建立一个Webpack-Vue项目开发环境(4.39.1-2019/08/07)

Step 1 安装 Webpack:

 
 
COPY
EXPAND
1
npm install webpack -g
 
 
COPY
EXPAND

Step 2 Webpack 4 需要再安装 Webpack-Cli:

 
 
COPY
EXPAND
1
npm install webpack-cli -g
 
 
COPY
EXPAND

Step 3 快速初始化一个Vue项目

 
 
COPY
EXPAND
1
npm init --yes
 
 
COPY
EXPAND

安装Vue和Webpack-dev-server

vue@2.6.10

webpack-cli@3.3.6

webpack-dev-server@3.7.2

 
 
COPY
EXPAND
1
npm install vue --save
 
 
COPY
EXPAND

这里安装webpack-dev-server,目的是方便调试,其热加载工具可以侦测项目文件夹下的文件变动,相应地进行自动刷新,当然,还需要手动配置,后面会讲到。

 
 
COPY
EXPAND
1
npm install webpack-dev-server --save
 
 
COPY
EXPAND

项目文件夹下安装,webpack,webpack-cli

 
 
COPY
EXPAND
1
npm install webpack --save
 
 
COPY
EXPAND

webpack现在的版本需要这样安装webpack-cli

 
 
COPY
EXPAND
1
npm install -D webpack-cli --save
 
 
COPY
EXPAND

安装vue-loader,同时还要安装vue-template-complier

 
 
COPY
EXPAND
1
npm install vue-loader vue-template-compiler --save
 
 
COPY
EXPAND

Step 4 开始动工一个项目

创建文件夹目录和文件,例如项目根目录叫做webpack-test,其下创建2个文件夹:dist/、src/,创建3个文件:index.html、packge.json、webpack.config.js,src/下创建main.js、templates/以及templates/main.vue,具体文件关系如下图:

按照如下编辑文件内容:

 
index.html
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>webpack-test</title>
</head>
<body>
    <div id="app"></div>
</body>
<script src="./dist/build.js" type="text/javascript"></script>
</html>
 
index.html
COPY
EXPAND
 
package.json
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
{
  "name": "webpack-test",
  "version": "1.0.0",
  "description": "webpack-test",
  "main": "index.js",
  "scripts": {
    "dev": "webpack-dev-server --open --hot --mode development",
    "build": "webpack --progress --hide-modules --mode production"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "vue": "^2.6.10",
    "vue-loader": "^15.7.1",
    "vue-template-compiler": "^2.6.10",
    "webpack": "^4.39.1",
    "webpack-dev-server": "^3.7.2"
  },
  "devDependencies": {
    "webpack-cli": "^3.3.6"
  }
}
 
package.json
COPY
EXPAND
 
webpack.config.js
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
const path = require("path");
// vue-loader
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const argvs = require("process").argv;
module.exports = {
    entry: './src/main.js', // 项目的入口文件,webpack会从main.js开始,把所有依赖的js都加载打包
    output: {
        path: path.resolve(__dirname, './dist'), // Webpack 打包目标文件夹
        // publicPath: './dist', // webpack-dev-serve 访问路径
        // 判断是开发模式还是打包发布模式设置合理的文件路径
        publicPath: argvs[argvs.indexOf("--mode")+1] === "development" ? "/dist/" : "./dist/",
        filename: 'build.js' // 打包后的文件名
    },
    devServer: {
        historyApiFallback: true, // 404 则返回到 index.html
        overlay: true, // html 页面顶层显示报错提示信息
        // clientLogLevel: "none" // 减少浏览器控制台 log
    },
    resolve: {
        alias: {
            vue$: "vue/dist/vue.esm.js"
        }
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: "vue-loader"
            }
        ]
    },
    plugins: [
        // 加载 vue-loader
        new VueLoaderPlugin()
    ]
};
 
webpack.config.js
COPY
EXPAND
 
main.js
COPY
EXPAND
1
2
3
4
5
6
7
import Vue from "vue";
import appMain from "./templates/main.vue";
new Vue({
    "el": "#app",
    "template": "<app-main/>",
    "components": { appMain }
})
 
main.js
COPY
EXPAND
 
main.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<template>
    <div class="main">
        <p v-text="txt">...</p>
    </div>
</template>
<script>
export default {
    "name": "appMain",
    data () {
        return {
            txt: "Hello,Vue!"
        }
    }
}
</script>
 
main.vue
COPY
EXPAND

Step 5 webpack 使用

先运行打包看看:

 
 
COPY
EXPAND
1
npm run build
 
 
COPY
EXPAND

之后便在 dist/ 下打包好一个 build.js 文件

开发模式,热加载,很方便,一旦它监测文件更改,便会热加载,解放了键盘刷新操作,很省心。

 
 
COPY
EXPAND
1
npm run dev
 
 
COPY
EXPAND

之后会开启一个webpack-dev服务,然后默认浏览器跳转到 localhost 页面,不出意外,屏幕上已经打印出了 Hello, Vue! :

②Webpack添加Babel编译器(2019/08/08)

@babel/core@7.5.5

@babel/preset-env@7.5.5

@babel/preset-react@7.0.0

babel-loader@8.0.6

Step 1 安装 BABEL

 
 
COPY
EXPAND
1
npm install @babel/core @babel/preset-env @babel/preset-react babel-loader --save
 
 
COPY
EXPAND

等待安装完成后,webpack.config.js中添加babel-loader:

 
webpack.config.js
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
const path = require("path");
// vue-loader
const VueLoaderPlugin = require("vue-loader/lib/plugin");
const argvs = require("process").argv;
module.exports = {
    entry: ['./src/main.js'], // 项目的入口文件,webpack会从main.js开始,把所有依赖的js都加载打包
    output: {
        path: path.resolve(__dirname, './dist'), // Webpack 打包目标文件夹
        // publicPath: './dist', // webpack-dev-serve 访问路径
        // 判断是开发模式还是打包发布模式设置合理的文件路径
        publicPath: argvs[argvs.indexOf("--mode")+1] === "development" ? "/dist/" : "./dist/",
        filename: 'build.js' // 打包后的文件名
    },
    devServer: {
        historyApiFallback: true, // 404 则返回到 index.html
        overlay: true, // html 页面顶层显示报错提示信息
        clientLogLevel: "none" // 减少浏览器控制台 log
    },
    resolve: {
        alias: {
            vue$: "vue/dist/vue.esm.js"
        }
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                loader: "vue-loader"
            },
            { // 此处添加 balbel-loader
                test: /\.js$/,
                use: {
                    loader: "babel-loader",
                    options: {
                        presets: ["@babel/env"]
                    }
                }
            }
        ]
    },
    plugins: [
        // 加载 vue-loader
        new VueLoaderPlugin()
    ]
};
 
webpack.config.js
COPY
EXPAND

Step 2 现在可以大胆地使用ES6的语法了,举例:

 
main.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<template>
    <div class="main">
        <span v-for="(l, i) in letters" :key="i" v-text="l"></span>
    </div>
</template>
<script>
export default {
    "name": "appMain",
    "computed": {
        letters () {
            const atA = "A".charCodeAt();
            const atZ = "Z".charCodeAt();
            let arr = [];
            for (let x=atZ+1; x>atA; arr[x--] = x);
            return arr.map( num => {
                return unescape(`%${num.toString(16)}`)
            }).filter( item => {
                return item;
            });
        }
    }
}
</script>
 
main.vue
COPY
EXPAND

如上vue实现的是遍历出26个英文字母,页面正常显示,查看控制台,babel确实起作用了,转成了ES5:

③单文件组件开发注意的几点:

1.避免打包文件过大,乱成“一锅粥”。

1) vue 单文件内的样式表部分可以全部写在打包文件夹目录之外的一个文件内,然后在index.html引入,否则在打包后出现下面的一些现象,显得代码臃肿:

2) utils等js插件尽量用script标签引入,减少打包过程的时间和打包文件的体积;

3) vue单文件的cssstyle标签内不要留有太多的注释,也是为了限制文件体积,参考 1);

VueJS基础

①单文件组件开发中,子父组件传值问题(2019/08/08)

子 → 父组件传值

方法一:使用 vm.$emit( eventName, […args] )

会在当前实例下触发一个事件,$emit的eventName后面的变量,将会传给Vue绑定的事件的回调函数里面,举个例子,譬如要实现一个多个选项的点击跳转功能:点击某个头像跳转到相应网址:

子组件文件定义了头像的整个布局或结构,父组件文件中依赖数组遍历子组件,这时就需要被点击到的子组件传递给父组件其对应的渲染 data

 
chCh.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 子组件
<template>
    <!-- 某个子组件被点击后,则会触发父组件的 goto 方法,同时传递渲染这个子组件的 obj -->
    <div class="ch-ch" :style="{'background-color': obj.color}" @click="$emit('goto', obj)">
        <div class="icon">
            <span v-text="obj.name.charAt(0)"></span>
        </div>
        <div class="label" v-text="obj.name"></div>
    </div>
</template>
<script>
export default {
    "name": "chCh",
    "props": [ "obj" ]
}
</script>
<style>
.ch-ch { cursor: pointer; position: relative; display: flex; justify-content: center; align-items: center; margin: 1rem .5rem; width: 3.5rem; height: 3.5rem; border-radius: 50%; }
.icon { display: flex; font-size: 2rem; font-weight: 600; color: #fff; }
.label { position: absolute; bottom: -1.5rem; left: 0; width: 100%; text-align: center; }
</style>
 
chCh.vue
COPY
EXPAND
 
faFa.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 父组件
<template>
    <div class="main">
        <!-- @goto === v-on:goto -->
        <ch-ch v-for="item in arr" :key="item.name" :obj="item" @goto="goto"></ch-ch>
    </div>
</template>
<script>
import chCh from "./chCh.vue";
export default {
    "name": "faFa",
    "components": { chCh },
    "methods": {
        // 被子组件触发的方法
        goto (data) {
            console.log(data.site)
            // window.location.href = data.site; // 跳转到某个网址
        }
    },
    data () {
        return {
            // 渲染数据
            arr: [
                {
                    name: "Mike", color: "cornflowerblue", site: "https://a.com"
                }, {
                    name: "Jhon", color: "firebrick", site: "https://b.com"
                }, {
                    name: "Frank", color: "yellowgreen", site: "https://c.com"
                }
            ]
        }
    }
}
</script>
<style>
.main { display: flex; justify-content: center; }
</style>
 
faFa.vue
COPY
EXPAND

方法二:子组件修改$parent.$data[...],父组件在watch中添加对[...]的watcher:

 
chCh.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 子组件
<template>
    <div class="ch-ch" :style="{'background-color': obj.color}" @click="goto(obj)">
        <div class="icon">
            <span v-text="obj.name.charAt(0)"></span>
        </div>
        <div class="label" v-text="obj.name"></div>
    </div>
</template>
<script>
export default {
    "name": "chCh",
    "props": [ "obj" ],
    "methods": {
        goto (data) {
            // 修改父组件的 $data 的值,触发 watcher
            this.$parent.obj = data;
        }
    }
}
</script>
<style>
.ch-ch { cursor: pointer; position: relative; display: flex; justify-content: center; align-items: center; margin: 1rem .5rem; width: 3.5rem; height: 3.5rem; border-radius: 50%; }
.icon { display: flex; font-size: 2rem; font-weight: 600; color: #fff; }
.label { position: absolute; bottom: -1.5rem; left: 0; width: 100%; text-align: center; }
</style>
 
chCh.vue
COPY
EXPAND
 
faFa.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
// 父组件
<template>
    <div class="main">
        <ch-ch v-for="item in arr" :key="item.name" :obj="item"></ch-ch>
    </div>
</template>
<script>
import chCh from "./chCh.vue";
export default {
    "name": "faFa",
    "components": { chCh },
    "watch": {
        // 添加监测
        obj (new_val, old_val) {
            console.log(new_val.site)
        }
    },
    data () {
        return {
            // 渲染数据
            arr: [
                {
                    name: "Mike", color: "cornflowerblue", site: "https://a.com"
                }, {
                    name: "Jhon", color: "firebrick", site: "https://b.com"
                }, {
                    name: "Frank", color: "yellowgreen", site: "https://c.com"
                }
            ], 
            //监测的对象
            obj: {}
        }
    }
}
</script>
<style>
.main { display: flex; justify-content: center; }
</style>
 
faFa.vue
COPY
EXPAND

父 → 子组件传值的几种办法

方法一:子组件暴露props,父组件使用v-bind,这个是最常用的方法之一。

方法二:父组件在引用子组件的标签上加入ref="..."属性,然后通过this.$refs[...].$data[---],来传递数据

 
faFa.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// 父组件
<template>
    <div class="main">
        <ch-ch ref="child"></ch-ch>
    </div>
</template>
<script>
import chCh from "./chCh.vue";
export default {
    "name": "faFa",
    "components": { chCh },
    mounted () {
        console.log(this.obj = this.$refs["child"].obj)
    }
}
</script>
 
faFa.vue
COPY
EXPAND

②添加过渡动画

Step 1 从四个「点」两个阶段/状态添加CSS样式/动画:

官方的一张图表:

由下面的3D flip card的例子(建议Chrome下运行)可知leave-to类名会影响到整个动画退出过程的样式:(其中的keyframes只起到定时隐藏或显现正反面内容的作用),注意leave-to/enter-to对animation过程的影响程度最长

 
test-main.vue
COPY
EXPAND
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
<template>
    <div class="test">
        <div class="card" :class="{'flip': isFlip}" @click="flip">
            <transition name="front">
                <div class="front" v-if="!isFlip"></div>
            </transition>
            <transition name="back">
                <div class="back" v-if="isFlip"></div>
            </transition>
        </div>
    </div>
</template>
<script>
export default {
    name: "testMain",
    methods: {
        flip () {
            this.isFlip = !this.isFlip;
        }
    },
    data () {
        return {
            isFlip: false
        }
    }
}
</script>
<style lang="css">
.test {
    display: flex; justify-content: center; align-items: center;
    width: 400px; height: 400px;
    font-size: 2.5rem; font-weight: 600; color: #fff;
    background-color: #fff;
    perspective: 450px;
}
.card {
    position: relative;
    width: 200px; height: 200px;
    background-color: #fff; cursor: pointer;
    transform-style: preserve-3d;
    transition: transform 1300ms ease-in-out;
}
.card.flip {
    transform: rotateY(180deg)
}
.front, .back{
    display: flex; justify-content: center; align-items: center;
    position: absolute; width: 100%; height: 100%; 
}
.front {
    z-index: 1; 
    background-color: orange; 
    backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -webkit-backface-visibility: hidden;
}
.front::before { content: "Front"; }
.back::before { content: "Back"; }
.back {
    z-index: 0; width: 100%; height: 100%;
    transform: rotateY(180deg); 
    background-color: tomato;
}
@keyframes show_hide { from { visibility: visible; } to { visibility: hidden; } }
.front-leave { background-color: red; }
.front-leave-active { animation: show_hide 650ms 650ms; background-color: orange; }
.front-leave-to { background-color: blue; color: green; }
.front-enter { background-color: black; }
.front-enter-active { animation: show_hide 650ms 650ms reverse; background-color: orange; }
.front-enter-to { background-color: purple; }
/* ---- */
.back-enter { background-color: black; }
.back-enter-active { animation: show_hide 650ms 650ms reverse; background-color: tomato; }
.back-enter-to { background-color: purple; }
.back-leave { background-color: red; }
.back-leave-active { animation: show_hide 650ms 650ms; background-color: tomato; }
.back-leave-to { background-color: blue; color: green; }
</style>
 
test-main.vue
COPY
EXPAND

Webpack + VueJS 学习、跳坑和总结的更多相关文章

  1. VueJs 学习笔记

    VueJs学习笔记 参考资料:https://cn.vuejs.org/ 特效库:TweenJS(补间动画库)  VelocityJS(轻量级JS动画库) Animate.css(CSS预设动画库) ...

  2. 两百条微信小程序跳坑指南(不定时更新)

    微信小程序联盟出品 跳坑textarea<二百二十三>不显示文本及textarea相关问题集合跳坑<二百一十三> background-image无法获取本地资源图片....跳 ...

  3. vuejs学习——vue+vuex+vue-router项目搭建(二)

    前言 最近比较忙,所有第二章发布晚了,不好意思各位. vuejs学习——vue+vuex+vue-router项目搭建(一) 中我们搭建好了vue项目,我相信大家已经体验了vue其中的奥妙了,接下来我 ...

  4. vuejs学习之 项目打包之后的首屏加载优化

    vuejs学习之 项目打包之后的首屏加载优化 一:使用CDN资源 我们在打包时,会将package.json里,dependencies对象里插件打包起来,我们可以将其中的一些使用cdn的方式加载,例 ...

  5. 小程序红包开发跳坑记 微信小程序红包接口开发过程中遇到的问题 微信小程序红包开发

    现在做小程序的越来越多,商家推广也是一个瓶颈,谁不发点红包,都很难找到人来用你的微信小程序了.于是不管你开发什么小程序功能,你或多或少都要用到小程序来发红包吧.  我们自己之前做公众号发红包,做了两三 ...

  6. JavaScript 跳坑指南

    JavaScript 跳坑指南 坑0-String replace string的replace方法我们经常用,替换string中的某些字符,语法像这样子 string.replace(subStr/ ...

  7. WebPack 简明学习教程

    WebPack 简明学习教程 字数1291 阅读22812 评论11 喜欢35 WebPack是什么 一个打包工具 一个模块加载工具 各种资源都可以当成模块来处理 网站 http://webpack. ...

  8. vuejs学习网站推荐

    vuejs学习网站推荐 https://coligo.io/

  9. Xamarin安装和跳坑指南

    安装Checklist 注意:本文只描述安装过程,由于组件的版本更新很快,为保证文章时效性,不提供下载链接,也尽可能不指明具体版本. 安装Visual Studio 2015进行默认安装,除非已经FQ ...

随机推荐

  1. java调用C# webService发布的接口

    java调用C# webService发布的接口 java调用C# webService方式有很多种我这里只介绍一种 首先需要引入axis的jar包 axis的maven坐标如下 <depend ...

  2. P4719 【模板】"动态 DP"&动态树分治

    题目描述 给定一棵 n 个点的树,点带点权. 有 m 次操作,每次操作给定 x,y,表示修改点 x 的权值为 y. 你需要在每次操作之后求出这棵树的最大权独立集的权值大小. 输入格式 第一行有两个整数 ...

  3. ctf常见源码泄露

    前言 在ctf中发现很多源码泄露的题,总结一下,对于网站的搭建要注意删除备份文件,和一些工具的使用如git,svn等等的规范使用,避免备份文件出现在公网 SVN源码泄露 原理 SVN(subversi ...

  4. webpack做项目优化

    webpack优化 -- compression-webpack-plugin 开启gzip 打包的时候开启gzip可以大大减少体积,非常适合于上线部署.下面以vue-cli2.x项目为例,介绍如何在 ...

  5. 07_Python语法示例(基础语法,文件操作,异常处理)

    1.写程序在终端输出图形 ######## # # # # ######## print("#" * 8) print("#" + " " ...

  6. 用Maven给一个Maven工程打包,使用阿里云镜像解决mvn clean package出错的问题,使用plugin解决没有主清单属性的问题

    本来在STS里做了一个极简Maven工程,内中只有一个Main方法的Java类,然后用新装的Maven3.6.3给它打包. 结果,Maven罢工,输出如下: C:\personal\programs\ ...

  7. Netty内置的编解码器和ChannelHandler

    Netty 为许多通用协议提供了编解码器和处理器,几乎可以开箱即用,这减少了你在那些相当繁琐的事务上本来会花费的时间与精力. 通过SSL/TLS 保护Netty 应用程序 SSL和TLS这样的安全协议 ...

  8. Spring Boot与日志

    目录 1.日志框架 2.市面上的日志框架 2.1 下表行间无任何对应关系 2.2 日志门面:slf4j 2.3 日志实现:logback 2.4 Spring Boot怎么做的呢? 3.slf4j的使 ...

  9. Apache报错:无法使用可靠的服务器域名

    Apache 安装和启动时报错:无法使用可靠的服务器域名,打开Apache配置文件httpd.conf,去除 ServerName 前面的注释即可 1. 报错信息:无法使用可靠的服务器域名 AH005 ...

  10. python基础:多进程、多线程

    一.定义和区别 1.一个任务就是一个进程,进程就是资源的集合.比如打开浏览器,启动一个进程.当一个进程需要干很多事的时候,就需要执行多个子任务,这些子任务就是线程. 2.线程是包含在进程中的,每个进程 ...