webpack4 - 8.整合jquery等第三方库
虽然目前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.js
和src/vue/test.vue
中使用了import来引入jquery,这种方式必须在每个需要引入jquery的文件中写上一句import $ from 'jquery'
。
ProvidePlugin这个插件可以自动加载模块,无需每处 import
或 require
。接下来就用这个插件来试验。
在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.js
及src/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插件
这里以iziToast
和iziModal
这两个基于jquery的弹出框插件为例。
顺便吐槽一下,市面上一些的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.html
、index.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均能正常显示,插件初步引入成功。
但是,别高兴得太早!我们在<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#115,afterRender
这个选项能够提供一些补救措施,但是依然不能在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 () {
});
}
});