node

node

Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行环境。
javascript/jQuery

javascript/jQuery

一种直译式脚本语言,是一种动态类型、弱类型、基于原型的语言,内置支持类型。
MongoDB

MongoDB

MongoDB 是一个基于分布式文件存储的数据库
openstack

openstack

OpenStack是一个由NASA(美国国家航空航天局)和Rackspace合作研发并发起的,以Apache许可证授权的自由软件和开放源代码项目。
VUE

VUE

一套构建用户界面的渐进式框架。与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计。
bootstrap

bootstrap

Bootstrap is the most popular HTML, CSS, and JS framework for developing responsive, mobile first projects on the web.
HTML

HTML

超文本标记语言,标准通用标记语言下的一个应用。
CSS/SASS/SCSS/Less

CSS/SASS/SCSS/Less

层叠样式表(英文全称:Cascading Style Sheets)是一种用来表现HTML(标准通用标记语言的一个应用)或XML(标准通用标记语言的一个子集)等文件样式的计算机语言。
PHP

PHP

PHP(外文名:PHP: Hypertext Preprocessor,中文名:“超文本预处理器”)是一种通用开源脚本语言。语法吸收了C语言、Java和Perl的特点,利于学习,使用广泛,主要适用于Web开发领域。PHP 独特的语法混合了C、Java、Perl以及PHP自创的语法。它可以比CGI或者Perl更快速地执行动态网页。用PHP做出的动态页面与其他的编程语言相比,PHP是将程序嵌入到HTML(标准通用标记语言下的一个应用)文档中去执行,执行效率比完全生成HTML标记的CGI要高许多;PHP还可以执
每天进步一点点

每天进步一点点

乌法把门的各累笑寂静
求职招聘

求职招聘

猎头招聘专用栏目
Python

Python

一种解释型、面向对象、动态数据类型的高级程序设计语言。

vue2.x 将table 内容导出excel 下载(转换页面table数据)

VUElopo1983 发表了文章 • 0 个评论 • 2784 次浏览 • 2018-01-22 18:06 • 来自相关话题

目前仅支持chrome?downloadjs需自行引入加载 对应的tab HTMLCollection 也应根据你的UI组件进行替换









<template lang="pug">
btn(:stype="stype",:size="size",@click="exportOffice(tid)")
slot
template(v-if="!$slots.default") {{label}}
</template>

<script>
/**
* bootstrap 4.x --> components --> table-->table
*
* @param {String} label 按钮名称
* @param {String} stype 样式
* @param {String} size 大小
*
* 注意以上参数为内置按钮参数 可根据你目前使用的UI组件进行修改
*
* @param {String} tid 表格ID
* @param {String} xlsname excel名称
* @param {String} filters 需过滤的cell className
*
* @date 2018-1-22
*
* @version v1.0.0 beta
*
* @important 注意目前仅支持chrome下使用
*
**/
import download from 'downloadjs'
import btn from '@/components/comp/button'
export default {
name: 'tableToExcel',
components: {
btn
},
props: {
// btn 组件参数
label: String,
stype: String,
size: {
type: String,
default: 'sm'
},
tid: String,
xlsname:String,
filters: String
},
methods: {
base64ToBlob: function(data, mime) {
let base64 = window.btoa(window.unescape(encodeURIComponent(data)))
let bstr = atob(base64)
let n = bstr.length
let u8arr = new Uint8ClampedArray(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
},
exportOffice(tableID) {
let elms = document.getElementById(tableID).cloneNode(true)
let table = elms.childNodes[1].childNodes[0]
// table根据你的ui组件修改对应的HTMLCollection
let rows = table.rows.length
let cells = table.rows.item(0).cells.length
let tableArr = table.getElementsByClassName(this.filters)
for (let i = 0; i < rows; i++) {
table.rows<em>.deleteCell(cells-1)
}
let excelContent = table.innerHTML
let excelFile = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html4 ... Bmeta name=ProgId content=Excel.Sheet> <meta name=Generator content="Microsoft Excel 11"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>${excelContent}</table></body></html>`
let blob = this.base64ToBlob(excelFile, 'application/vnd.ms-excel')
download(blob, this.xlsname||this.$route.name+moment().format('x'), 'application/vnd.ms-excel')
}
}
}
</script> 查看全部

目前仅支持chrome?downloadjs需自行引入加载 对应的tab HTMLCollection 也应根据你的UI组件进行替换



table.png


QQ图片20180122224557.png
<template lang="pug">
btn(:stype="stype",:size="size",@click="exportOffice(tid)")
slot
template(v-if="!$slots.default") {{label}}
</template>

<script>
/**
* bootstrap 4.x --> components --> table-->table
*
* @param {String} label 按钮名称
* @param {String} stype 样式
* @param {String} size 大小
*
* 注意以上参数为内置按钮参数 可根据你目前使用的UI组件进行修改
*
* @param {String} tid 表格ID
* @param {String} xlsname excel名称
* @param {String} filters 需过滤的cell className
*
* @date 2018-1-22
*
* @version v1.0.0 beta
*
* @important 注意目前仅支持chrome下使用
*
**/
import download from 'downloadjs'
import btn from '@/components/comp/button'
export default {
name: 'tableToExcel',
components: {
btn
},
props: {
// btn 组件参数
label: String,
stype: String,
size: {
type: String,
default: 'sm'
},
tid: String,
xlsname:String,
filters: String
},
methods: {
base64ToBlob: function(data, mime) {
let base64 = window.btoa(window.unescape(encodeURIComponent(data)))
let bstr = atob(base64)
let n = bstr.length
let u8arr = new Uint8ClampedArray(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
},
exportOffice(tableID) {
let elms = document.getElementById(tableID).cloneNode(true)
let table = elms.childNodes[1].childNodes[0]
// table根据你的ui组件修改对应的HTMLCollection
let rows = table.rows.length
let cells = table.rows.item(0).cells.length
let tableArr = table.getElementsByClassName(this.filters)
for (let i = 0; i < rows; i++) {
table.rows<em>.deleteCell(cells-1)
}
let excelContent = table.innerHTML
let excelFile = `<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html4 ... Bmeta name=ProgId content=Excel.Sheet> <meta name=Generator content="Microsoft Excel 11"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>${excelContent}</table></body></html>`
let blob = this.base64ToBlob(excelFile, 'application/vnd.ms-excel')
download(blob, this.xlsname||this.$route.name+moment().format('x'), 'application/vnd.ms-excel')
}
}
}
</script>

vue2.x 将table 内容导出excel 下载(直接转换渲染数据)

VUElopo1983 发表了文章 • 0 个评论 • 2539 次浏览 • 2018-01-22 17:51 • 来自相关话题

https://github.com/jecovier/vue-json-excel
<template lang="pug">
btn(:stype="stype",:size="size",@click="generate")
slot
template(v-if="!$slots.default") {{label}}
</template>
<script>
// https://github.com/jecovier/vue-json-excel
import download from 'downloadjs'
import btn from '@/components/comp/button'
export default {
name: 'vbaJsonExcel',
components: {
btn
},
props: {
// btn 组件参数
label: String,
stype: String,
size: {
type: String,
default: 'sm'
},
// 设置导出格式 [xls, csv], 默认: xls
type: {
type: String,
default: 'xls'
},
// Json to download
data: {
type: Array,
required: true
},
// 导出的表格标题
// 若不设置将使用默认的json数据key
fields: {
type: Object,
required: true
},
// excel标题
title: {
type: String,
default: null
},
// 导出excel标题名称
name: {
type: String,
default: 'datas.xls'
},
meta: {
type: Array,
default: () =>
}
},
computed: {
// unique identifier
idName: function() {
var now = new Date().getTime()
return 'export_' + now
}
},
methods: {
generate() {
if (!this.data.length) {
return
}
let json = this.getProcessedJson(this.data, this.fields)
if (this.type == 'csv') {
return this.export(this.jsonToCSV(json), this.name, 'application/csv')
}
return this.export(
this.jsonToXLS(json),
this.name,
'application/vnd.ms-excel'
)
},
/*
Use downloadjs to generate the download link
*/
export: function(data, filename, mime) {
let blob = this.base64ToBlob(data, mime)
download(blob, filename, mime)
},
/*
jsonToXLS
---------------
Transform json data into an xml document with MS Excel format, sadly
this format show a prompt when open due to a default behavior
on Microsoft office. It's recommended to use CSV format instead.
*/
jsonToXLS: function(data) {
let xlsTemp =
'<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html4 ... Bmeta name=ProgId content=Excel.Sheet> <meta name=Generator content="Microsoft Excel 11"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>${table}</table></body></html>'
let xlsData = '<thead><tr>'

if (this.title != null) {
xlsData +=
'<tr><th colspan="' +
Object.keys(data[0]).length +
'">' +
this.title +
'<th></tr>'
}

for (let key in data[0]) {
xlsData += '<th>' + key + '</th>'
}
xlsData += '</tr></thead>'
xlsData += '<tbody>'

data.map(function(item, index) {
xlsData += '<tbody><tr>'
for (let key in item) {
xlsData += '<td>' + item[key] + '</td>'
}
xlsData += '</tr></tbody>'
})
return xlsTemp.replace('${table}', xlsData)
},
/*
jsonToCSV
---------------
Transform json data into an CSV file.
*/
jsonToCSV: function(data) {
var csvData = ''

if (this.title != null) {
csvData += this.title + '\r\n'
}

for (let key in data[0]) {
csvData += key + ','
}
csvData = csvData.slice(0, csvData.length - 1)
csvData += '\r\n'

data.map(function(item) {
for (let key in item) {
let escapedCSV = item[key] + '' // cast Numbers to string
if (escapedCSV.match(/[,"\n]/)) {
escapedCSV = '"' + escapedCSV.replace(/\"/g, '""') + '"'
}
csvData += escapedCSV + ','
}
csvData = csvData.slice(0, csvData.length - 1)
csvData += '\r\n'
})
return csvData
},
/*
getProcessedJson
---------------
Get only the data to export, if no fields are set return all the data
*/
getProcessedJson: function(data, header) {
let keys = this.getKeys(data, header)
let newData =
let _self = this
data.map(function(item, index) {
let newItem = {}
for (let label in keys) {
var iii = item
let property = keys[label]
newItem[label] = _self.getNestedData(property, item)
}
newData.push(newItem)
})

return newData
},
getKeys: function(data, header) {
if (header) {
return header
}

let keys = {}
for (let key in data[0]) {
keys[key] = key
}
return keys
},
getNestedData: function(key, item) {
let valueFromNestedKey = null
let keyNestedSplit = key.split('.')
valueFromNestedKey = item[keyNestedSplit[0]]
for (let j = 1; j < keyNestedSplit.length; j++) {
valueFromNestedKey = valueFromNestedKey[keyNestedSplit[j]]
}
return valueFromNestedKey
},
base64ToBlob: function(data, mime) {
let base64 = window.btoa(window.unescape(encodeURIComponent(data)))
let bstr = atob(base64)
let n = bstr.length
let u8arr = new Uint8ClampedArray(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
} // end methods
}
</script>


fileds 获取(该组件需要对标题进行格式化)
?
methods
setFields() {
let _this = this
let Obj = new Object()
let arr = this.$refs.tables.$slots.default
.filter(e => e.componentInstance)
.map((column, index) => {
const instance = column.componentOptions.propsData
return instance
})
arr.forEach(element => {
if (!!element['prop']) {
_this.xlsfields[element['label']] = element['prop']
}
})
}mounted
mounted() {
this.setFields()
} 查看全部

https://github.com/jecovier/vue-json-excel


<template lang="pug">
btn(:stype="stype",:size="size",@click="generate")
slot
template(v-if="!$slots.default") {{label}}
</template>
<script>
// https://github.com/jecovier/vue-json-excel
import download from 'downloadjs'
import btn from '@/components/comp/button'
export default {
name: 'vbaJsonExcel',
components: {
btn
},
props: {
// btn 组件参数
label: String,
stype: String,
size: {
type: String,
default: 'sm'
},
// 设置导出格式 [xls, csv], 默认: xls
type: {
type: String,
default: 'xls'
},
// Json to download
data: {
type: Array,
required: true
},
// 导出的表格标题
// 若不设置将使用默认的json数据key
fields: {
type: Object,
required: true
},
// excel标题
title: {
type: String,
default: null
},
// 导出excel标题名称
name: {
type: String,
default: 'datas.xls'
},
meta: {
type: Array,
default: () =>
}
},
computed: {
// unique identifier
idName: function() {
var now = new Date().getTime()
return 'export_' + now
}
},
methods: {
generate() {
if (!this.data.length) {
return
}
let json = this.getProcessedJson(this.data, this.fields)
if (this.type == 'csv') {
return this.export(this.jsonToCSV(json), this.name, 'application/csv')
}
return this.export(
this.jsonToXLS(json),
this.name,
'application/vnd.ms-excel'
)
},
/*
Use downloadjs to generate the download link
*/
export: function(data, filename, mime) {
let blob = this.base64ToBlob(data, mime)
download(blob, filename, mime)
},
/*
jsonToXLS
---------------
Transform json data into an xml document with MS Excel format, sadly
this format show a prompt when open due to a default behavior
on Microsoft office. It's recommended to use CSV format instead.
*/
jsonToXLS: function(data) {
let xlsTemp =
'<html xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns="http://www.w3.org/TR/REC-html4 ... Bmeta name=ProgId content=Excel.Sheet> <meta name=Generator content="Microsoft Excel 11"><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><!--[if gte mso 9]><xml><x:ExcelWorkbook><x:ExcelWorksheets><x:ExcelWorksheet><x:Name>{worksheet}</x:Name><x:WorksheetOptions><x:DisplayGridlines/></x:WorksheetOptions></x:ExcelWorksheet></x:ExcelWorksheets></x:ExcelWorkbook></xml><![endif]--></head><body><table>${table}</table></body></html>'
let xlsData = '<thead><tr>'

if (this.title != null) {
xlsData +=
'<tr><th colspan="' +
Object.keys(data[0]).length +
'">' +
this.title +
'<th></tr>'
}

for (let key in data[0]) {
xlsData += '<th>' + key + '</th>'
}
xlsData += '</tr></thead>'
xlsData += '<tbody>'

data.map(function(item, index) {
xlsData += '<tbody><tr>'
for (let key in item) {
xlsData += '<td>' + item[key] + '</td>'
}
xlsData += '</tr></tbody>'
})
return xlsTemp.replace('${table}', xlsData)
},
/*
jsonToCSV
---------------
Transform json data into an CSV file.
*/
jsonToCSV: function(data) {
var csvData = ''

if (this.title != null) {
csvData += this.title + '\r\n'
}

for (let key in data[0]) {
csvData += key + ','
}
csvData = csvData.slice(0, csvData.length - 1)
csvData += '\r\n'

data.map(function(item) {
for (let key in item) {
let escapedCSV = item[key] + '' // cast Numbers to string
if (escapedCSV.match(/[,"\n]/)) {
escapedCSV = '"' + escapedCSV.replace(/\"/g, '""') + '"'
}
csvData += escapedCSV + ','
}
csvData = csvData.slice(0, csvData.length - 1)
csvData += '\r\n'
})
return csvData
},
/*
getProcessedJson
---------------
Get only the data to export, if no fields are set return all the data
*/
getProcessedJson: function(data, header) {
let keys = this.getKeys(data, header)
let newData =
let _self = this
data.map(function(item, index) {
let newItem = {}
for (let label in keys) {
var iii = item
let property = keys[label]
newItem[label] = _self.getNestedData(property, item)
}
newData.push(newItem)
})

return newData
},
getKeys: function(data, header) {
if (header) {
return header
}

let keys = {}
for (let key in data[0]) {
keys[key] = key
}
return keys
},
getNestedData: function(key, item) {
let valueFromNestedKey = null
let keyNestedSplit = key.split('.')
valueFromNestedKey = item[keyNestedSplit[0]]
for (let j = 1; j < keyNestedSplit.length; j++) {
valueFromNestedKey = valueFromNestedKey[keyNestedSplit[j]]
}
return valueFromNestedKey
},
base64ToBlob: function(data, mime) {
let base64 = window.btoa(window.unescape(encodeURIComponent(data)))
let bstr = atob(base64)
let n = bstr.length
let u8arr = new Uint8ClampedArray(n)
while (n--) {
u8arr[n] = bstr.charCodeAt(n)
}
return new Blob([u8arr], { type: mime })
}
} // end methods
}
</script>


fileds 获取(该组件需要对标题进行格式化)
?
methods
    setFields() {
let _this = this
let Obj = new Object()
let arr = this.$refs.tables.$slots.default
.filter(e => e.componentInstance)
.map((column, index) => {
const instance = column.componentOptions.propsData
return instance
})
arr.forEach(element => {
if (!!element['prop']) {
_this.xlsfields[element['label']] = element['prop']
}
})
}
mounted
mounted() {
this.setFields()
}

axios

每天进步一点点戏子 发表了文章 • 0 个评论 • 1697 次浏览 • 2018-01-16 11:25 • 来自相关话题

// src/api/index.js
import axios from 'axios'
const instance = axios.create({
// 根据自己的业务配置
baseURL: '/api',
withCredentials: true
})
instance.interceptors.request.use(config => {
// request 拦截器
// 比如添加 token
return config
})
instance.interceptors.response.use(response => {
// 返回数据
return response.data
}, error => {
// 处理错误码,比如 404跳转
return Promise.reject(error);
})
export default instance// src/main.js
import api from './api'
// 获取列表
api.get('users').then(response => {
console.log(response)
})
// 获取单个
api.get('users/1').then(response => {
console.log(response)
})
// 添加
api.post('users', { name: 'lopo' }).then(response => {
console.log(response)
})
// 修改
api.put('users/1', { name: 'vlopo' }).then(response => {
console.log(response)
})
// 删除
api.delete('users/1').then(response => {
console.log(response)
})?
?
? 查看全部
// src/api/index.js
import axios from 'axios'
const instance = axios.create({
// 根据自己的业务配置
baseURL: '/api',
withCredentials: true
})
instance.interceptors.request.use(config => {
// request 拦截器
// 比如添加 token
return config
})
instance.interceptors.response.use(response => {
// 返回数据
return response.data
}, error => {
// 处理错误码,比如 404跳转
return Promise.reject(error);
})
export default instance
// src/main.js
import api from './api'
// 获取列表
api.get('users').then(response => {
console.log(response)
})
// 获取单个
api.get('users/1').then(response => {
console.log(response)
})
// 添加
api.post('users', { name: 'lopo' }).then(response => {
console.log(response)
})
// 修改
api.put('users/1', { name: 'vlopo' }).then(response => {
console.log(response)
})
// 删除
api.delete('users/1').then(response => {
console.log(response)
})
?
?
?

vue-cli 模拟数据配置

VUE戏子 发表了文章 • 0 个评论 • 1727 次浏览 • 2018-01-16 11:13 • 来自相关话题

build/webpack.dev.conf.js
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,

// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay ?
{ warnings: false, errors: true } :
false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
},
before(app) {
app.get('/api/a', (req, res) => {
if (res.json) {
res.json({
errno: 0,
data: 'AA'
})
}
})
app.get('/api/b', (req, res) => {
if (res.json) {
res.json({
errno: 0,
data: 'BB'
})
}
})
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwir ... lugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}])
]
})

module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port

// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors ?
utils.createNotifierCallback() :
undefined
}))

resolve(devWebpackConfig)
}
})
}) 查看全部
build/webpack.dev.conf.js
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')

const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)

const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,

// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay ?
{ warnings: false, errors: true } :
false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
},
before(app) {
app.get('/api/a', (req, res) => {
if (res.json) {
res.json({
errno: 0,
data: 'AA'
})
}
})
app.get('/api/b', (req, res) => {
if (res.json) {
res.json({
errno: 0,
data: 'BB'
})
}
})
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwir ... lugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}])
]
})

module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port

// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors ?
utils.createNotifierCallback() :
undefined
}))

resolve(devWebpackConfig)
}
})
})

axios RESTful 接口封装....(进一步优化版本)

VUElopo1983 发表了文章 • 0 个评论 • 4139 次浏览 • 2018-01-15 04:23 • 来自相关话题

import axios from 'axios'
import { baseUrl, localUrl } from '@/config/env'
import Vue from 'vue'
import vuex from 'vuex'
import store from '../store'
const instance = axios.create()
instance.defaults.baseURL = baseUrl
instance.interceptors.request.use(
function(config) {
if (Lockr.get('token')) {
config.headers.common['Authorization'] = Lockr.get('token')
}
return config
},
error => {
return Promise.reject(error)
}
)
instance.interceptors.response.use(
res => {
if (res.data.code) {
switch (res.data.code) {
case 401:
Lockr.rm('token')
window.location.href = '/#/admin/login/'
break
}
} else {
}
return res
},
err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '请求错误'
break
case 401:
err.message = '授权失败,请检查token'
break
case 403:
err.message = '拒绝访问'
break
case 404:
err.message = `请求${err.response.config.url
.split('/')
.pop()
.replace(/\.html/, '')}接口出错`
break
case 408:
err.message = '请求超时'
break
case 500:
err.message = '服务器内部错误'
break
case 501:
err.message = '服务未实现'
break
case 502:
err.message = '网关错误'
break
case 503:
err.message = '服务不可用'
break
case 504:
err.message = '网关超时'
break
case 505:
err.message = 'HTTP版本不受支持'
break
default:
}
}
store.commit('setModal', err.message)
return Promise.reject(err)
}
)
export function ajax(url, params, type) {
let config = { method: type || 'post' }
if (type === 'get') {
config.params = params
} else if (type === 'put' || type === 'patch' || type === 'delete') {
config.data = type ? {} : params
config.headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
config.transformRequest = [
() => {
let ret = new URLSearchParams()
for (let key in params) {
ret.append(key, params[key])
}
return ret
}
]
} else {
config.data = type ? {} : params
config.headers = { 'Content-Type': 'multipart/form-data' }
config.transformRequest = [
() => {
if (!_.isPlainObject(params)) {
if (params instanceof FormData) {
return params
} else {
let ret = new FormData(params)
return ret
}
} else {
let ret = new FormData()
for (var key in params) {
ret.append(key, params[key])
}
return ret
}
}
]
}
return instance(url, config).then(response => {
return response.data
})
} 查看全部
import axios from 'axios'
import { baseUrl, localUrl } from '@/config/env'
import Vue from 'vue'
import vuex from 'vuex'
import store from '../store'
const instance = axios.create()
instance.defaults.baseURL = baseUrl
instance.interceptors.request.use(
function(config) {
if (Lockr.get('token')) {
config.headers.common['Authorization'] = Lockr.get('token')
}
return config
},
error => {
return Promise.reject(error)
}
)
instance.interceptors.response.use(
res => {
if (res.data.code) {
switch (res.data.code) {
case 401:
Lockr.rm('token')
window.location.href = '/#/admin/login/'
break
}
} else {
}
return res
},
err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '请求错误'
break
case 401:
err.message = '授权失败,请检查token'
break
case 403:
err.message = '拒绝访问'
break
case 404:
err.message = `请求${err.response.config.url
.split('/')
.pop()
.replace(/\.html/, '')}接口出错`
break
case 408:
err.message = '请求超时'
break
case 500:
err.message = '服务器内部错误'
break
case 501:
err.message = '服务未实现'
break
case 502:
err.message = '网关错误'
break
case 503:
err.message = '服务不可用'
break
case 504:
err.message = '网关超时'
break
case 505:
err.message = 'HTTP版本不受支持'
break
default:
}
}
store.commit('setModal', err.message)
return Promise.reject(err)
}
)
export function ajax(url, params, type) {
let config = { method: type || 'post' }
if (type === 'get') {
config.params = params
} else if (type === 'put' || type === 'patch' || type === 'delete') {
config.data = type ? {} : params
config.headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
config.transformRequest = [
() => {
let ret = new URLSearchParams()
for (let key in params) {
ret.append(key, params[key])
}
return ret
}
]
} else {
config.data = type ? {} : params
config.headers = { 'Content-Type': 'multipart/form-data' }
config.transformRequest = [
() => {
if (!_.isPlainObject(params)) {
if (params instanceof FormData) {
return params
} else {
let ret = new FormData(params)
return ret
}
} else {
let ret = new FormData()
for (var key in params) {
ret.append(key, params[key])
}
return ret
}
}
]
}
return instance(url, config).then(response => {
return response.data
})
}

ES6常用新特性(vue中常用)

javascript/jQuerylopo1983 发表了文章 • 0 个评论 • 1753 次浏览 • 2018-01-10 09:07 • 来自相关话题

刚开始用vue或者react,很多时候我们都会把ES6这个大兄弟加入我们的技术栈中。但是ES6那么多那么多特性,掌握好常用的。
?1.let 和 const 命令
?
let和const来声明,let表示变量、const表示常量。let和const都是块级作用域。
?
什么是会计作用域?
?{}大括号内的代码块即为let 和 const的作用域。
案例 向一个数组中插入0~9//
var funcs =
for (var i = 0; i < 10; i++) {
funcs.push(function() { console.log(i) })
}
funcs.forEach(function(func) {
func()
})

//
// ES5告诉我们可以利用闭包解决这个问题
var funcs =
for (var i = 0; i < 10; i++) {
func.push((function(value) {
return function() {
console.log(value)
}
}(i)))
}
// es6
for (let i = 0; i < 10; i++) {
func.push(function() {
console.log(i)
})
}
。2.模板字符串
js 拼接模板很头疼,es5 之前 += + 各种“” ‘’
?
es6直接`` //es5
var name = 'lopo'
console.log('hello' + name)
//es6
const name = 'lopo'
console.log(`hello ${name}`) //hello lopo
console.log(`hello ${name==='xz'?'213':'hehe'}`) // hello hehe
3.函数
?函数默认值
es6 可为参数提供默认值,以方便初始化//es5
function action(num) {
num = num || 200
//当传入num时,num为传入的值
//当没传入参数时,num即有了默认值200
return num
}
//es6
function action(num = 200) {
console.log(num)
}
action() //200
action(300) //300


箭头函数
?
ES6很有意思的一部分就是函数的快捷写法。也就是箭头函数。
箭头函数最直观的三个特点。
不需要function关键字来创建函数省略return关键字继承当前上下文的 this 关键字
//es5
[1,2,3].map((function(x){
return x + 1
}).bind(this))
//es6 仅有一个参数的时候,是可以省略掉括号的
[1,2,3].map( x => {x + 1} )
[1,2,3].map( x => x + 1 )
//有参数
var people = (name, age) => {
const fullName = 'h' + name
return fullName
} ?
.....未完待续...... 查看全部

刚开始用vue或者react,很多时候我们都会把ES6这个大兄弟加入我们的技术栈中。但是ES6那么多那么多特性,掌握好常用的。


?1.let 和 const 命令
?
let和const来声明,let表示变量、const表示常量。let和const都是块级作用域。
?
什么是会计作用域?

?{}大括号内的代码块即为let 和 const的作用域。


案例 向一个数组中插入0~9
//
var funcs =
for (var i = 0; i < 10; i++) {
funcs.push(function() { console.log(i) })
}
funcs.forEach(function(func) {
func()
})

//
// ES5告诉我们可以利用闭包解决这个问题
var funcs =
for (var i = 0; i < 10; i++) {
func.push((function(value) {
return function() {
console.log(value)
}
}(i)))
}
// es6
for (let i = 0; i < 10; i++) {
func.push(function() {
console.log(i)
})
}
2.模板字符串
js 拼接模板很头疼,es5 之前 += + 各种“” ‘’
?
es6直接``
    //es5 
var name = 'lopo'
console.log('hello' + name)
//es6
const name = 'lopo'
console.log(`hello ${name}`) //hello lopo
console.log(`hello ${name==='xz'?'213':'hehe'}`) // hello hehe

3.函数
?函数默认值
es6 可为参数提供默认值,以方便初始化
//es5
function action(num) {
num = num || 200
//当传入num时,num为传入的值
//当没传入参数时,num即有了默认值200
return num
}
//es6
function action(num = 200) {
console.log(num)
}
action() //200
action(300) //300


箭头函数
?
ES6很有意思的一部分就是函数的快捷写法。也就是箭头函数。
箭头函数最直观的三个特点。
  • 不需要function关键字来创建函数
  • 省略return关键字
  • 继承当前上下文的 this 关键字

//es5
[1,2,3].map((function(x){
return x + 1
}).bind(this))
//es6 仅有一个参数的时候,是可以省略掉括号的
[1,2,3].map( x => {x + 1} )
[1,2,3].map( x => x + 1 )
//有参数
var people = (name, age) => {
const fullName = 'h' + name
return fullName
}
?
.....未完待续......

RESTful 标准的axios封装(vue2.x)

VUElopo1983 发表了文章 • 0 个评论 • 2103 次浏览 • 2018-01-04 16:54 • 来自相关话题

export function ajax(url, params, type) {
let config = { method: type || 'post' }
if (type === 'get') {
config.params = params
} else if (type === 'put' || type === 'patch' || type === 'delete') {
config.data = type ? {} : params
config.headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
config.transformRequest = [
() => {
let ret = new URLSearchParams()
for (let key in params) {
ret.append(key, params[key])
}
return ret
}
]
} else {
config.data = type ? {} : params
}
return instance(url, config).then(response => {
return response.data
})
}?
?
instance.interceptors.response.use(
res => {
if (res.data.code) {
switch (res.data.code) {
case 401:
Lockr.rm('token')
window.location.href = '/#/admin/login/'
break
}
} else {
}
return res
},
err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '请求错误'
break
case 401:
err.message = '授权失败,请检查token'
break
case 403:
err.message = '拒绝访问'
break
case 404:
err.message = `请求${err.response.config.url
.split('/')
.pop()
.replace(/\.html/, '')}接口出错`
break
case 408:
err.message = '请求超时'
break
case 500:
err.message = '服务器内部错误'
break
case 501:
err.message = '服务未实现'
break
case 502:
err.message = '网关错误'
break
case 503:
err.message = '服务不可用'
break
case 504:
err.message = '网关超时'
break
case 505:
err.message = 'HTTP版本不受支持'
break
default:
}
}
store.commit('setModal', err.message)
return Promise.reject(err)
}
) 查看全部
export function ajax(url, params, type) {
let config = { method: type || 'post' }
if (type === 'get') {
config.params = params
} else if (type === 'put' || type === 'patch' || type === 'delete') {
config.data = type ? {} : params
config.headers = { 'Content-Type': 'application/x-www-form-urlencoded' }
config.transformRequest = [
() => {
let ret = new URLSearchParams()
for (let key in params) {
ret.append(key, params[key])
}
return ret
}
]
} else {
config.data = type ? {} : params
}
return instance(url, config).then(response => {
return response.data
})
}
?
?
instance.interceptors.response.use(
res => {
if (res.data.code) {
switch (res.data.code) {
case 401:
Lockr.rm('token')
window.location.href = '/#/admin/login/'
break
}
} else {
}
return res
},
err => {
if (err && err.response) {
switch (err.response.status) {
case 400:
err.message = '请求错误'
break
case 401:
err.message = '授权失败,请检查token'
break
case 403:
err.message = '拒绝访问'
break
case 404:
err.message = `请求${err.response.config.url
.split('/')
.pop()
.replace(/\.html/, '')}接口出错`
break
case 408:
err.message = '请求超时'
break
case 500:
err.message = '服务器内部错误'
break
case 501:
err.message = '服务未实现'
break
case 502:
err.message = '网关错误'
break
case 503:
err.message = '服务不可用'
break
case 504:
err.message = '网关超时'
break
case 505:
err.message = 'HTTP版本不受支持'
break
default:
}
}
store.commit('setModal', err.message)
return Promise.reject(err)
}
)

FormData 对象的使用

每天进步一点点lopo1983 发表了文章 • 0 个评论 • 1710 次浏览 • 2018-01-03 21:21 • 来自相关话题

通过FormData对象可以组装一组用 XMLHttpRequest发送请求的键/值对。它可以更灵活方便的发送表单数据,因为可以独立于表单使用。如果你把表单的编码类型设置为multipart/form-data ,则通过FormData传输的数据格式和表单通过submit() 方法传输的数据格式相同
FormData类型其实是在XMLHttpRequest 2级定义的,它是为序列化表以及创建与表单格式相同的数据(当然是用于XHR传输)提供便利。var formData = new FormData();

formData.append("username", "Groucho");
formData.append("accountnum", 123456); // 数字 123456 会被立即转换成字符串 "123456"

// HTML 文件类型input,由用户选择
formData.append("userfile", fileInputElement.files[0]);

// JavaScript file-like 对象
var content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的正文...
var blob = new Blob([content], { type: "text/xml"});

formData.append("webmasterfile", blob);

var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php");
request.send(formData);1.概述
FormData类型其实是在XMLHttpRequest 2级定义的,它是为序列化表以及创建与表单格式相同的数据(当然是用于XHR传输)提供便利。
2. 构造函数# template
<form id="myForm" action="" method="post">
<input type="text" name="name">名字
<input type="password" name="psw">密码
<input type="submit" value="提交">
</form>
# js
// 获取页面已有的一个form表单
var form = document.getElementById("myForm");
// 用表单来初始化
var formData = new FormData(form);
// 我们可以根据name来访问表单中的字段
var name = formData.get("name"); // 获取名字
var psw = formData.get("psw"); // 获取密码
// 当然也可以在此基础上,添加其他数据
formData.append("token","kshdfiwi3rh");
?3. 操作方法
?formData里面存储的数据形式,一对key/value组成一条数据
?
key : [value,vaule1,value2]
key1 : value3
?
获取(get\getAll)formData.get("key");// return value
formData.getAll("key");// return [value,vaule1,value2]
?添加(append)
?
指定的key不存在则会新增一条数据,如果key存在,则添加到数据的末尾const formdata = new FormDara()
formdata.append('key','value1')
formdata.append('key','value2')

formdata.get('key') //return value1
formdata.getAll('key') //return [value1,value2]
?设置(set)formdata.set('key','value1')
判断是否有对应的key(has) 返回Boolean
注意是判断key 不是 valueformData.has("key"); // true
formData.has("dawang"); // false
删除(del)
注意是删除key 及对应的值formData.delete("key");
遍历迭代器(entries(),values())var i = formData.values();

i.next(); // {done:false, value:"v1"}
i.next(); // {done:fase, value:"v2"}
i.next(); // {done:fase, value:"v1"}
i.next(); // {done:true, value:undefined}

var i = formData.entries();

i.next(); // {done:false, value:["k1", "v1"]}
i.next(); // {done:fase, value:["k1", "v2"]}
i.next(); // {done:fase, value:["k2", "v1"]}
i.next(); // {done:true, value:undefined}
?
?VUE
// template
Forms(:state="formstate",:formMethod="updateInfo",ref="sendinfo",v-if="step!=3")
...

//javascript
update(ref, db, id) {
let def = this.$refs[`${ref}`].$el
api.update(def, db, id)
// api
update(def, db, id) {
let data = new FormData(def)
data.append('id', id)
return ajax('update' + db+'info', data)
},

? 查看全部

通过FormData对象可以组装一组用 XMLHttpRequest发送请求的键/值对。它可以更灵活方便的发送表单数据,因为可以独立于表单使用。如果你把表单的编码类型设置为multipart/form-data ,则通过FormData传输的数据格式和表单通过submit() 方法传输的数据格式相同


FormData类型其实是在XMLHttpRequest 2级定义的,它是为序列化表以及创建与表单格式相同的数据(当然是用于XHR传输)提供便利。
var formData = new FormData();

formData.append("username", "Groucho");
formData.append("accountnum", 123456); // 数字 123456 会被立即转换成字符串 "123456"

// HTML 文件类型input,由用户选择
formData.append("userfile", fileInputElement.files[0]);

// JavaScript file-like 对象
var content = '<a id="a"><b id="b">hey!</b></a>'; // 新文件的正文...
var blob = new Blob([content], { type: "text/xml"});

formData.append("webmasterfile", blob);

var request = new XMLHttpRequest();
request.open("POST", "http://foo.com/submitform.php";);
request.send(formData);
1.概述
FormData类型其实是在XMLHttpRequest 2级定义的,它是为序列化表以及创建与表单格式相同的数据(当然是用于XHR传输)提供便利。
2. 构造函数
# template
<form id="myForm" action="" method="post">
<input type="text" name="name">名字
<input type="password" name="psw">密码
<input type="submit" value="提交">
</form>
# js
// 获取页面已有的一个form表单
var form = document.getElementById("myForm");
// 用表单来初始化
var formData = new FormData(form);
// 我们可以根据name来访问表单中的字段
var name = formData.get("name"); // 获取名字
var psw = formData.get("psw"); // 获取密码
// 当然也可以在此基础上,添加其他数据
formData.append("token","kshdfiwi3rh");

?3. 操作方法
?formData里面存储的数据形式,一对key/value组成一条数据
?
key : [value,vaule1,value2]
key1 : value3
?
获取(get\getAll)
formData.get("key");// return value
formData.getAll("key");// return [value,vaule1,value2]

?添加(append)
?
指定的key不存在则会新增一条数据,如果key存在,则添加到数据的末尾
const formdata = new FormDara()
formdata.append('key','value1')
formdata.append('key','value2')

formdata.get('key') //return value1
formdata.getAll('key') //return [value1,value2]

?设置(set)
formdata.set('key','value1')

判断是否有对应的key(has) 返回Boolean
注意是判断key 不是 value
formData.has("key"); // true
formData.has("dawang"); // false

删除(del)
注意是删除key 及对应的值
formData.delete("key");

遍历迭代器(entries(),values())
var i = formData.values();

i.next(); // {done:false, value:"v1"}
i.next(); // {done:fase, value:"v2"}
i.next(); // {done:fase, value:"v1"}
i.next(); // {done:true, value:undefined}

var i = formData.entries();

i.next(); // {done:false, value:["k1", "v1"]}
i.next(); // {done:fase, value:["k1", "v2"]}
i.next(); // {done:fase, value:["k2", "v1"]}
i.next(); // {done:true, value:undefined}

?
?VUE
// template
Forms(:state="formstate",:formMethod="updateInfo",ref="sendinfo",v-if="step!=3")
...

//javascript
update(ref, db, id) {
let def = this.$refs[`${ref}`].$el
api.update(def, db, id)
// api
update(def, db, id) {
let data = new FormData(def)
data.append('id', id)
return ajax('update' + db+'info', data)
},


?

Vue axios 封装 拦截示例

VUElopo1983 发表了文章 • 0 个评论 • 2118 次浏览 • 2018-01-03 04:42 • 来自相关话题

?
封装export function ajax(url, params, type) {
let config = { method: type || 'post' }
if (type === 'GET') {
config.params = params
} else {
config.data = type ? {} : params
}
console.log(config)
return instance(url, config)
.then(response => {
return response.data
})
.catch(error => {
console.log('通信失败,请检查您的网络,或联系系统管理员')
})
}


?REQ拦截instance.interceptors.request.use(
function(config) {
if (Lockr.get('token')) {
config.headers.common['Authorization'] = Lockr.get('token')
}
return config
},
error => {
return Promise.reject(error)
}
)


RES拦截instance.interceptors.response.use(res => {
if (res.data.code) {
switch (res.data.code) {
case 401:
Lockr.rm('token')
window.location.href = '/#/admin/login/'
break
}
} else {
}
return res
})


?
使用FormData传递数据const instance = axios.create()
instance.defaults.headers.post['Content-Type'] = 'multipart/form-data'
instance.defaults.headers.put['Content-Type'] = 'multipart/form-data'
instance.defaults.headers.patch['Content-Type'] = 'multipart/form-data'



?使用接口
export default {
getList(display = '7', page = '1', db, type = '1') {
let params = {
'display':display,
'current':page,
'type':type
}
return ajax(db, params,'GET')
},
//
putList(db,id) {
let data = new FormData()
data.append('id',id)
return ajax(db, data,'PATCH')
}}


? 查看全部
?
封装
export function ajax(url, params, type) {
let config = { method: type || 'post' }
if (type === 'GET') {
config.params = params
} else {
config.data = type ? {} : params
}
console.log(config)
return instance(url, config)
.then(response => {
return response.data
})
.catch(error => {
console.log('通信失败,请检查您的网络,或联系系统管理员')
})
}


?REQ拦截
instance.interceptors.request.use(
function(config) {
if (Lockr.get('token')) {
config.headers.common['Authorization'] = Lockr.get('token')
}
return config
},
error => {
return Promise.reject(error)
}
)


RES拦截
instance.interceptors.response.use(res => {
if (res.data.code) {
switch (res.data.code) {
case 401:
Lockr.rm('token')
window.location.href = '/#/admin/login/'
break
}
} else {
}
return res
})


?
使用FormData传递数据
const instance = axios.create()
instance.defaults.headers.post['Content-Type'] = 'multipart/form-data'
instance.defaults.headers.put['Content-Type'] = 'multipart/form-data'
instance.defaults.headers.patch['Content-Type'] = 'multipart/form-data'



?使用接口

export default {
getList(display = '7', page = '1', db, type = '1') {
let params = {
'display':display,
'current':page,
'type':type
}
return ajax(db, params,'GET')
},
//
putList(db,id) {
let data = new FormData()
data.append('id',id)
return ajax(db, data,'PATCH')
}}


?

关于RESTful(仅供参考)

每天进步一点点lopo1983 发表了文章 • 0 个评论 • 1488 次浏览 • 2018-01-03 03:53 • 来自相关话题

Request 和 Response?
GET(SELECT):从服务器取出资源(一项或多项)POST(CREATE):在服务器新建一个资源PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)DELETE(DELETE):从服务器删除资源
??
PATCH 方法用来更新局部资源?
PUT 方法用来更新完整的资源
PATCH 与 PUT 属性上的一个重要区别还在于:PUT 是幂等的,而 PATCH 不是幂等的
?
参考?理解HTTP幂等性,RESTful 手册
??
当GET,PUT和PATCH请求成功时,要返回对应的数据,及状态码200,即SUCCESS当POST创建数据成功时,要返回创建的数据,及状态码201,即CREATED当DELETE删除数据成功时,不返回数据,状态码要返回204,即NO CONTENT当GET不到数据时,状态码要返回404,即NOT FOUND任何时候,如果请求有问题,如校验请求数据时发现错误,要返回状态码400,即BAD REQUEST当API 请求需要用户认证时,如果request中的认证信息不正确,要返回状态码401,即NOT AUTHORIZED当API 请求需要验证用户权限时,如果当前用户无相应权限,要返回状态码403,即FORBIDDEN

JSON
Number可以表示整数和浮点数。Boolean可以表示真假,值为true或false。String表示一个字符串。Null通常用于表示空对象。
?
返回的数据包含在http响应体中。数据?必须(MUST)?是一个JSON Object。该Object可能包含3个字段:状态,状态信息,数据,版本号(如需要的话)。
{
"code": 200,
"msg": {
"text": "参数错误",
"parameters": {
"email": "电子邮件格式不正确"
}
},
"data": {
"data": [
{
"name": "Google",
"url": "http://www.google.com"
}
],
"dateSelect": [
"2018-1-1",
"2018-1-3"
],
"has_next": true,
"has_prev": false,
"page": 0,
"pageSize": 1,
"keyword": "",
"totle": 20
},
"version": "3.0.2"
}?
URL Rules
?
包含版本信息/api/v1/order/
/api/v2/order/







url是指向资源的,而不是描述行为# Bad APIs
/api/getOrder/1/
/api/updateOrder/1/
/api/deleteOrder/1/

# Good APIs
/api/Order/1/
避免浏览器默认行为的安全问题 确保GET和HEAD方法必须始终是安全的# Bad APIs

# [DELETE]
/api/Order?id=1
通过url参数对资源进行过滤/api/Order&display=15&current=1&type=1
至于编写RESTful API时到底应采用哪种方式,TMD 你想怎么玩就这么玩 别挖坑就好。
?
? 查看全部
Request 和 Response?
  1. GET(SELECT):从服务器取出资源(一项或多项)
  2. POST(CREATE):在服务器新建一个资源
  3. PUT(UPDATE):在服务器更新资源(客户端提供完整资源数据)
  4. PATCH(UPDATE):在服务器更新资源(客户端提供需要修改的资源数据)
  5. DELETE(DELETE):从服务器删除资源

??

PATCH 方法用来更新局部资源?
PUT 方法用来更新完整的资源
PATCH 与 PUT 属性上的一个重要区别还在于:PUT 是幂等的,而 PATCH 不是幂等的
?
参考?理解HTTP幂等性RESTful 手册


??
  • GET,PUTPATCH请求成功时,要返回对应的数据,及状态码200,即SUCCESS
  • POST创建数据成功时,要返回创建的数据,及状态码201,即CREATED
  • DELETE删除数据成功时,不返回数据,状态码要返回204,即NO CONTENT
  • GET不到数据时,状态码要返回404,即NOT FOUND
  • 任何时候,如果请求有问题,如校验请求数据时发现错误,要返回状态码400,即BAD REQUEST
  • 当API 请求需要用户认证时,如果request中的认证信息不正确,要返回状态码401,即NOT AUTHORIZED
  • 当API 请求需要验证用户权限时,如果当前用户无相应权限,要返回状态码403,即FORBIDDEN


JSON
  • Number可以表示整数和浮点数。
  • Boolean可以表示真假,值为true或false。
  • String表示一个字符串。
  • Null通常用于表示空对象。

?

返回的数据包含在http响应体中。数据?必须(MUST)?是一个JSON Object。该Object可能包含3个字段:状态,状态信息,数据,版本号(如需要的话)。


{
"code": 200,
"msg": {
"text": "参数错误",
"parameters": {
"email": "电子邮件格式不正确"
}
},
"data": {
"data": [
{
"name": "Google",
"url": "http://www.google.com"
}
],
"dateSelect": [
"2018-1-1",
"2018-1-3"
],
"has_next": true,
"has_prev": false,
"page": 0,
"pageSize": 1,
"keyword": "",
"totle": 20
},
"version": "3.0.2"
}
?
URL Rules
?
包含版本信息
/api/v1/order/
/api/v2/order/







url是指向资源的,而不是描述行为
# Bad APIs
/api/getOrder/1/
/api/updateOrder/1/
/api/deleteOrder/1/

# Good APIs
/api/Order/1/

避免浏览器默认行为的安全问题 确保GET和HEAD方法必须始终是安全的
# Bad APIs

# [DELETE]
/api/Order?id=1

通过url参数对资源进行过滤
/api/Order&display=15&current=1&type=1

至于编写RESTful API时到底应采用哪种方式,TMD 你想怎么玩就这么玩 别挖坑就好。
?
?