一、监听数据变化的三种形式
假设我们需要提供两个输入框,分别输入姓和名,然后自动拼接为姓名。这样,我们就需要监听输入框的数据变化,让完整的姓名跟随输入的变动而变化。我们可以使用以下三种方式:
1、结合DOM事件使用mothod
来监听数据变化
html代码:使用keyup
事件来监听数据的改变。
<div id="app">
<input type="text" v-model="firstname" @keyup="getFullname">
<input type="text" v-model="lastname" @keyup="getFullname">
<input type="text" v-model="fullname">
</div>
js代码:
new Vue({
el: '#app',
data: {
firstname: '',
lastname: '',
fullname: ''
},
methods: {
getFullname(){
this.fullname = (this.firstname + ' ' + this.lastname).trim();
return this.fullname;
}
}
});
2、使用watch
侦听器
类似methods
的使用,我们可以在Vue实例中使用watch
来监听表达式数据的变化,并执行对应的回调函数。
html代码:
<div id="app">
<input type="text" v-model="firstname">
<input type="text" v-model="lastname">
<input type="text" v-model="fullname">
</div>
js代码:
new Vue({
el: '#app',
data: {
firstname: '',
lastname: '',
fullname: ''
},
watch: {
firstname: function(){
this.fullname = (this.firstname + ' ' + this.lastname).trim();
},
lastname: function(){
this.fullname = (this.firstname + ' ' + this.lastname).trim();
}
}
});
可以发现,watch
监听器以要监听的数据表达式作为键,值为处理数据变化后的函数。
3、使用计算属性computed
直接看效果:
html代码不变,注意js代码:
new Vue({
el: '#app',
data: {
firstname: '',
lastname: ''
},
computed: {
fullname: function(){
return (this.firstname + ' ' + this.lastname).trim();
}
}
});
首先去掉了data
中的fullname属性,取而代之的是computed中的fullname属性。计算属性需要返回一个值作为属性值,且能自动监听内部依赖的变化,自动更新属性值,并对值进行存储,以供多次调用。
4、三者的区别
watch
侦听器更像是专门用于监听数据变化的处理方法,但容易造成滥用,而methods
一般用于处理业务逻辑,即相同的逻辑可以直接调用。计算属性很直接,将需要的属性进行计算处理后再进行调用。
二、webpack的简单使用
1、静态资源的处理
对于Web项目来说,包含各式各样的静态资源页面,且格式种类繁多,如:
- js
- css
- image
- 模块&组件
静态资源多而杂的时候,页面加载效率就低,且难以处理好资源之间的依赖关系。
所以我们需要对资源进行整合压缩,对于小图片来说还可以使用图片精灵图(image sprite
)、转码为Base64字节码等。
而依赖关系除了手动处理我们还可以使用一些工具。
而以上问题我们都可以使用webpack
工具进行解决,如文件格式转化、压缩整合等。下面我们将结合Vue来使用webpack
。
2、webpack的配置
场景
请看以下场景:
我们在Node中使用jquery
来改变表格的样式,其中,我们还使用了大多浏览器不支持的es6语法:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
</head>
<body>
<table id="tab" border="1" rules="all">
<thead>
<td>header1</td>
<td>header2</td>
<td>header3</td>
</thead>
<tbody>
<tr>
<td>1</td>
<td>1</td>
<td>1</td>
</tr>
<tr>
<td>2</td>
<td>2</td>
<td>2</td>
</tr>
<tr>
<td>3</td>
<td>3</td>
<td>3</td>
</tr>
<tr>
<td>4</td>
<td>4</td>
<td>4</td>
</tr>
</tbody>
</table>
<script type="text/javascript" src="./dist/main.js"></script>
</body>
</html>
import $ from 'jquery';//es6语法:等价于const $ = require('jquery');
$(function(){
$('#tab > thead').css({
backgroundColor: '#bdccc2'
});
$('#tab > tbody > tr:even').css({
backgroundColor: '#c1f1cd'
});
$('#tab > tbody > tr:odd').css({
backgroundColor: '#f3ffab'
});
});
这样,当我们直接访问这个页面时就会报错。现在我们使用webpack
对mian.js
进行打包处理,并保存到新的目录文件中,如: \dist\bundle.js
在使用之前,我们需要先安装webpack
。
安装
# 全局安装
npm install webpack -g
# 本地开发环境安装
npm install webpack --save-dev
# 4.0以上版本还需要安装
npm install --save-dev webpack-cli
打包
使用命令行工具执行:
webpack ./src/mian.js -o ./dist/bundle.js
然后main.js就会被打包成新的bundle.js文件,我们在页面中引用这个js,就可以看到jquery做出的样式效果:
我们发现,webpack
为我们做了以下几点:
- 打包压缩js文件(main.js)
- 自动处理包之间的依赖(jqurey)
改进:配置文件
我们发现每次都需要在命令行填写输入输出文件路径实在是太麻烦了,且容易出错。所以webpack
提供了一个读取默认名为webpack.config.js
配置文件的功能。在该配置文件中我们可以配置诸多信息,其中就包括文件的入口和出口。
现在,我们在项目的更目录下新建一个名为webpack.config.js
的文件。
//webpack是基于node的,所以配置文件其实就是一个js导出的对象
var path = require('path');
module.exports = {
//入口
entry: path.join(__dirname, '/src/main.js'),
//出口
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js'
}
}
这样,我们就可以直接使用webpack
命令进行打包了。可能我们还不满足于手动加载的方式,就像nodemon
一样,我们希望当我们作出变动时就能及时打包响应,这样我们需要另外安装一个模块:webpack-dev-server
。
再改进:使用webpack-dev-server
热加载
-
安装
# 安装(注意,依赖本地webpack)
npm install web-dev-server --save-dev -
使用
在
package.json
的scripts
中配置一下就能使用了:# 配置到package.json
"dev": "webpack-dev-server"
# 命令行启动
npm run dev -
细节问题
现在我们需要通过
http://localhost:8080
来访问页面。此时如果我们修改并保存main.js,会自动执行打包动作,但我们页面却没有发生变化,这是因为自动编译的出口目录并不是原来那个文件,且不在物理磁盘,而在内存中。默认的路径为根路径,所以/bundle.js
才能访问到自动打包的文件。 -
更多的配置
我们可以修改命令或者在
webpack.config.js
中增加配置来修改一些默认选项。-
使用命令:
# --open 自动打开浏览器访问根目录
# --contentBase ./src 设置访问的根目录为src目录
# --hot 启用热加载
webpack-dev-server --open --contentBase ./src --hot -
使用配置文件也能达到一样的效果
const path = require('path');
const webpack = require('webpack'); module.exports = {
//入口
entry: path.join(__dirname, '/src/main.js'),
//出口
output: {
path: path.join(__dirname, '/dist'),
filename: 'bundle.js'
},
devServer: {
open: true,
contentBase: path.join(__dirname, '/src'),
hot: true //注意,这样配置还不够,因为热更新需要使用到webpack自带的一个插件:模块热替换插件
},
plugins: [
new webpack.HotModuleReplacementPlugin()//启用模块热替换插件
]
}
-
更多关于webpack-dev-server
请参考https://www.webpackjs.com/configuration/dev-server/
3、加载非js文件
webpack
默认只能加载js文件,如果是非js文件则需要使用第三方文件加载模块。
比如我们在main.js
导入我们写的一个css文件main.css
。
-
1、首要我们任意规定一个css样式:
li{
list-style-type: none;
} -
2、然后需要在
main.js
中导入(这是webpack提供的特殊loader模式):import './main.css'
-
3、现在我们只需要配置需要的第三方文件加载模块即可
加载css文件需要两个模块:
style-loader
和css-loader
.npm install style-loader css-loader --dev
修改配置文件,增加配置选项:
module.exports = {
module: {//第三方模块的引用
rules: [//匹配规则 test使用正则表达式来匹配loader的文件类型 use是使用的模块:从后往前加载
{test: /\.css$/, use: ['style-loader', 'css-loader']}
]
}
}注意:这个加载顺序很重要,如果模块之间存在依赖或顺序关系,则需要保证加载顺序从后往前加载。
类似的文件加载是一样的道理。
更多使用细节请参考官方文档