vue 起步:
$ npm install -g vue-cli
$ vue init webpack my-project
$ npm install --save-dev react-router@2.8.1
$ cd my-project
$ npm install
$ npm run dev
1.新建mock文件夹,预置模拟数据js文件
2.新建utils文件夹, 存放重新封装的axios和一些工具类js文件
3.修改main.js主文件:
/*
这里是全局引入配置
*/
import Vue from 'vue'
import App from './App'
import router from './router'
// 引入mockjs
require('./mock/mock.js')
Vue.config.productionTip = false/* eslint-disable no-new */
new Vue({
el: '#app',
router,
components: { App },
template: '<App/>'
})
4.定义路由
import Vue from 'vue'
import Router from 'vue-router'
import layout from '@/views/Layout/Layout'
Vue.use(Router)
const First = {template: '<div>主体内容文本1111{{ JSON.stringify($route,null,2) }}</div>'}
const Two = {template: '<div>主体内容文本22222222</div>'}
const Third = {template: '<div>主体内容文本3333333</div>'}
export default new Router({
mode: 'history', //去掉url的#
//后台设置 https://router.vuejs.org/zh/guide/essentials/history-mode.html#%E5%90%8E%E7%AB%AF%E9%85%8D%E7%BD%AE%E4%BE%8B%E5%AD%90
routes: [
{
path: '/',
component: layout,
children:[
{
path: '/dashboard',
name: 'dashboard',
component: First
},
{
path: '/asset',
name: 'asset',
component: Two
},
{
path: '/order',
name: 'order',
component: Third
},
{
path: '/scan/task',
name: 'scanTask',
component: resolve => require(['../views/ScanTask.vue'], resolve)
},
{
path: '/scan/plugin',
name: 'scanPlugin',
component: resolve => require(['../views/ScanPlugin.vue'], resolve)
}
]
}
]
})
5.编写组件
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<!-- 子组件挂在显示位置 -->
<transition name="move" mode="out-in"><router-view></router-view></transition>
</div>
<!-- 调用组件
<TaskTable :apiUrl="tableUrl" ref="table1" @click="handleInit">
: 表示data里面的属性也可以是props的属性;@可以调用事件
apiUrl 子组件参数
ref=table1 设置子组件名称,以方便父类调用其子组件方法
</TaskTable>
-->
</template>
<script>
// 加载组件也可以加载样式[属于局部加载]
// import TaskTable from './../components/TaskTable'; 这个是自定义的组件
// import { Message } from 'element-ui'
// import 'element-ui/lib/theme-chalk/index.css'
export default {
name: 'HelloWorld',
// 子类组件属性, 父类调用
//props: ["apiUrl"],
data () {
return {
msg: "",
tableUrl:{
list: '',
delete: '',
edit: '',
audit: '',
change: ''
}
}
},
// 初始化数据,或者方法
mounted(){
this.msg = "test";
// this.handleInit();
},
// 自定义方法
methods: {
// handleInit(){},
// this.$refs.table1.hanldSearch(); 调用子组件的方法
},
// 过滤
filters:{},
// 加载组件
components: {
// TaskTable //引用自定义组件
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
6.编写子组件
<template>
<div class="table">
<el-table ref="multipleTable" :data="tableData" tooltip-effect="dark" style="width: 100%"
@selection-change="handleSelectionChange"
stripe border>
<el-table-column type="selection" width="60"></el-table-column>
<el-table-column prop="tid" label="任务事件" show-overflow-tooltip></el-table-column>
<el-table-column prop="taskid" label="任务ID" show-overflow-tooltip></el-table-column>
<el-table-column prop="target" label="扫描域名" show-overflow-tooltip></el-table-column>
<el-table-column prop="bussines" label="事业部" show-overflow-tooltip></el-table-column>
<el-table-column prop="parameter" label="扫描参数" :formatter="jsonFormats" show-overflow-tooltip></el-table-column>
<el-table-column prop="pluginCount" label="扫描插件" show-overflow-tooltip></el-table-column>
<el-table-column label="状态" width="100">
<template slot-scope="scope">
<h1 v-if="scope.row.status === 1"><el-button type="warning" size="mini">运行中</el-button></h1>
<h1 v-else-if="scope.row.status === 2"><el-button type="success" size="mini">已完成</el-button></h1>
<h1 v-else><el-button type="danger" size="mini">未运行</el-button></h1>
</template>
</el-table-column>
<el-table-column prop="ctime" label="创建时间" :formatter="dateFormats" show-overflow-tooltip width="180"></el-table-column>
<el-table-column label="操作" width="300">
<template slot-scope="scope">
<el-button size="mini" type="danger" @click="handleDelete(scope.$index, scope.row)">删除</el-button>
</template>
</el-table-column>
</el-table>
<el-pagination @current-change="handleCurrentChange" :current-page="page.current" :total="page.total" style="float:right"
layout="total, prev, pager, next, jumper">
</el-pagination>
</div>
</template>
<script>
import request from './../utils/request.js';
import dateFormat from './../utils/common.js';
import { Message } from 'element-ui'
export default {
props: ['apiUrl'],
data() {
return {
tableData: [],
dialogFormVisible: false,
page: {
current: 1,
total: 40
},
inputName: '',
multipleSelection:[]
}
},
mounted(){
// 初始化数据
this.handleInit();
},
methods: {
//数据全选
handleSelectionChange(val) {
this.multipleSelection = val;
},
//搜索
hanldSearch(val) {
Message.error("搜索功能暂时未启用!!!");
},
//编辑数据
handleEdit(index, row) {
this.tableData[index].name = false;
},
//保存数据
handleSave(index, row) {
let data = {'pid': row.pid,'name': this.inputName};
request.BingPost(this.apiUrl.edit, data)
.then(res => {
if(res.status == 1){
Message.success('successful !!!')
this.handleCurrentChange(0)
}else{
Message.error(res.msg);
}
}).catch(error => {
Message.error('数据错误');
})
},
//鼠标离开
handleMouseOut(index, row){
this.handleCurrentChange(0);
},
//审核数据
handleAudit(index, row) {
let data = {'pid': row.pid}
request.BingPost(this.apiUrl.audit, data)
.then(res => {
if(res.status == 1){
Message.success('successful !!!')
this.handleCurrentChange(0)
}else{
Message.error(res.msg);
}
}).catch(error => {
Message.error('数据错误');
})
},
//状态切换
handleChange(index, row) {
let data = {'pid': row.pid}
request.BingPost(this.apiUrl.change, data)
.then(res => {
if(res.status == 1){
Message.success('switch successful !!!')
this.handleCurrentChange(0)
}else{
Message.error(res.msg);
}
}).catch(error => {
Message.error('数据错误');
})
},
//删除数据
handleDelete(index, row) {
let data = {'pid': row.pid}
request.BingPost(this.apiUrl.delete, data)
.then(res => {
if(res.status == 1){
Message.success('successful !!!')
this.handleCurrentChange(0)
}else{
Message.error(res.msg);
}
}).catch(error => {
Message.error('数据错误');
})
},
//页面跳转
handleCurrentChange(val) {
request.BingGet(this.apiUrl.list, '')
.then(res => {
if(res.status == 1){
this.page.total = res.msg.length;
this.tableData = res.msg.slice((val-1)*10,(val-1)*10+10);
}else{
Message.error(res.msg);
}
}).catch(error => {
Message.error('数据错误');
})
},
//获取数据,进行初始化
handleInit(){
request.BingGet(this.apiUrl.list, '')
.then(res => {
if(res.status == 1){
this.page.total = res.msg.length;
this.tableData = res.msg.slice(0,1*10);
}else{
Message.error("没有数据");
}
}).catch(error => {
Message.error('数据错误');
})
},
//根据时间戳生成的时间对象
dateFormats(row, column) {
var value = row[column.property];
var date = dateFormat(value)
return date;
},
//根据json转字符
jsonFormats(row, column) {
var value = row[column.property];
var date = JSON.stringify(value)
return date;
}
}
}
</script>
/*
computed是响应式的,methods并非响应式。
调用方式不一样,computed定义的成员像属性一样访问,methods定义的成员必须以函数形式调用。
computed是带缓存的,只有其引用的响应式属性发生改变时才会重新计算,而methods里的函数在每次调用时都要执行。
computed中的成员可以只定义一个函数作为只读属性,也可以定义get/set变成可读写属性,这点是methods中的成员做不到的。
如下:
<Icon @click.native="collapsedSider" :class="rotateIcon" :style="{margin: '0 20px'}" type="md-menu" size="24"></Icon>
computed: {
rotateIcon () {
return [
'menu-icon',
this.isCollapsed ? 'rotate-icon' : ''
];
},
menuitemClasses () {
return [
'menu-item',
this.isCollapsed ? 'collapsed-menu' : ''
]
}
}
*/
组件文件夹下的Index.js
作用就是重新定义导出的格式
export { default as Navbar } from './Navbar'
export { default as Sidebar } from './Sidebar'
export { default as TagsView } from './TagsView'
调用的时候,如下:
import { Navbar, Sidebar, TagsView } from './components' //components 是文件夹
Axios
1、浏览器中创建XMLHttpRequests
2、从node.js创建http请求
3、支持promise API
4、拦截请求和响应
5、转换请求和响应数据
6、取消请求
7、自动转换JSON
8、客户端支持防御XSRF
Promise介绍
Promise主要是对回调嵌套的一种优化方案,早期使用$.ajax()的时候需要传递一个回调函数,如果业务导致层级嵌套太多,会非常难看,现在的Promise在后面直接.then()或者.catch()则要优雅许多。
var promise = new Promise ( (resolve, reject) => { ... } )
当顺利完成后:
呼叫 resolve(value) 回应所得資料
当作业错误时:
呼叫 reject(reason) 回应错误信息
如下:
export function doSomethingAsync(){
return new Promise((resolve, reject) => {
// 模拟非同步作业
setTimeout(function () {
let isSuccess = false
if (isSuccess) {
resolve('success')
} else {
reject(new Error('something wrong'))
}
}, 2000)
})
}
在vue项目中,我们不建议使用jquery,所以我们在异步获取数据时就不能使用$.get()或者$.post()等方法了。而vue官方已经不推荐使用vue-resource,而是使用axios;
如下:
export function myGet(url, params) {
let _url = apiUrl + url
return new Promise((resolve, reject) => {
axios.get(_url, {params}).then(function (response) {
resolve(response.data)
})
.catch(function (err) {
reject(err)
})
})
}
export function myPost(url, params) {
let _url = apiUrl + url
return new Promise((resolve, reject) => {
axios.post(_url, {params}).then(function (response) {
resolve(response.data)
})
.catch(function (err) {
reject(err)
})
})
}