webpack4 - 8.整合jquery等第三方库

2018-09-24  本文已影响655人  yuanzicheng

虽然目前angular/react/vue这些现代化的框架使前端开发模式发生了极大的变化,但是有些东西还是需要依靠我们的老朋友jquery来实现。

1.引入jquery

我们继续使用之前的代码,引入jquery。

1.1 使用import手动引入jquery

安装jquery依赖

npm install jquery

src/js/index/js中引入jquery,使用jquery来修改页面的title内容

import '../css/index.css'
import Vue from 'vue'
import test from '../vue/test.vue'
import $ from 'jquery'
new Vue({
    el: '#test',
    render: h => h(test)
});

$("title").html('title by jquery');

src/vue/test.vue中引入jquery,使用jquery来动态修改div中的内容

<template>
    <div id="demo">
        <h1>Hello,{{msg}}</h1>
        <input type="text" v-model="msg">
        <div id="jquery"></div>
    </div>
</template>
<script>
    import $ from 'jquery'
    export default {
        data () {
            return {
                msg: 'xxx12314`'
            }
        },
        mounted () {
            $("#jquery").html("Hello jQuery!");
        }
    }
</script>
<style scoped>
    #demo {
        background: yellow;
    }
</style>

到这里为止引入jquery的工作就完成了,使用webpack-dev-server打开页面进行测试,看到预期的结果,证明jquery引入成功,能够正常使用。

另外,使用webpack命令进行打包,可以发现在生成的.js文件中,jquery的内容也被包含在内了。

1.2 使用ProvidePlugin自动引入jquery

从上面的例子可以发现,分别在src/js/index.jssrc/vue/test.vue中使用了import来引入jquery,这种方式必须在每个需要引入jquery的文件中写上一句import $ from 'jquery'

ProvidePlugin这个插件可以自动加载模块,无需每处 importrequire 。接下来就用这个插件来试验。

webpack.config.js中添加ProvidePlugin相关配置

const path = require('path');
const webpack = require('webpack');
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
const HtmlWebpackPlugin = require('html-webpack-plugin');
const VueLoaderPlugin = require('vue-loader/lib/plugin');

module.exports = {
    mode: 'production',
    entry: {
        index: './src/js/index.js'
    },
    output: {
        path: path.resolve(__dirname, 'dist'),
        filename: 'js/[name].[hash:8].js'
    },
    module: {
        rules: [
            {
                test: /\.vue$/,
                use: 'vue-loader'
            },
            {
                test: /\.js$/,
                use: 'babel-loader',
                exclude: /node_modules/
            },
            {
                test: /\.css$/,
                use: [
                    {
                        loader: MiniCssExtractPlugin.loader,
                        options: {
                            publicPath: '../'  // 特别重要,否则css文件打包后其中引用的图片文件不正确
                        }
                    },
                    "css-loader"
                ]
            },
            {
                test: /\.html$/,
                use: {
                    loader: 'html-loader'
                }
            },
            {
                test: /\.(png|jpg|gif|jpeg|svg)$/,
                use:[
                    {
                        loader: "url-loader",
                        options: {
                            name: "img/[name].[hash:5].[ext]",
                            limit: 1024, // size <= 1kib
                            // outputPath: "img",
                            publicPath: "../"
                        }
                    }
                ]
            }
        ]
    },
    plugins: [
        new MiniCssExtractPlugin({
            filename: "css/[name].[hash:8].css",
        }),
        new HtmlWebpackPlugin(
            {
                template: './src/page/index.html',
                filename:'./page/index.html',
                hash: false,
                chunks: ['index']
            }
        ),
        new VueLoaderPlugin(),
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery'
        })
    ],
    devServer: {
        contentBase: path.resolve(__dirname, "../dist/"),
        index:'./page/index.html'
    }
};

去除src/js/index.jssrc/vue/test.vue中的import $ from 'j query'

使用webpck-dev-server打开页面后jquery相关的效果依然存在,并且检查页面资源,发现原来的js文件中依然有jquery相关代码,说明使用ProvidePlugin能够实现模块自动加载。

前面的文章中使用了import Vue from 'vue'来引入vue.js,有了ProvidePlugin之后,vue.js也可以用它来动态引入

new webpack.ProvidePlugin({
  Vue: ['vue/dist/vue.esm.js', 'default']
});

2.引入jquery插件

这里以iziToastiziModal这两个基于jquery的弹出框插件为例。

iziToast.png iziModal.png

顺便吐槽一下,市面上一些的UI组件中的对话框真的丑,而且功能少,还有bug!(iView中的Modal全屏模式在中小尺寸的屏幕上显示错乱的问题到了3.x版本一直都没解决,之前的项目中用到了这个,能力有限自己解决不了bug,无奈只能改设计方案,放弃了全屏窗口的功能。)


iView-Modal.png

废话不多说了,基于前文的项目代码,开始引入插件。

安装插件

npm install --save izitoast izimodal

webpack.config.js中配置自动加载插件

module.exports = {
    mode: 'development',
    entry: {
        index: './src/js/index.js'
    },
    output: {
        ...
    },
    module: {
        ...
    },
    plugins: [
        ...
        new webpack.ProvidePlugin({
            $: 'jquery',
            jQuery: 'jquery',
            Vue: ['vue/dist/vue.esm.js', 'default'],
            iziToast: 'izitoast',
            iziModal: 'izimodal'
        })
    ],
    devServer: {
        ...
    }
};

这里我们在vue组件中使用这两个插件,新增一个.vue文件
src/vue/izi.vue(点击两个链接,分别弹出iziToast和iziModal)

<template>
    <div>
        <a href="#" @click="toast">iziToast</a>
        <a href="#" class="trigger">iziModal</a>
        <div id="modal">
            <p>1</p>
            <p>2</p>
        </div>
    </div>
</template>
<script>
    export default {
        data () {
            return {}
        },
        mounted () {
            $.fn.iziModal = iziModal;
            $("#modal").iziModal({
                title: 'AAAAAAAA',
                subtitle: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
                headerColor: 'yellowgreen',
                fullscreen: true
            });
            $(document).on('click', '.trigger', function (event) {
                event.preventDefault();
                $('#modal').iziModal('open');
            });
        },
        methods: {
            toast () {
                iziToast.show({
                    title: 'Hey',
                    message: 'What would you like to add?'
                });
            }
        }
    }
</script>
<style scoped>
</style>

index.htmlindex.js稍作修改,去除无关的代码
src/page/index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<div id="app">
    <izi></izi>
</div>
</body>
</html>

src/js/index.js(引入插件相关的css及自己定义的vue组件)

import 'izitoast/dist/css/iziToast.min.css'
import 'izimodal/css/iziModal.min.css'
import izi from '../vue/izi.vue'
new Vue({
    el: '#app',
    components: {izi}
});

使用webpack-dev-server打开页面后,点击两个链接,iziToast和iziModal均能正常显示,插件初步引入成功。

izi.png

但是,别高兴得太早!我们在<div id="modal"></div>中加入一些vue.js的代码

<template>
    <div>
        <a href="#" @click="toast">iziToast</a>
        <a href="#" class="trigger">iziModal</a>
        <div id="modal">
            <h1>Hello,{{ msg }}</h1>
            <input name="msg" type="text" v-model="msg">
        </div>
    </div>
</template>

<script>中的data加入一项msg

<script>
    export default {
        data () {
            return {
                msg: 'xxxx'
            }
        },
        mounted () {
            ...
        },
        methods: {
            ...
        }
    }
</script>

重新打开弹出框,在其中的输入框填入任意的内容,What?<h1>标签中的msg内容居然没有一起改变,说明经过iziModal初始化后的vue.js相关功能已经失效了!这个问题在github已经存在issue#115afterRender这个选项能够提供一些补救措施,但是依然不能在iziModal中直接使用vue.js。本人能力有限,暂时不在这里白费力气了,目前只能退而求其次不在iziModal中使用vue.js了,或者不使用iziModal。

$("#modal").iziModal({
    title: 'AAAAAAAA',
    subtitle: 'bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb',
    headerColor: 'lightcoral',
    fullscreen: true,
    afterRender: function() {
        $('input[name="msg"]').on('change', function () {
        });
    }
});
上一篇下一篇

猜你喜欢

热点阅读