Vue基础及应用
简介
Vue是一套用于构建用户界面的渐进式框架,核心是一个采用简洁的模板语法来声明式地将数据渲染进DOM的系统。
基础用法
1. 起步
Vue 的两个核心功能:
-
声明式渲染:Vue 基于标准 HTML 拓展了一套模板语法,让我们可以声明式地描述最终输出的 HTML 和 JavaScript 状态之间的关系。
-
响应式:Vue会自动跟踪 JavaScript 状态变化并在改变发生时响应式地更新 DOM。
代码示例:
<div id="app">
{{ message }}
</div>
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
运行结果:
Vue可以将数据和DOM进行关联,使我们不再和HTML直接交互。
该示例通过"el: '#app'"将Vue挂载到div元素上,HTML使用“Mustache”语法 (双大括号)进行数据绑定,div中message的取值即为vue中data.message的值,修改data.message的值页面显示的内容就会发生变化。
2.v-bind
除了文本插值,还可以v-bind来绑定元素attribute
<div id="app">
<button type="button" v-bind:disabled="isDisabled">测试按钮</button>
</div>
var app1 = new Vue({
el: '#app',
data: {
isDisabled:true
}
})
运行结果:
Vue将这个button元素的disabled attribute和Vue实例的data.isDisabled进行了绑定,data.isDisabled值为true所以按钮不可以,如果将data.isDisabled的值改为false则按钮会变为可用
v-bind还可以简写成只使用冒号“:”,日常项目中建议使用简写
简写代码:
<div id="app-1">
<button type="button" :disabled="isDisabled">测试按钮</button>
</div>
除了可以绑定data,还可以绑定方法
<div id="app">
<button type="button" :disabled="checkDisabled">测试按钮</button>
</div>
var vm = new Vue({
el: '#app',
data: {
},
methods: {
checkDisabled() {
if(Math.random() > 0.5) {
return true
} else {
return false
}
}
}
})
取值为绑定方法的返回值,如果Math.random()随机出的数字大于0.5则返回true,运行结果为:
3.v-model
v-model用于实现双向数据绑定。
双向数据绑定:数据不仅能从data流向页面,还可以从页面流向data
代码示例:
<div id="app-3">
<p>{{ message }}</p>
<input v-model="message">
</div>
var app3 = new Vue({
el: '#app-3',
data: {
message: ''
}
})
运行结果:
初始只有一个文本输入框
当在输入框输入内容后
该示例使用v-model将input输入框和message进行了绑定,在输入框进行输入操作,输入框改变了message的值,从而改变p元素显示的内容
4.v-on
用 v-on
指令监听 DOM 事件,并在触发时运行对应方法
代码示例:
<div id="app-2">
<p>{{ message }}</p>
<button v-on:click="reverseMessage">反转消息</button>
</div>
var app2 = new Vue({
el: '#app-2',
data: {
message: 'Hello Vue.js!'
},
methods: {
reverseMessage: function () {
this.message = this.message.split('').reverse().join('')
}
}
})
运行结果:
点击按钮后:
该示例通过v-on绑定了click事件和reverseMessage方法,点击“反转消息”按钮后会触发click事件并执行reverseMessage方法,reverseMessage方法将message文本反转并重新赋值给message,从而改变了p元素显示的内容
v-on还可以简写成"@",日常项目中建议使用简写
简写代码:
5.v-if
v-if用于条件判断,同时还可以配合v-else-if和v-else指令给v-if添加一个"else if"、"else"代码块
代码示例:
<div id="app4">
<div v-if="type === 'A'">
A
</div>
<div v-else-if="type === 'B'">
B
</div>
<div v-else-if="type === 'C'">
C
</div>
<div v-else>
Not A/B/C
</div>
</div>
var app4 = new Vue({
el: '#app',
data: {
type: 'C'
}
})
运行结果:
如果将type的值改为E,则运行结果如下:
6.v-for
v-for用于循环遍历数组,v-for指令需要以 site in sites 形式的特殊语法,sites 是源数据数组,site是数组元素迭代的别名
代码示例:
<div id="app-5">
<ol>
<li v-for="item in todos">
{{ item.text }}
</li>
</ol>
</div>
var app5 = new Vue({
el: '#app-5',
data: {
todos: [
{ text: '学习 JavaScript' },
{ text: '学习 Vue' },
{ text: '整个牛项目' }
]
}
})
运行结果:
7.watch
vue提供了监听属性watch,可以通过watch来监听数据的变化
代码示例:
<!DOCTYPE html>
<html>
<head>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
</head>
<body>
<div id="watch_props">
千米 : <input type="text" v-model="kilometers">
米 : <span>{{ meters }}</span>
</div>
<script type="text/javascript">
var vm = new Vue({
el: '#watch_props',
data: {
kilometers: 0,
meters: 0
},
watch: {
kilometers: function (newValue, oldValue) {
this.meters = newValue * 1000
}
}
});
</script>
</body>
</html>
代码示例有一个input输入框“千米”和一个文本显示“米”,分别对应绑定了data属性中的kilometers和meters,kilometers 和 meters 初始值都为0,同时使用watch创建了data.kilometers的监听
当“千米”输入框输入内容时会改变data.kilometers的值从而触发kilometers的监听,监听器会执行kilometers监听方法将kilometers的值乘以1000并将计算结果复制给meters,此时米对应显示的数字会自动发生变化
8.computed
Vue提供了计算属性,用来处理一些复杂逻辑的计算
代码示例:
<div id="app">
<p>原始字符串: {{ message }}</p>
<p>计算后反转字符串: {{ reversedMessage }}</p>
</div>
var vm = new Vue({
el: '#app',
data: {
message: 'Hello Vue.js!'
},
computed: {
reversedMessage: function () {
return this.message.split('').reverse().join('')
}
}
})
运行结果:
-----------------------------------------------------------分割线
Vue生命周期
说明
每个实例都有一个属于它的生命周期,实例创建、数据初始化、挂载、更新、销毁的过程就是一个生命周期。
模版:
<div id="app">
{{ message }}
</div>
数据:
var app = new Vue({
el: '#app',
data: {
message: 'Hello Vue!'
}
})
生命周期可以简单理解为三部分:
(1)初始化阶段的钩子函数(初始化Vue实例的过程):
beforeCreate:实例创建前:数据和模板均未获取到 created:实例创建后: 可访问到 data 数据,但模板未获取到 beforeMount:数据挂载前:模板已获取到,但是数据未渲染到模板上 mounted:数据挂载后: 数据已渲染到模板中
(2)更新阶段的钩子函数(数据渲染、更新Dom的过程,可重复):
beforeUpdate:模板更新前:data 改变后,更新数据模板前调用 updated:模板更新后:将 data 渲染到数据模板中
(3)销毁阶段的钩子函数(销毁实例的过程):
beforeDestroy:实例销毁前 destroyed:实例销毁后
钩子函数:
var vm = new Vue({
el:'#app',
data:{
msg:'测试钩子函数'
},
beforeCreate() {
console.log('beforeCreate')
},
created() {
console.log('created')
},
beforeMount() {
console.log('beforeMount')
},
mounted() {
console.log('mounted')
},
beforeUpdate() {
console.log('beforeUpdate')
},
updated() {
console.log('updated')
},
beforeDestroy() {
console.log('beforeDestroy')
},
destroyed() {
console.log('destroyed')
}
})
使用
生命周期中每一个钩子函数在特定的阶段执行,可以利用不同钩子函数的特性,实现不同的功能。实际使用时可根据需求选择使用对应的钩子函数。比如:
created钩子函数中可以用来接收路径参数,将接收到的值赋值给data中对应的字段
mounted钩子函数中可以用来发送异步请求去后端获取数据,将后台数据赋值给data中对应的字段,从而改变页面显示内容
var app2 = new Vue({
el: '#app-2',
data: {
orderId : '',
orderDetail: {}
},
methods: {
getDetail(orderId) {
orderApi.orderDetail(orderId).then(data => {
this.orderDetail = data
})
}
},
created() {
this.orderId = this.$route.params.orderId
},
mounted() {
this.getDetail(this.orderId)
}
})
以上为Vue最基础且常用的内容,更多详细教程可参考三方网站:
Element - The world's most popular Vue UI framework
项目应用
项目结构
整体结构
|-- build ---- 构建脚本文件夹
|--build.js ---- 生产环境构建脚本
|--check-version.js ---- 检查npm、node.js版本
|--utils.js ---- 构建相关工具方法
|--vue-loader.conf.js ---- 配置css加载器以及编译css之后自动添加前缀
|--webpack.base.conf.js ---- webpack基本配置
|--webpack.dev.conf.js ----- webpack开发环境配置
|--webpack.prod.conf.js ---- webpack生产环境配置
|-- config ---- 项目配置文件夹
|-- dev.env.js ---- 开发环境变量
|-- index.js ---- 项目配置文件
|-- prod.env.js ---- 生产环境变量
|-- dist ---- 打包文件目录,执行打包命令后生成
|-- node_modules ---- npm加载项目的依赖模块,安装依赖后生成
|-- src ---- 源码文件夹(名称不可修改)
|-- assets ---- 资源文件夹,比如存放 css,图片等资源
|-- components ---- 组件文件夹,用来存放公共组件
|-- icons ---- 图标文件夹,用来存放svg等图标文件
|-- pages ---- 页面文件夹,用来放路由指向的主体页面
|-- router ---- 路由文件夹,用来存放路由配置文件
|-- service ---- 服务文件夹,用来存放定义后台接口请求方法文件
|-- store ---- 全局存储文件夹,用来存放权限、菜单状态等文件
|-- utils ---- 工具文件夹,用来存放各种工具类
|-- App.vue ---- 项目主组件,所有页面都是在该组件下进行切换的
|-- main.js ---- 项目入口js文件,作用是初始化 vue 实例,并引入所需要的插件
|-- static ---- 静态资源文件夹,不会被webpack构建
|-- index.html ---- 入口html页面
|-- package.json ---- npm包配置文件,定义项目的npm脚本、依赖包等信息
|-- README.md ---- 项目的说明文档,markdown格式
|-- .xxx ---- 各类配置文件,比如代码风格校验、git忽略文件等配置文件
重点目录及文件
整体结构只需简单了解即可,日常开发主要关注下几个重点目录及文件
-
config/index.js
本地开发调试前端代码时需单独启动前端项目,前端项目启动后浏览器访问的host和端口需要在该文件中配置。配置示例如下:
host: 'xxxucgoodstest.xxx.com',
port: 80,
前端调用后台接口可能存在域名或端口不一致问题,可通过配置config/index.js中的proxyTable解决。proxyTable用的是http-proxy-middleware中间件,该中间件本质上是在本地开了一个服务器dev-server,所有的请求都通过这里转发出去,即把浏览器的发送请求代理转发到代理服务器上,再由代理服务器发送请求给目标服务器,从而解决跨域问题。配置示例如下:
proxyTable: {
'/wapi': {
target: 'http://zucheucgoodstest.zuche.com:8080',
changeOrigin: true,
pathRewrite: {
'^/wapi/': '/zucheucgoods/wapi/'
}
}
}
-
src/*
日常需求代码主要都在src文件夹对应目录下开发
src/components:全局公共组件
src/pages:页面代码
src/router:页面路由配置
src/service:后台接口请求定义
src/utils:公共工具类
-
package.json
类似于JAVA项目的pom.xml,如要引入其他前端项目或三方的npm包,需在package.json配置具体的包名和版本
"@zuche/ucar-vue": "1.3.6",
"@car/mmc-element": "^0.4.1",
"@car/car-admin-vue": "latest",
版本号可直接指定,也可在版本号前加 ^、~等
~:代表匹配最近的小版本依赖包,比如~1.2.3会匹配所有1.2.x版本,但是不包括1.3.0
^:代表匹配最新的大版本依赖包,比如^1.2.3会匹配所有1.x.x的包,包括1.3.0,但是不包括2.0.0
*或latest:代表安装最新版本的依赖包
服务启动与关闭
确认本地node版本,公司服务器默认使用8.9,本地建议使用8.9,最高不要超过10
1.安装依赖
cd到前端项目目录,然后执行npm install命令安装项目依赖
2.确认配置
查看config下的index.js文件的配置,域名一般配置成测试环境域名,便于登录状态的获取
3.修改本地hosts文件
将测试域名指向127.0.0.1,可直接修改系统中的hosts文件,windows系统也可下载SwitchHosts去管理hosts
4.启动服务
启动前端项目前要确认后端服务可用
在前端项目目录中,执行npm run dev,项目启动成功后控制台会有Compiled successfully提示
服务启动后可浏览器直接输入页面地址进行访问,也可到caradmin中访问
5.关闭服务
按键盘Ctrl+C,控制台输入Y即可关闭前端服务
UI组件库
UI组件库就是按照组件化设计规范与组件化编码规范,使用统一的风格样式封装的一整套常用的UI组件,能大幅提高设计研发的效率及质量
目前公司内部使用的ui组件库是Element UI,同时公司前端团队基于租车后台系统的业务需求和使用场景在Element UI的基础上又二次封装了部分常用组件
Element UI
官方网址:Element - 网站快速成型工具
组件列表:
Basic基础组件 | Layout 布局 |
Container 布局容器 | |
Color 色彩 | |
Typography 字体 | |
Border 边框 | |
Icon 图标 | |
Button 按钮 | |
Link 文字链接 | |
Form表单相关 | Radio 单选框 |
Checkbox 多选框 | |
Input 输入框 | |
InputNumber 计数器 | |
Select 选择器 | |
Cascader 级联选择器 | |
Switch 开关 | |
Slider 滑块 | |
TimePicker 时间选择器 | |
DatePicker 日期选择器 | |
DateTimePicker 日期时间选择器 | |
Upload 上传 | |
Rate 评分 | |
ColorPicker 颜色选择器 | |
Transfer 穿梭框 | |
Form 表单 | |
Data数据相关 | Table 表格 |
Tag 标签 | |
Progress 进度条 | |
Tree 树形控件 | |
Pagination 分页 | |
Badge 标记 | |
Avatar 头像 | |
Skeleton 骨架屏 | |
Empty 空状态 | |
Descriptions 描述列表 | |
Result 结果 | |
Notice提醒相关 | Alert 警告 |
Loading 加载 | |
Message 消息提示 | |
MessageBox 弹框 | |
Notification 通知 | |
Navigation导航相关 | NavMenu 导航菜单 |
Tabs 标签页 | |
Breadcrumb 面包屑 | |
PageHeader 页头 | |
Dropdown 下拉菜单 | |
Steps 步骤条 | |
Others其他 | Dialog 对话框 |
Tooltip 文字提示 | |
Popover 弹出框 | |
Popconfirm 气泡确认框 | |
Card 卡片 | |
Carousel 走马灯 | |
Collapse 折叠面板 | |
Timeline 时间线 | |
Divider 分割线 | |
Calendar 日历 | |
Image 图片 | |
Backtop 回到顶部 | |
InfiniteScroll 无限滚动 | |
Drawer 抽屉 |
使用方式
1.确定组件,根据需求及原型设计去Element UI官网组件库查找符合要求的组件。
比如页面要实现一个日期选择功能,在Element UI官网组件库查找发现有两个组件和日期相关,分别为“DatePicker 日期选择器”和“DateTimePicker 日期时间选择器”,由于需求只要求选择日期所以可确定使用“DatePicker 日期选择器”组件。
2.确定组件具体展示形式,Element UI官网每个组件都会提供各种支持的形式,比如“DatePicker 日期选择器”组件可支持选择日、周、月、年,还可实现选择日期范围
3.复制代码
确定好组件具体形式后,点击“显示代码”即可查看组件具体的使用代码,直接将代码复制到自己开发的vue页面即可
4.调整代码
如果Element UI提供的代码不完全满足需求,可以参考组件介绍页面下面的完整属性介绍,通过修改组件的属性去实现想要的效果
比如“DatePicker 日期选择器”组件选择日期后默认会出现“清空”图标,但需求要求日期选择完成后不能清空,则不能展示该图标
查询文档后发现DatePicker组件有一个clearable属性,默认是true,所以默认会出现“清空”图标
将DatePicker组件的clearable设置成false后,发现清空图标消失了
<el-date-picker
:clearable=false
v-model="value1"
type="date"
placeholder="选择日期">
</el-date-picker>
5.复杂组件
上面举例的“DatePicker日期选择器”组件相对简单,比如要实现一个相对复杂的表单功能,就要使用“Form 表单”组件,该组件由el-form和el-form-item组成,整个表单为一个el-form,每一个表单项为一个el-form-item
如下面截图和代码示例,整个表单使用el-form标签,每一项比如“活动名称”、“活动区域”为一个el-form-item。el-form-item的label属性为展示的表单项名称,el-form-item内使用具体的组件实现表单项输入,比如“活动名称”使用el-input实现文本输入公共、“活动区域”使用el-select实现下拉选择功能。将各个独立的组件组合到一起就可实现相对复杂的样式
<el-form ref="form" :model="sizeForm" label-width="80px" size="mini">
<el-form-item label="活动名称">
<el-input v-model="sizeForm.name"></el-input>
</el-form-item>
<el-form-item label="活动区域">
<el-select v-model="sizeForm.region" placeholder="请选择活动区域">
<el-option label="区域一" value="shanghai"></el-option>
<el-option label="区域二" value="beijing"></el-option>
</el-select>
</el-form-item>
<el-form-item label="活动时间">
<el-col :span="11">
<el-date-picker type="date" placeholder="选择日期" v-model="sizeForm.date1" style="width: 100%;"></el-date-picker>
</el-col>
<el-col class="line" :span="2">-</el-col>
<el-col :span="11">
<el-time-picker placeholder="选择时间" v-model="sizeForm.date2" style="width: 100%;"></el-time-picker>
</el-col>
</el-form-item>
<el-form-item label="活动性质">
<el-checkbox-group v-model="sizeForm.type">
<el-checkbox-button label="美食/餐厅线上活动" name="type"></el-checkbox-button>
<el-checkbox-button label="地推活动" name="type"></el-checkbox-button>
<el-checkbox-button label="线下主题活动" name="type"></el-checkbox-button>
</el-checkbox-group>
</el-form-item>
<el-form-item label="特殊资源">
<el-radio-group v-model="sizeForm.resource" size="medium">
<el-radio border label="线上品牌商赞助"></el-radio>
<el-radio border label="线下场地免费"></el-radio>
</el-radio-group>
</el-form-item>
<el-form-item size="large">
<el-button type="primary" @click="onSubmit">立即创建</el-button>
<el-button>取消</el-button>
</el-form-item>
</el-form>
编码规范
命名
-
文件夹:采用下划线连接,例:demo_folder
-
普通文件:采用短横线连接,例:demo-list.vue、demo-api.js
-
自定义组件:采用大驼峰命名法,例:DetailContractInfo.vue
路径
-
页面文件:在src/pages下建立对应页面文件夹,页面文件放入该文件夹下
-
局部组件:放入相对应页面文件夹下的components子文件夹中
-
全局组件:放入src/components文件夹下