一、安装npm cnpm
1 下载安装node.js
地址:https://nodejs.org/en/download/
查看是否安装成功
node -v
npm -v
2 安装cnpm 即安装淘宝镜像
系统搜索打开打开 Windows PowerShel窗口,命令开始安装:
npm install -g cnpm --registry=https://registry.npm.taobao.org
查看是否安装成功
cnpm -v
二、页面结构
1 div层
2 data层:数据定义层
3 components:引用组件
4 computed:计算属性
5 methods方法层
6 生命周期
7 watch:监听数据
8 style:样式层
<template>
<div>
<!-- 1 div层-->外围只可有一个div
v-model双向绑定数据
<el-input v-model="inputData"/> 调用数据{{getComputedInputData}}
数据遍历
<div v-for="(it,i) in list" :key="i">
数据{{i}}: {{it}}
</div>
<div>
数据判断 v-if 与v-show v-if=false时不会加载内容 v-show=false时会加载内容
<span v-if="sex===1">男</span>
<span v-else-if="sex===2">女</span>
<span v-else>保密</span>
</div>
{{str}}
子组件调用
<child actionId="1" @func="getChildMsg"></child>
<child :actionId="actionId" @func="getChildMsg"></child>
</div>
<template>
import child from './child.vue'
<script>
export default {
name: "test",
//注册组件
components:{
child
},
computed: {
// 计算属性的 getter
getComputedInputData: function () {
// `this` 指向 vm 实例
return this.inputData+'abcdefg'
}
},
// 2 数据定义层
data(){
return{
inputData:'',
list:[{id:1,name:'张三',id:2,name:'李四'}],
sex:1,
str:'hello wrold!',
actionId:2
}
},
// 3 方法层
methods:{
handleDemo(){
console.log(123);
},
getChildMsg(msg){
//打印子组件传过来的值
console.log(msg);
}
},
/**
*vue生命周期
* 1、beforeCreate 实例未创建,调用不到data数据
* 2、created 实例创建完成后调用,此阶段完成了数据的观测等,但尚未挂载
* 3、beforeMount (实例创建完)el未挂载到实例上,获取的是vue启动前的最初DOM
* 4、mounted (实例创建完)且el挂载到实例上后调用,页面首次进入执行只执行一次(经常用到)
* 5、 beforeDestroy 实例销毁之前调用
* 6、 destroyed 实例销毁之后调用
* 7、beforeUpdate 获取数据更新前的原DOM
* 8、updated 获取数据更新后的DOM
*【常用created】
*/
created(){
this.handleDemo()
},
//监听
watch:{
//str改变后会执行
str(n,o){
this.handleDemo();
}
}
}
<!--scoped css当前页有效-->
<style scoped>
// 4 样式层
</style>
三、定义子组件
<template>
<div>
父组件传过来的值{{actionId}}
{{actionIdMiddle}}
<button @click="handleTake"></button>
</div>
<template>
<script>
export default {
name: "test",
// 父组件传递的值,data中不可再定义actionId,该组件内不可以改变actionId的内容,
// 只可以用中间值做改变
props:['actionId'],
data(){
return{
msg:'',
actionIdMiddle:this.actionId
}
}
methods:{
handleTake(){
this.$emit('func',this.msg)
}
},
created(){
this.actionIdMiddle+'abcdef'
}
}
四、组件双向绑定
1 子组件
<template>
<div>
<el-input v-model="value2"/>
</div>
</template>
<script>
export default {
name: 'HelloWorld',
props: {
value: {
type: String,
default:''
}
},
data () {
return {
value2: this.value
}
},
watch:{
// n new的值 o old的值
value(n,o) {
this.value2 = n
this.$emit('input',this.value2)
}
}
}
</script>
2 父组件
<template>
<div>
<HelloWorld v-model = 'value'/>
父组件的值
</div>
</template>
<script>
import HelloWorld from './components/HelloWorld'
export default {
name: 'App',
components: {
HelloWorld
},
data () {
return {
value: abc
}
}
}
</script>
五、规范
v-for 必须带key属性
js部分字符串用单引号,即:“” 变成 ''
js最后面的结尾不带逗号
vue的name要首字母大写
==与!= 转成===与!==
v-for 和v-if不要在同一行标签使用 <div v-for="(it,i) in list" :key="i" v-if="it.value===1">男</div>
也可以用 ESLint 去处理代码
六、前后端交互
七、table组件
八、表单组件
九、表格组件
<template>
<el-card>
<el-card class="aaa_query_card" shadow="hover">
<el-button type="primary" class="el-icon-plus" @click="doAdd">添加</el-button>
<el-button class="el-icon-refresh" @click="doRefresh">刷新</el-button>
</el-card>
<aaa-m-table ref="t" :config="config"/>
<el-dialog :visible.sync="vis" title="班次配置" width="40%">
// 表单组件
<el-form ref="addForm" :rules="{}" :model="addForm" label-position="left" label-width="100px">
<el-form-item label="班次名称" prop="className">
<el-input v-model="addForm.className" maxlength="20" />
</el-form-item>
<el-form-item :rules="rules" label="奶庁" prop="systemId">
<el-select v-model="addForm.systemId" style="width: 100%;">
<el-option v-for="(it,i) in systemData" :key="i" :label="'奶厅'+it.systemNumber" :value="it.id"/>
</el-select>
</el-form-item>
<template v-for="(it, i) in addForm.timeData">
<el-form-item :prop="'timeData.' + i + '.value'" :rules="rules" :label="`班次时间${i+1}`" :key="i">
<el-time-picker v-model="it.value"/>
<el-button v-if="i===0" size="small" type="primary" class="el-icon-plus" @click="addTime"/>
<el-button v-if="i!==0&&addForm.timeData.length>1" type="danger" size="small" class="el-icon-close" @click="lessTime(i)"/>
</el-form-item>
</template>
</el-form>
<span slot="footer" class="dialog-footer">
<el-button @click="vis = false">取 消</el-button>
<el-button type="primary" @click="doPost">确 定</el-button>
</span>
</el-dialog>
</el-card>
</template>
<script>
// 班次设置
export default {
name: 'ClassSetting',
data() {
return {
config: {},
systemData: [],
addForm: {
systemId: '',
timeData: [{ value: '' }, { value: '' }, { value: '' }]
},
rules: [{ required: true, message: '不可为空', trigger: 'change' }],
vis: false
}
},
created() {
this.getSysTemData()
},
methods: {
// 获取奶厅
getSysTemData() {
//前后端交互 axios请求
this.$api.get(`${this.$global.equipmentApi}/systems/list`, {
userId: 1,
systemType: 1
}).then(res => {
console.log('res', res)
this.systemData = res.data
this.getTableData()
})
},
getTableData() {
// 表格组件
this.config = {
url: `${this.$global.equipmentApi}/classes/list`,
where: { userId: 1 },
columns: [
{ prop: 'index', label: '编号' },
{ prop: 'className', label: '班次名称', minWidth: 110 },
{
prop: 'systemId', label: '奶厅', minWidth: 100, render: (h, scope) => {
return this.getSystemName(scope.row.systemId)
}
},
{ prop: 'time1', label: '班次时间1', minWidth: 90 },
{ prop: 'time2', label: '班次时间2', minWidth: 90 },
{ prop: 'time3', label: '班次时间3', minWidth: 90 },
{ prop: 'time4', label: '班次时间4', minWidth: 90 },
{ prop: 'time5', label: '班次时间5', minWidth: 90 },
{ prop: 'createTime', label: '配置时间', minWidth: 160 },
{
label: '操作', minWidth: 120, render: (h, scope) => {
return (<el-button type = 'danger' on-click={() => this.delete(scope.row)} size= 'small'> 删除 </el-button>)
}
}
]
}
}, getSystemName(systemId) {
const obj = this.systemData.find(it => {
return it.systemNumber === systemId
})
const systemName = obj ? '奶厅' + obj.systemNumber : ''
return (<span> {systemName} </span>)
},
doRefresh() {
this.getTableData()
this.$notify.success('刷新成功')
},
doAdd() {
this.vis = true
}, addTime() {
if (this.addForm.timeData.length < 5) {
this.addForm.timeData.push({ value: '' })
} else {
this.$notify.info('最多添加5个班次时间')
}
}, lessTime(i) {
if (this.addForm.timeData.length > 0) {
this.addForm.timeData.splice(i, 1)
}
}, doPost() {
this.$refs['addForm'].validate((valid) => {
if (valid) {
if (this.addForm.timeData.length < 3) {
this.$notify.error('请至少添加三个班次时间')
return false
}
const data = {
userId: 1,
systemId: this.addForm.systemId,
className: this.addForm.className
}
const arr = this.addForm.timeData
arr.sort((a, b) => {
return a.value - b.value
})
let i = 1
for (const it of arr) {
data['time' + i] = this.$dateUtil.format(it.value, 'hh:mm:ss')
i++
}
this.$api.post(`${this.$global.equipmentApi}/classes/add`, data).then(res => {
this.$notify.success('保存成功')
this.addForm = {
systemId: '',
timeData: [{ value: '' }, { value: '' }, { value: '' }]
}
this.getTableData()
})
}
})
}, delete(row) {
this.$confirm(`确定要删除该条记录吗?`, '提示', {
confirmButtonText: '确定',
cancelButtonText: '取消',
type: 'warning'
}).then(() => {
this.$api.post(`${this.$global.equipmentApi}/classes/delete`, { userId: 1, systemId: row.systemId }).then(res => {
this.$notify.success('删除成功')
this.getTableData()
})
})
}
}
}
</script>
<style scoped>
</style>
十、全局定义
// 定义全局js
import api from './utils/api'
Vue.prototype.$api = api
// 定义全局组件
import aaaMTable from './components/aaa/aaaMTable'
Vue.component('aaaMTable', aaaMTable)
// 一般很少改动
十一、router与菜单栏与菜单
import Layout from '@/layout'
// perm 权限值,idx 序号
const deviceRouter = {
path: '/device',
component: Layout,
redirect: '/device/classSetting',
name: 'device',
meta: { title: '设备管理', icon: 'table', perm: 'device', idx: 10 },
children: [
{
path: 'classSetting',
component: () => import('../../views/device/ClassSetting'),
name: 'classSetting',
meta: { title: '班次设置', icon: 'table', perm: 'classSetting', idx: 2 }
},
{
path: 'gatewayParam',
component: () => import('../../views/device/GatewayParam'),
name: 'GatewayParam',
meta: { title: '网关参数录入', icon: 'table', perm: 'gatewayParam', idx: 3 }
}
]
}
export default deviceRouter
十二、页面跳转
<template>
<div>
<!-- 直接跳转 -->
<router-link to='/testDemo'>
<button>点击跳转2</button>
</router-link>
<!-- 带参数跳转 -->
<router-link :to="{path:'testDemo',query:{setid:123456}}">
<button>点击跳转1</button>
</router-link>
<router-link :to="{name:'testDemo',params:{setid:1111222}}">
<button>点击跳转3</button>
</router-link>
<button @click='goTo()'>点击跳转4</button>
</div>
</template>
<script>
export default {
name: 'test',
methods: {
goTo() {
//直接跳转
this.$router.push('/testDemo')
//带参数跳转
//地址栏上看得到参数 其它页面调用this.$route.query.setid
this.$router.push({ path: '/testDemo', query: { setid: 123456 } })
//地址栏上看不到参数 其它页面调用this.$route.params.setid
this.$router.push({ name: 'testDemo', params: { setid: 111222 } })
}
}
}
</script>
十三、链接
vue官网:https://cn.vuejs.org/v2/guide/
element主题框架 https://element.eleme.cn/#/zh-CN/component/installation
mcommonTable https://hyk51594176.github.io/mcommon/
vue中文社区 https://vue-js.com/
vue全家桶文档 http://doc.liangxinghua.com/vue-family/1.html
十四、多种遍历
1 for循环
// 1.1 基础for循环
//for
let arr = [{id: 1, name: '男'}, {id: 2, name: '女'}];
for (let i = 0, len = arr.length; i < len; i++) {
console.log(i); // 0 1
console.log(arr[i].name); //男 女
}
// 1.2 for in循环
/**
* for in (也可遍历Object)
* @param key 索引(下标)
*/
for (var key in arr) {
console.log(key); // 0 1 返回数组索引
console.log(arr[key].name) // 男 女
}
// 1.3 for of循环
/**
* for of
* @param item 对象
*/
for (let item of arr) {
console.log(item.name); // 男 女
}
// 输出数组索引
for (let item of arr.keys()) {
console.log(item); // 0 1
}
// 输出内容和索引
for (let [item, val] of arr.entries()) {
console.log(item + ':' + val); // 0:男 1:女
}
2 返回值相关
// 2.1 forEach循环
/**
* forEach
* @param item 对象 必填参数
* @param index 索引(下标)
* @param arr 数组本身
* @return undefined(即无返回值)
*/
arr.forEach((item, index, arr) => {
console.log(item.name); //男 女
console.log(index); // 0 1
console.log(arr); // [{id: 1, name: '男'}, {id: 2, name: '女'}];
})
// 2.2 find,map,filter语法
/**
* find,map,filter
* @param item 对象(必写)
* @param index 索引(下标)
* @param arr 数组本身
* @return
* find(存在返回第一个元素,无返回undefined)
* filter(返回符合条件的数组,无返回[])
* map(不用于条件返回而用于单个属性返回成数组,不存在此属性返回[undefined,undefined]
*/
// 2.2.1 find 语法
var arr = [1,2,3,4,5,6,7];
var ar = arr.find((item,index)=>{
return item>5;
});
console.log(ar);//6
console.log(arr);//[1,2,3,4,5,6,7]
// 2.2.2 filter 语法
var arr2 = [1,2,3,4,5,6,7];
var ar2 = arr2.filter((item,index)=>{
return item>5;
});
console.log(ar2);//[6,7]
console.log(arr2);//[1,2,3,4,5,6,7]
// 2.2.3 map 语法
//处理数组
var arr = [1,2,3,4,5];
var ar = arr.map(function(item){
return item*2;
});
console.log(ar);//[2,4,6,8,10]
console.log(arr);//[1,2,3,4,5]
//获取数组某个属性
var arr3 = [{id:1,name:'张三'},{id:2,name:'李四'}];
var ids = this.arr3.map(item => item.id).toString();
var names = this.arr3.map(item => item.id).toString();
var arr4= this.arr3.map(item => {
if(item.name == '张三'){
item.name = '王五'
}
return item
});
console.log(ids);//1,2
console.log(names);//张三,李四
console.log(arr4);//[{id:1,name:'王五'},{id:2,name:'李四'}];