10 watch和computed
computed计算属性
我们可以将同一函数定义为一个方法而不是一个计算属性。两种方式的最终结果确实是完全相同的。然而,不同的是计算属性是基于它们的依赖进行缓存的。只在相关依赖发生改变时它们才会重新求值。这就意味着只要 message
还没有发生改变,多次访问 reversedMessage
计算属性会立即返回之前的计算结果,而不必再次执行函数。
我们为什么需要缓存?假设我们有一个性能开销比较大的计算属性 A,它需要遍历一个巨大的数组并做大量的计算。然后我们可能有其他的计算属性依赖于 A 。如果没有缓存,我们将不可避免的多次执行 A 的 getter!如果你不希望有缓存,请用方法来替代。
computed: {
now: function () {
return Date.now()
}
}
侦听属性
Vue 提供了一种更通用的方式来观察和响应 Vue 实例上的数据变动:侦听属性。当你有一些数据需要随着其它数据变动而变动时,你很容易滥用 watch
——特别是如果你之前使用过 AngularJS。然而,通常更好的做法是使用计算属性而不是命令式的 watch
回调。细想一下这个例子:
<div id="demo">{{ fullName }}</div>
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar',
fullName: 'Foo Bar'
},
watch: {
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
lastName: function (val) {
this.fullName = this.firstName + ' ' + val
}
}
})
上面代码是命令式且重复的。将它与计算属性的版本进行比较:
var vm = new Vue({
el: '#demo',
data: {
firstName: 'Foo',
lastName: 'Bar'
},
computed: {
fullName: function () {
return this.firstName + ' ' + this.lastName
}
}
})
好得多了,不是吗?
计算属性默认只有 getter ,不过在需要时你也可以提供一个 setter :
computed: {
fullName: {
// getter
get: function () {
return this.firstName + ' ' + this.lastName
},
// setter
set: function (newValue) {
var names = newValue.split(' ')
this.firstName = names[0]
this.lastName = names[names.length - 1]
}
}
}
现在再运行 vm.fullName = 'John Doe'
时,setter 会被调用,vm.firstName
和 vm.lastName
也会相应地被更新。
11 安装webpack
安装webpack首先需要nodjs的环境
安装nodejs
1.下载地址
https://nodejs.org/en/
2.运行安装包,选择相关的路径,主要注意点如下选择add to path,因为这样会自动给你配置对应的环境变量,其余的都是直接下一步下一步然后install
3.检验是否安装成功,执行两个命令node -v
和npm -v
(这个主要高版本的nodejs
会在安装的过程中自动帮你安装的,主要的作用是对Node.js
依赖的包进行管理,也可以理解为用来安装/卸载Node.js
需要装的东西) 分别查看版本信息
Nodejs使用前的准备工作
1.在安装目录D:\Program Files\nodejs
下创建两个文件夹node_global
和node_cache
,主要防止执行其他安装命令时候将东西安装在C
盘里面,希望将全模块所在路径和缓存路径放在我node.js
安装的文件夹中。
2.新建文件后在执行命令行
cmd
,然后执行下面两个语句
npm config set prefix "D:\Program Files\nodejs\node_global"
npm config set cache "D:\Program Files\nodejs\node_cache"
3.接下来设置环境变量,关闭
cmd
窗口,“我的电脑”-右键-“属性”-“高级系统设置”-“高级”-“环境变量”,系统变量下新建NODE_PATH
,填写好对应的路径修改默认的用户变量
D:\Program Files\nodejs\node_global
测试一下
配置完后,安装个module
测试下,我们就安装最常用的express
模块,打开cmd
窗口,
输入如下命令进行模块的全局安装:
npm install express -g # -g是全局安装的意思
安装nrm
命令
npm install nrm -g
设置镜像地址为taobao
镜像
nrm ls #查看镜像地址
nrm use taobao #切换到淘宝镜像
安装webpack1.14.0版本
npm install webpack@1.14.0 -g
Webpack常用指令和wabpack.config.js配置文件
- webpack常用指令
webpack 入口文件.js 输出文件.js
webpack //最基本的启动webpack的方法,默认查找名为webpack.config.js文件
webpack --config webpack.config.js //指定配置文件
webpack -p //对打包后的文件进行压缩
webpack -d //提供source.map,方便调试代码
-
webpack配置文件
webpack配置文件打包方式需要新建一个dist目录用于存放打包后的配置文件
src中存放需要打包的文件及入口js文件main.js
,在入口文件中使用的文件会被打包
webpack.config.js文件
module.exports={
entry:'./src/main.js',//指定打包的入口文件
output:{//配置输出
path:__dirname + '/dist',//注意:webpack1.14.0要求这个路径是一个绝对路径
filename:'build.js'
}
}
11.1 webpack相关配置
在使用loader之前需要在当前目录下打开cmd命令面板,输入:
nmp init
初始化一个package.json文件在存放相关的文件
11.1.1 打包css资源演示
wabpack中使用css-loader和style-loader这两个loader来处理css资源的打包工作,所以使用前必须在项目中安装这两个包:
npm i css-loader style-loader --save-dev
- 在webpack.config.js中配置这两个loader
css-loader:只负责加载css模块,不会将加载的css样式应用到html
style-loader:负责将css-loader加载到的css样式动态的添加到html-head-style标签中
在webpack.config.js中添加处理css文件的loader配置:
module.exports={
entry:'./src/main.js',//指定打包的入口文件
output:{//配置输出
path:__dirname + '/dist',//注意:webpack1.14.0要求这个路径是一个绝对路径
filename:'build.js'
},
module:{
loaders:[
{
test:/\.css$/,//以css结尾的文件
loader:'style-loader!css-loader'//使用!作为分隔符
}
]
}
}
在执行webpack命令,重新打包输出文件,打包好以后css就被打包到了build.js
文件中,只要引入build.js
文件css
样式就会生效
11.2 打包less文件
安装less
和less-loader
cnpm install less less-loader style-loader css-loader --save-dev
在./statics/css/
目录下新建一个less文件:site2.less
@color:green;
#res{
border: 3px solid @color;
}
在入口文件main.js中导入less文件:
//导入less文件
require('../statics/css/site2.less')
使用webpack
打包即可预览到效果
11.3webpack打包url()请求的资源
- 需要安装的node包有:
url-loader:打包通过url方式请求的资源
file-loader:url-loader的依赖loader
在项目根目录下打开cmd输入:
npm install url-loader file-loader --save-dev
- 在webpack.config.js文件中配置这两个loader
{
test: /\.(png|jpe?g|gif|svg|ttf|bmp)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1000,
name: 'img/[name].[hash:7].[ext]'
}
}
在css文件中使用图片资源
#bg{
width: 300px;
height: 300px;
background: url(../img/AIMP.png);
}
在webpack打包即可
11.4 利用webpack-dev-server实现热刷新配置
我们在修改了代码以后需要不断的重新执行webpack命令重新打包然后回到浏览器刷新页面查看,这种开发效率低下,所以这里使用weboack-dev-server当代码更新的时候自动刷新浏览器。
需要安装的node包有:
- webpack@1.14.0:webpack-dev-server依赖与webpack
- webpack-dev-server@1.16.0 :webpack开发服务器
- html-webpack-plugin : 结果webpack在内存中自动生成index.html的入口文件
安装(前提有node环境):
cnpm install webpack@1.14.0 webpack-dev-server@1.16.0 html-webpack-plugin --save-dev
在package.json文件中配置webpack-dev-server命令
"script": {
"dev":"webpack-dev-server --inline --hot --open --port 4009"
}
参数说明:
- --inline:自动刷新
- --hot :热加载
- --port : 指定监听端口号为4009
- --open : 指定在默认浏览器中打开
- --host : 可以指定服务器的ip,不指定默认为127.0.0.1(localhost)
配置html-wabpack-plugin组件
webpack-dev-server要实现浏览器自动刷新,必须要利用html-webpack-plugin在内存中生成index.html页面才能实现,html-webpack-plugin配置步骤:
- 1.在webpack.config.js文件中加入如下代码:
//导入html-webpack-plugin包获取到插件对象
var htmlwp = require('html-webpack-plugin');
plugins:[
new htmlwp({
title:'首页',//生成的页面标题
filename:'index.html',//webpack-dev-server在内存中生成的文件名称,自动将build.js注入到这个页面底部
template:'index1.html'//更具index1.html这个模板生成(这个文件由程序员自己定义)
})
]
运行
在控制台执行:
npm run dev
就会开启webpack-dev-server服务器来运行vue项目,这时候随便修改一个css样式,就会自动刷新看到效果。
webpack.config.js完整示例配置:
var htmlwp = require('html-webpack-plugin');
module.exports={
entry:'./src/main.js',//指定打包的入口文件
output:{//配置输出
path:__dirname + '/dist',//注意:webpack1.14.0要求这个路径是一个绝对路径
filename:'build.js'
},
module:{
loaders:[
{
test:/\.css$/,//以css结尾的文件
loader:'style-loader!css-loader'//使用!作为分隔符
},
{
test:/\.less$/,//以less结尾的文件
loader:'style-loader!css-loader!less-loader'
},
{
test: /\.(png|jpe?g|gif|svg|ttf|bmp)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1000,
name: 'img/[name].[hash:7].[ext]'
}
}
]
},
plugins:[
new htmlwp({
title:'首页',//生成的页面标题
filename:'index.html',//webpack-dev-server在内存中生成的文件名称,自动将build.js注入到这个页面底部
template:'index1.html'//更具index1.html这个模板生成(这个文件由程序员自己定义)
})
]
}
11.5ECMAScript6语法转ECMAScript5语法
需要安装的node包有:
- babel-core
- babel-loader
- babek-plugin-trabsform-runtime:这个包主要是打包.vue组件页面中的es6语法需要
在项目目录下打开cmd命令面板输入:
npm install babel-core babel-loader@6.4.1 babel-preset-es2015 babel-plugin-transform-runtime --save-dev
- 在webpack-config.js中配置这两个loader
loaders:[{
//将当前项目中所有的.js文件都要进行es6转es5操作,node_moudels除外
test:/\.js$/,//表示当前打包的文件后缀的正则表达式
//loader:'babel-loader?presets[]=es2015',//如果写到这里将来在打包.vue文件的时候会报错,表示先利用css-loader解析.css文件,在调用style-loader打包
loader:'babel-loader',
exclude:/node_modules/ //node_modules中的所有.js文件不去转换,提高打包性能
}],
babel:{
presets:['es2015'],
plugins:['transform-runtime']//这句代码就是为了解决打包.vue文件不报错
}
完整的配置为:
module.exports = {
entry: './src/main.js', //指定打包的入口文件
output: { //配置输出
path: __dirname + '/dist', //注意:webpack1.14.0要求这个路径是一个绝对路径
filename: 'build.js'
},
module: {
loaders: [{
test: /\.css$/, //以css结尾的文件
loader: 'style-loader!css-loader' //使用!作为分隔符
},
{
test: /\.less$/, //以less结尾的文件
loader: 'style-loader!css-loader!less-loader'
},
{
test: /\.(png|jpe?g|gif|svg|ttf|bmp)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1000,
name: 'img/[name].[hash:7].[ext]'
}
},
{
//将当前项目中所有的.js文件都要进行es6转es5操作,node_moudels除外
test: /\.js$/, //表示当前打包的文件后缀的正则表达式
//loader:'babel-loader?presets[]=es2015',//如果写到这里将来在打包.vue文件的时候会报错,表示先利用css-loader解析.css文件,在调用style-loader打包
loader: 'babel-loader',
exclude: /node_modules/ //node_modules中的所有.js文件不去转换就是排除,提高打包性能
}
]
},
babel: {
presets: ['es2015'],
plugins: ['transform-runtime'] //这句代码就是为了解决打包.vue文件不报错
},
plugins: [
new htmlwp({
title: '首页', //生成的页面标题
filename: 'index.html', //webpack-dev-server在内存中生成的文件名称,自动将build.js注入到这个页面底部
template: 'index1.html' //更具index1.html这个模板生成(这个文件由程序员自己定义)
})
]
}
- 在main.js中使用es6语法导入site.css
import '../statics/css/site.css'
各依赖版本:
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^6.4.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"css-loader": "^0.28.11",
"file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0",
"less": "^3.0.4",
"less-loader": "^4.1.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.0"
}
11.6利用webpack解析和打包.vue组件页面
Vue项目中的每个页面其实都是一个.vue的文件,这种文件,Vue称之为组件页面,必须借助于webpack的vue-loader才能使用
所以必须安装相关包:
vue : vuejs核心包
vue-loader : .vue文件编译loader
babel-plugin-transform-runtime : es6实时转成es5语法
1.在项目根目录下打开cmd命令面板,输入:
npm install vue-loader vue-template-compiler babel-plugin-transform-runtime --save-dev
npm install vue --save
2.在webpack.config.js中添加如下配置(只能在webpack1.0中使用):
babel:{
presets:['es2015'],
plugins:['transform-runtime']//这句话就是为了解决打包.vue文件不报错
}
在webpack2.0中在webpack.config.js文件中添加babel:{}是不认识的要改写如下方式:
在项目根目录下新建.babelrc文件,内容填写如下:
{
presets:['es2015'],
plugins:['transform-runtime']//这句话就是为了解决打包.vue文件不报错
}
3.在webpack.config.js的loader中增加
{
//打包
test:/\.vue$/,
loader:'vue-loader'
}
12 搭建webpack1.14.0+Vue2.6.0的HelloWorld
App.vue文件
<!-- 以后项目的根组件 -->
<template>
<!-- 主要放html页面结构 -->
<div>
<span v-text="message" class="red"></span>
</div>
</template>
<script>
// 负责到处.vue这个组件对象(它的本质是一个vue对象,所以vue中该定义的元素都可以使用)
export default{
data(){//等价于es5的data:function(){}c
return {
message:'Hello VueJs!!'
}
},
methods: {
},
created(){
}
}
</script>
<style scoped>
/* 当前页面的css样式写到这里,其中scoped表示这个里面的css代码只是在当前组件页面有效,不会去影响到其他组件页面 */
.red{
color:red;
}
</style>
main.js文件
//导入vue核心包
import Vue from 'vue';
//导入App.vue的vue对象
import App from './App.vue';
//利用vue对象进行渲染
new Vue({
el:'#app',
// render:function(create){
// create(App)
// }es5写法
render:create=>create(App) //es6箭头函数写法也称goes to 语法,左边参数右边方法体
});
index.html模板index1.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no" />
<title>首页</title>
</head>
<body>
<div id="app">
</div>
</body>
</html>
web.config.js文件
var htmlwp = require('html-webpack-plugin');
module.exports = {
entry: './src/main.js', //指定打包的入口文件
output: { //配置输出
path: __dirname + '/dist', //注意:webpack1.14.0要求这个路径是一个绝对路径
filename: 'build.js'
},
module: {
loaders: [{
test: /\.css$/, //以css结尾的文件
loader: 'style-loader!css-loader' //使用!作为分隔符
},
{
test: /\.less$/, //以less结尾的文件
loader: 'style-loader!css-loader!less-loader'
},
{
test: /\.(png|jpe?g|gif|svg|ttf|bmp)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 1000,
name: 'img/[name].[hash:7].[ext]'
}
},
{
//将当前项目中所有的.js文件都要进行es6转es5操作,node_moudels除外
test: /\.js$/, //表示当前打包的文件后缀的正则表达式
//loader:'babel-loader?presets[]=es2015',//如果写到这里将来在打包.vue文件的时候会报错,表示先利用css-loader解析.css文件,在调用style-loader打包
loader: 'babel-loader',
exclude: /node_modules/ //node_modules中的所有.js文件不去转换就是排除,提高打包性能
},
{
//打包
test: /\.vue$/,
loader: 'vue-loader'
}
]
},
babel: {
presets: ['es2015'],
plugins: ['transform-runtime'] //这句代码就是为了解决打包.vue文件不报错
},
plugins: [
new htmlwp({
title: '首页', //生成的页面标题
filename: 'index.html', //webpack-dev-server在内存中生成的文件名称,自动将build.js注入到这个页面底部
template: 'index1.html' //更具index1.html这个模板生成(这个文件由程序员自己定义)
})
]
}
package.json文件
{
"name": "package",
"version": "1.0.0",
"description": "",
"main": "webpack.config.js",
"scripts": {
"dev": "webpack-dev-server --inline --hot --open --port 4009"
},
"author": "guqing",
"license": "ISC",
"dependencies": {
"vue": "^2.6.4"
},
"devDependencies": {
"babel-core": "^6.26.3",
"babel-loader": "^6.4.1",
"babel-plugin-transform-runtime": "^6.23.0",
"babel-preset-es2015": "^6.24.1",
"css-loader": "^0.28.11",
"file-loader": "^1.1.11",
"html-webpack-plugin": "^3.2.0",
"less": "^3.0.4",
"less-loader": "^4.1.0",
"style-loader": "^0.23.1",
"url-loader": "^1.1.2",
"vue-loader": "^10.0.2",
"vue-template-compiler": "^2.6.4",
"webpack": "^1.14.0",
"webpack-dev-server": "^1.16.0"
}
}
13 项目中使用的ECMAScript6语法
- 1.对象的写法
es5中对象:
{
add:add,
substrict:substrict
}
es6中对象:
{
add,
substrict
}
注意这种写法的属性名和值变量是同一个名称才可以简写,否则要写成es5那样
- 2.在对象中的方法写法
es5中对象:
{
add:function(){},
substrict:function(){}
}
es6中对象:
{
add(){},
substrict(){}
}
3.对象的到出写法
es5两种形式:
module.exports = function(){}
exports.add = function(){}
es6中写法:
1.export defaut{
add(){}
}
2.export function add(){}//相当于将add方法当作一个属性挂载到exports对象
4.对象的导入
es5:
var add = require('./calc.js');
es6:
如果导出的是:
export default{
add(){}
}
那么可以通过
import obj from './calc.js'导入
如果到处的是:
export function add(){}
export function substrict(){}
export const PI=3.14
那么可以通过按需加载
import {add,substrict,PI} from './calc.js'
5.es6中的箭头函数的写法
箭头的演变过程:
[2,1,3].sort(function(x,y){return y-x;})
用箭头函数实现=>读 goes to
[2,1,3].sort((x,y)=>{return y-x});
[2,1,3].sort((x,y)=>{return x++;y++;y-x});
[2,1,3].forEach(x=>{console.log(x)});
14 webpack项目中集成vue-router步骤
1.安装vue-router:
npm install vue-router --save
2.在webpack打包入口js文件中(entry指定的哪个文件main.js)配置如下:
//1.导入vue核心包
import Vue from 'vue';
//2.导入App.vue的vue对象
import App from './App.vue';
//3.导入路由vue-router
import VueRouter from 'vue-router';
//4.将VueRouter绑定到Vue对象上
Vue.use(VueRouter);
//6.导入路由规则需要的组件对象
import login from './components/account/login.vue';
import regist from './components/account/regist.vue';
//5.定义路由规则
var router = new VueRouter({
routes:[//重点在这里是routes而不是routers没有r,否则<router-view>标签是真的不会显示的
{path:'/login',component:login},
{path:'/regist',component:regist}
]
})
//利用vue对象进行渲染
new Vue({
el:'#app',
//使用路由对象实例
router,
// render:function(create){
// create(App)
// }es5写法
render:create=>create(App) //es6箭头函数写法也称goes to 语法,左边参数右边方法体
});
App.vue文件
<!-- 以后项目的根组件 -->
<template>
<!-- 主要放html页面结构 -->
<div>
<!-- <span v-text="message" class="red"></span> -->
<router-link to="/login">登陆</router-link>
<span>|</span>
<router-link to="/regist">|注册</router-link>
<!-- 路由占位符 -->
<router-view></router-view>
</div>
</template>
<script>
// 负责到处.vue这个组件对象(它的本质是一个vue对象,所以vue中该定义的元素都可以使用)
export default{
data(){//等价于es5的data:function(){}c
return {
message:'Hello VueJs!!'
}
},
methods: {
show
},
created(){
}
}
function show(){
alert("你看见我了");
}
</script>
<style scoped>
/* 当前页面的css样式写到这里,其中scoped表示这个里面的css代码只是在当前组件页面有效,不会去影响到其他组件页面 */
.red{
color:red;
}
</style>
在component/account/下写login.vue文件
<template>
<div>
<h1>登陆组件页面</h1>
</div>
</template>
<script>
export default{
}
</script>
<style scoped>
</style>
在component/account/下写regist.vue文件
<template>
<div>
<h1>注册组件页面</h1>
</div>
</template>
<script>
export default{
}
</script>
<style scoped="scoped">
</style>
15Vue移动组件mint-ui使用
vue拥有很多的第三方开发的PC端或者移动端UI组件,此项目中主要用到了Vue移动端组件:mint-ui
类似的移动端组件还有:
- 1.vux
- 2.淘宝团队开发的:SUI
- 3.muse-ui
PC端组件:
- 1.饿了么团队开发的:element
http://element-cn.eleme.io/#/zh-CN/component/collapse
- 2.iView是一套基于Vue.js的开源UI组件库,主要用于服务PC界面中的后台产品
mint-ui资源介绍
下载地址:
https://github.com/ElemeFE/mint-ui
2.官网:
http://mint-ui.github.io/#!/zh-cn
3.文档地址:
http://mint-ui.github.io/docs/#/
安装mint-ui集成到项目中
1.安装:
cnpm install mint-ui --save #命令将mint-ui安装到项目中
2.在main.js中全局导入mint-ui和它的css后即可在任何组件中使用mint-ui组件了
//6导入mint-ui的css文件
import 'mint-ui/lib/style.min.css'
//7.导入mint-ui组件对象
import Mint from 'mint-ui'
//8在Vue中使用Mint
Vue.use(Mint)
16.MUI介绍
官网
http://dev.dcloud.net.cn/mui/
文档地址
http://dev.dcloud.net.cn/mui/ui/
github地址
https://github.com/dcloudio/mui
直接使用git克隆项目到本地然后查看
mui/examples/hello-mui
目录中的实例,复制代码使用,dist目录中是需要的js和css
使用时在入口文件中导入
import '../statics/mui/css/mui.css';
使用:例如使用mui的九宫格样式
<!-- 九宫格 -->
<div class="mui-content gridview">
<ul class="mui-table-view mui-grid-view mui-grid-9">
<li class="mui-table-view-cell mui-media mui-col-xs-2 mui-col-sm-5" v-for="item in gridviews" :key="item.id">
<a href="#">
<!-- <span class="mui-icon mui-icon-home"></span> -->
<img class="gridIcon" :src="item.icon" width="34px" height="34px">
<div class="mui-media-body">{{item.title}}</div>
</a>
</li>
</ul>
</div>