1. 品牌管理案例
实现功能:
- 添加新品牌:
add
- 删除品牌:数组循环,根据 ID 查找索引,调用
splice
方法删除 - 根据品牌名过滤:数组循环
- 格式化时间:过滤器
- 时间补全:
padStart()
, ES6 新增, 如:2020-2-6
补全后为2020-02-06
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
</head>
<body>
<div id="app">
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">添加品牌</h3>
</div>
<div class="panel-body form-inline">
<label>
Id:
<input type="text" class="form-control" v-model="id">
</label>
<label>
Name:
<input type="text" class="form-control" v-model="name">
</label>
<!-- 在Vue中,使用事件绑定机制,为元素指定处理函数的时候,如果加了小括号,就可以给函数传参了 -->
<input type="button" value="添加" class="btn btn-primary" @click="add()">
<label>
搜索名称关键字:
<input type="text" class="form-control" v-model="keywords">
</label>
</div>
</div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>Id</th>
<th>Name</th>
<th>Ctime</th>
<th>Operation</th>
</tr>
</thead>
<tbody>
<tr v-for="item in search(keywords)">
<td>{{ item.id }}</td>
<td v-text="item.name"></td>
<td>{{ item.ctime | dateFormat() }}</td>
<td>
<a href="/" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
// 自定义过滤器
Vue.filter('dateFormat', function(dateStr, pattern = "") {
var dt = new Date(dateStr)
var y = dt.getFullYear()
var m = (dt.getMonth() + 1).toString().padStart(2, '0')
var d = (dt.getDate()).toString().padStart(2, '0')
if (pattern.toLowerCase === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
} else {
var hh= (dt.getHours()).toString().padStart(2, '0')
var mm = (dt.getMinutes()).toString().padStart(2, '0')
var ss = (dt.getSeconds()).toString().padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
})
var vm = new Vue({
el: '#app',
data: {
id: '',
name: '',
keywords: '',
list: [
{ id: 1, name: '奔驰', ctime: new Date() },
{ id: 2, name: '宝马', ctime: new Date() }
]
},
methods: {
add() {
var newData = { id: this.id, name: this.name, ctime: new Date() };
this.list.push(newData);
this.id = this.name = ''
},
del(id) {
// 根据 id 查找数组索引,再根据索引删除元素
var index = this.list.findIndex(item => {
if (item.id === id) {
return true;
}
})
this.list.splice(index, 1)
},
search(keywords) {
// 根据关键字搜索
// var newList = []
// this.list.forEach(item => {
// if (item.name.indexOf(keywords) != -1) {
// newList.push(item)
// }
// })
// return newList
// ES6 中 String.prototype.includes('要包含的字符串')
return this.list.filter(item => {
if (item.name.includes(keywords)) {
return item
}
})
}
}
})
</script>
</body>
</html>
2. 过滤器
过滤器定义语法:
Vue.filter('过滤器的名称', function(参数一, 参数二...){})
过滤器中的 function
,第一个参数,永远都是过滤器管道符前面传递过来的数据。
使用:
{{ name | 过滤器的名称 }}
2.1 全局过滤器
<td>{{ item.ctime | dateFormat() }}</td>
// 自定义过滤器
Vue.filter('dateFormat', function(dateStr, pattern = "") {
var dt = new Date(dateStr)
var y = dt.getFullYear()
var m = (dt.getMonth() + 1).toString().padStart(2, '0')
var d = (dt.getDate()).toString().padStart(2, '0')
if (pattern.toLowerCase === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
} else {
var hh= (dt.getHours()).toString().padStart(2, '0')
var mm = (dt.getMinutes()).toString().padStart(2, '0')
var ss = (dt.getSeconds()).toString().padStart(2, '0')
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
})
// Vue 实例
var vm = new Vue({
})
Tips:全局过滤器在全局 Vue 实例中使用
2.1 私有过滤器
私有过滤器在 Vue
实例中定义:
<div id="app2">
<h3>{{ dt | dateFormat }}</h3>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
// 自定义过滤器
Vue.filter('dateFormat', function (dateStr, pattern = "") {
var dt = new Date(dateStr)
var y = dt.getFullYear()
var m = dt.getMonth() + 1
var d = dt.getDate()
if (pattern.toLowerCase === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
} else {
var hh = dt.getHours()
var mm = dt.getMinutes()
var ss = dt.getSeconds()
return `${y}-${m}-${d} ${hh}:${mm}:${ss}`
}
})
var vm2 = new Vue({
el: '#app2',
data: {
dt: new Date()
},
filters: {
dateFormat: function (dateStr, pattern = '') {
var dt = new Date(dateStr)
var y = dt.getFullYear()
var m = dt.getMonth() + 1
var d = dt.getDate()
if (pattern.toLowerCase === 'yyyy-mm-dd') {
return `${y}-${m}-${d}`
} else {
var hh = dt.getHours()
var mm = dt.getMinutes()
var ss = dt.getSeconds()
return `${y}-${m}-${d} ${hh}:${mm}:${ss}~~~`
}
}
}
})
</script>
Tips:若私有过滤器与全局过滤器名字一致,则采取就近原则,即使用私有过滤器!
3. 键盘修饰符和自定义键盘修饰符
全部按键别名:enter、tab、delete(捕获删除和退格)、esc、up、down、left、right、ctrl、alt、shift、meta
// 回车触发 add 事件
<input type="text" class="form-control" v-model="name" v-on:keyup.13="add">
// 简写 使用 keycode
<input type="text" class="form-control" v-model="name" @keyup.13="add">
// 或者使用按键别名
<input type="text" class="form-control" v-model="name" @keyup.enter="add">
自定义按键修饰符
我们自己也可以自定义按键修饰符,便于记忆。
// 配置,
Vue.config.keyCodes.f2 = 113;
// 使用
<input type="text" v-model="name" @keyup.f2="add">
参考文档:
- js 里面的键盘事件对应的键码:
https://www.cnblogs.com/wuhua1/p/6686237.html
4. 自定义指令
4.1 自定义全局指令
语法:
// 参数一:指令名称,定义时名称前面不需要加 v-,但是在 html 中使用时,需要加 v- 的前缀来调用
// 参数二:为一个对象,里面可以配置一些指令相关的函数,这些函数在特定的阶段,执行相关操作
// 常见的有 bind、inserted、updated
Vue.directive('指令名称', {
// el 为被绑定指令的元素,为一个原生的 js 对象,因此可以进行一些 js 方面的操作
bind: function(el){
// 当指令绑定到元素上时,会立即执行,执行一次
},
inserted: function(el){
// 元素插入的 DOM 中时,会执行 inserted 函数,触发一次
},
uodated: function(el) {
// 当VNode 更新的时候,会执行 updated,可能会触发多次
}
})
何时用 bind、inserted 和 updated
- 与 JS 行为相关的操作,最好使用
inserted
中执行,放置 JS行为不生效 - 与样式相关的操作,一般都可以在
bind
执行
示例一:
初始化页面时,给搜索框获取焦点:
<div id="app">
<label>
搜索名称关键字:
<input type="text" class="form-control" v-model="keywords" v-focus>
</label>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
// 自定义全局指令
Vue.directive('focus', {
bind: function(el) {},
inserted: function(el) {
el.focus()
},
updated: function(el) {}
})
var vm = new Vue({
el: '#app'
})
</script>
4.2 局部自定义指令
<body>
<div id="app">
<label for="fo">页面加载时自动聚焦</label>
<input v-focus id="fo"/>
</div>
<script src="https://cdn.staticfile.org/vue/2.2.2/vue.js"></script>
<script>
Vue.directive('focus', {
inserted: function(el) {
el.focus()
}
})
var vm = new Vue({
el: '#app',
// 局部定义
directives: ('focus', {
inserted: function(el) {
el.focus()
}
})
})
</script>
</body>
4.3. 钩子函数
指令定义函数提供了几个钩子函数(可选):
- bind: 只调用一次,指令第一次绑定到元素时调用,用这个钩子函数可以定义一个在绑定时执行一次的初始化动作。
- inserted: 被绑定元素插入父节点时调用(父节点存在即可调用,不必存在于 document 中)。
- update: 被绑定元素所在的模板更新时调用,而不论绑定值是否变化。通过比较更新前后的绑定值,可以忽略不必要的模板更新(详细的钩子函数参数见下)。
- componentUpdated: 被绑定元素所在模板完成一次更新周期时调用。
- unbind: 只调用一次, 指令与元素解绑时调用。
钩子函数参数
- el: 指令所绑定的元素,可以用来直接操作 DOM 。
- binding: 一个对象,包含以下属性:
- name: 指令名,不包括 v- 前缀。
- value: 指令的绑定值, 例如: v-my-directive="1 + 1", value 的值是 2。
- oldValue: 指令绑定的前一个值,仅在 update 和 componentUpdated 钩子中可用。无论值是否改变都可用。
- expression: 绑定值的表达式或变量名。 例如 v-my-directive="1 + 1" , expression 的值是 "1 + 1"。
- arg: 传给指令的参数。例如 v-my-directive:foo, arg 的值是 "foo"。
- modifiers: 一个包含修饰符的对象。 例如: v-my-directive.foo.bar, 修饰符对象 modifiers 的值是 { foo: true, bar: true }。
- vnode: Vue 编译生成的虚拟节点。
- oldVnode: 上一个虚拟节点,仅在 update 和 componentUpdated 钩子中可用。
示例二:
自定义一个 设置字体颜色的 指令:
<div id="app">
<label>
搜索名称关键字:
<!-- <input type="text" class="form-control" v-model="keywords" v-focus v-color> -->
<input type="text" class="form-control" v-model="keywords" v-focus v-color="'red'">
</label>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
// 自定义全局指令:颜色
Vue.directive('color', {
bind: function(el, binding) {
// el.style.color = 'red'
el.style.color = binding.value // 使用指令绑定的值
}
})
var vm = new Vue({
el: '#app'
})
</script>
4.4 函数简写
在很多时候,你可能想在 bind
和 update
时触发相同行为,而不关心其它的钩子。比如这样写:
Vue.directive('color-swatch', function (el, binding) {
el.style.backgroundColor = binding.value
})
示例三:
<div id="app2">
<h3 v-fontsize="50">{{ dt | dateFormat }}</h3>
</div>
<script>
// 自定义全局指令,获取焦点
Vue.directive('focus', {
bind: function(el) {},
inserted: function(el) {
el.focus()
},
updated: function(el) {}
})
// 自定义全局指令:颜色
Vue.directive('color', {
bind: function(el, binding) {
el.style.color = binding.value
}
})
var vm2 = new Vue({
el: '#app2',
data: {
dt: new Date()
},
directives: {
'fontsize': function(el, binding) {
el.style.fontSize = parseInt(binding.value) + 'px'
}
}
})
</script>
5. vue实例的生命周期
什么是生命周期:从Vue实例创建、运行、到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期!
声明周期钩子函数
即在生命周期内发生的事件,以下为所有钩子函数:
- 创建期间的生命周期函数:
beforeCreate
:实例刚在内存中被创建出来,此时,还没有初始化好 data 和 methods 属性created
:实例已经在内存中创建OK,此时 data 和 methods 已经创建OK,此时还没有开始 编译模板beforeMount
:此时已经完成了模板的编译,但是还没有挂载到页面中mounted
:此时,已经将编译好的模板,挂载到了页面指定的容器中显示
- 运行期间的生命周期函数:
beforeUpdate
:状态更新之前执行此函数, 此时 data 中的状态值是最新的,但是界面上显示的 数据还是旧的,因为此时还没有开始重新渲染DOM节点updated
:实例更新完毕之后调用此函数,此时 data 中的状态值 和 界面上显示的数据,都已经完成了更新,界面已经被重新渲染好了!
- 销毁期间的生命周期函数:
beforeDestroy
:实例销毁之前调用。在这一步,实例仍然完全可用destroyed
:Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。
示例
<body>
<div id="app">
<input type="button" value="修改msg" @click="msg='No'">
<h3 id="h3">{{ msg }}</h3>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script>
var vm = new Vue({
el: '#app',
data: {
msg: 'Hello'
},
methods: {
show() {
console.log('函数 show')
}
},
beforeCreate() {
// 实例创建之前触发
// 在 beforeCreate 生命周期函数执行的时候,data 和 methods 中的 数据都还没有没初始化
// console.log(this.msg)
// this.show()
},
created() {
// 实例创建后触发
// 在 created 中,data 和 methods 都已经被初始化好了!
// 如果要调用 methods 中的方法,或者操作 data 中的数据,最早,只能在 created 中操作
// console.log(this.msg)
// this.show()
},
beforeMount() {
// 挂载之前触发
// 模板已经在内存中编辑完成了,但是尚未把 模板渲染到 页面中
// 在 beforeMount 执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串
// console.log(document.getElementById('h3').innerText) // {{ msg }}
},
mounted() {
// 模板挂载后触发
// 内存中的模板,已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
// mounted 是 实例创建期间的最后一个生命周期函数,当执行完 mounted 就表示,实例已经被完全创建好了,
// 此时,如果没有其它操作的话,这个实例,就静静的 躺在我们的内存中,一动不动
// console.log(document.getElementById('h3').innerText) // Hello
},
// 运行中生命周期钩子函数
// 以下两个钩子函数,当 data 发生改变时才会触发,msg 内容原本为 Hello,当点击后变为 No
beforeUpdate() {
// 模板挂载完毕,只有当 data 发生改变时才会触发
// 当执行 beforeUpdate 的时候,页面中的显示的数据,还是旧的,此时 data 数据是最新的,页面尚未和 最新的数据保持同步
// console.log('界面上元素的内容:' + document.getElementById('h3').innerText) // No
// console.log('data 中的 msg 数据是:' + this.msg) // No
},
updated() {
// 模板挂载完毕,只有当 data 发生改变时才会出发
// updated 事件执行的时候,页面和 data 数据已经保持同步了,都是最新的
console.log('界面上元素的内容:' + document.getElementById('h3').innerText) // No
console.log('data 中的 msg 数据是:' + this.msg) // No
}
})
</script>
</body>
参考文档:
6. vue-resource
Vue
要实现异步加载需要使用到 vue-resource
库。Vue.js 2.0
版本推荐使用 axios
来完成 ajax
请求。
6.1 GET 请求
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Vue-Resource</title>
<script src="https://cdn.staticfile.org/vue/2.4.2/vue.min.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
</head>
<body>
<div id="box">
<input type="button" @click="get" value="点我异步获取数据(Get)">
</div>
<script type = "text/javascript">
window.onload = function(){
var vm = new Vue({
el:'#box',
data:{
msg:'Hello World!',
},
methods:{
get() {
//发送get请求
this.$http.get('/try/ajax/ajax_info.txt').then(function(res){
document.write(res.body);
},function(){
console.log('请求失败处理');
});
}
}
});
}
</script>
</body>
</html>
如果需要传递数据,可以使用 this.$http.get('get.php',{params : jsonData})
格式,第二个参数 jsonData
就是传到后端的数据。
this.$http.get('get.php',{params : {a:1,b:2}}).then(function(res){
document.write(res.body);
},function(res){
console.log(res.status);
});
6.2 POST 请求
post
发送数据到后端,需要第三个参数 {emulateJSON:true}
。emulateJSON
的作用: 如果 Web
服务器无法处理编码为 application/json
的请求,你可以启用 emulateJSON
选项。
<body>
<div id="box">
<input type="button" @click="post" value="点我异步获取数据(Post)">
</div>
<script type = "text/javascript">
window.onload = function(){
var vm = new Vue({
el:'#box',
data:{
msg:'Hello World!',
},
methods:{
post(){
//发送 post 请求
this.$http.post('/try/ajax/demo_test_post.php',{name:"POST 请求",url:"http://www.runoob.com"},{emulateJSON:true}).then(function(res){
document.write(res.body);
},function(res){
console.log(res.status);
});
}
}
});
}
</script>
</body>
语法 & API
既可以全局对象方式发送请求,也可以在一个 vue
实例中发送请求,使用方式如下:
// 基于全局Vue对象使用http
Vue.http.get('/someUrl', [options]).then(successCallback, errorCallback);
Vue.http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
// 在一个Vue实例内使用$http
this.$http.get('/someUrl', [options]).then(successCallback, errorCallback);
this.$http.post('/someUrl', [body], [options]).then(successCallback, errorCallback);
七种 REST 风格的请求方式:
get(url, [options])
head(url, [options])
delete(url, [options])
jsonp(url, [options])
post(url, [body], [options])
put(url, [body], [options])
patch(url, [body], [options])
options 参数
参数 | 类型 | 描述 |
---|---|---|
url | string | 请求的目标URL |
body | Object, FormData, string | 作为请求体发送的数据 |
headers | Object | 作为请求头部发送的头部对象 |
params | Object | 作为URL参数的参数对象 |
method | string | HTTP方法 (例如GET,POST,...) |
timeout | number | 请求超时(单位:毫秒) (0表示永不超时) |
before | function(request) | 在请求发送之前修改请求的回调函数 |
progress | function(event) | 用于处理上传进度的回调函数 ProgressEvent |
credentials | boolean | 是否需要出示用于跨站点请求的凭据 |
emulateHTTP | boolean | 是否需要通过设置X-HTTP-Method-Override头部并且以传统POST方式发送PUT,PATCH和DELETE请求。 |
emulateJSON | boolean | 设置请求体的类型为application/x-www-form-urlencoded |
响应
1、属性:
属性 | 类型 | 描述 |
---|---|---|
url | string | 响应的 URL 源 |
body | Object, Blob, string | 响应体数据 |
headers | Header | 请求头部对象 |
ok | boolean | 当 HTTP 响应码为 200 到 299 之间的数值时该值为 true |
status | number | HTTP 响应码 |
statusText | string | HTTP 响应状态 |
2、方法:
方法 | 类型 | 描述 |
---|---|---|
text() | 约定值 | 以字符串方式返回响应体 |
json() | 约定值 | 以格式化后的 json 对象方式返回响应体 |
blob() | 约定值 | 以二进制 Blob 对象方式返回响应体 |
6.3 JSONP 请求
JSONP的实现原理
- 由于浏览器的安全性限制,不允许AJAX访问 协议不同、域名不同、端口号不同的 数据接口,浏览器认为这种访问不安全;
- 可以通过动态创建script标签的形式,把script标签的src属性,指向数据接口的地址,因为script标签不存在跨域限制,这种数据获取方式,称作JSONP(注意:根据JSONP的实现原理,知晓,JSONP只支持Get请求)
具体实现过程
- 先在客户端定义一个回调方法,预定义对数据的操作
- 再把这个回调方法的名称,通过URL传参的形式,提交到服务器的数据接口;
- 服务器数据接口组织好要发送给客户端的数据,再拿着客户端传递过来的回调方法名称,拼接出一个调用这个方法的字符串,发送给客户端去解析执行
- 客户端拿到服务器返回的字符串之后,当作Script脚本去解析执行,这样就能够拿到JSONP的数据了
<body>
<div id="app">
<input type="button" value="jsonp请求" @click="jsonpInfo">
</div>
<script>
// 创建 Vue 实例,得到 ViewModel
var vm = new Vue({
el: '#app',
data: {},
methods: {
jsonpInfo() { // 发起JSONP 请求
this.$http.jsonp('http://vue.studyit.io/api/jsonp').then(result => {
console.log(result.body)
})
}
}
});
</script>
</body>
Node.js 服务器示例
1、app.js
// 导入 http 内置模块
const http = require('http')
const urlModule = require('url')
// 创建一个 http 服务器
const server = http.createServer()
// 监听 http 服务器的 request 请求
server.on('request', function (req, res) {
const { pathname: url, query } = urlModule.parse(req.url, true)
if (url === '/getscript') {
// 拼接一个合法的 JS 脚本,拼接的是一个方法的调用
var data = {
name: 'rose',
age: 18,
gender: '女',
phone: '18674447633'
}
var scriptStr = `${query.callback}(${JSON.stringify(data)})`
// res.end 发送给客户端,客户端将这个字符串当前 JS 代码去解析执行
res.end(scriptStr)
} else {
res.end('404')
}
})
// 指定端口号并启动服务器监听
server.listen(3000, function () {
console.log('server listen at http://127.0.0.1:3000')
})
执行 node app.js
运行 node 服务器。
2、client.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div id="app">
<input type="button" value="get 请求" @click="getinfo">
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script src="https://cdn.staticfile.org/vue-resource/1.5.1/vue-resource.min.js"></script>
<script>
var vm = new Vue({
el: '#app',
methods: {
getinfo() {
// get 请求
this.$http.get('http://vue.studyit.io/api/getlunbo').then(function (result) {
console.log(result)
})
}
}
})
</script>
</body>
</html>
7. 配置本地数据库和数据接口 API
品牌管理案例改造
- 获取接口:
http://www.liulongbin.top:3005/api/getprodlist
- 添加接口:
http://www.liulongbin.top:3005/api/addproduct
- 删除接口:
http://www.liulongbin.top:3005/api/delproduct/id
API 接口
1、获取品牌数据
- 请求方式:get
- 返回数据格式:json
- 请求参数:无
- 请求URL:
http://www.liulongbin.top:3005/api/getprodlist
- 返回数据示例
{"status":0,"message":[{"id":5,"name":"宝马","ctime":"2020-02-08T04:32:58.000Z"},{"id":6,"name":"玛莎拉蒂","ctime":"2020-02-08T04:33:03.000Z"},{"id":12,"name":"1","ctime":"2020-02-08T04:51:21.000Z"}]}
2、添加新品牌
- 请求方式:post
- 返回数据格式:json
- 请求参数:
{name: 品牌名}
- 请求URL:
http://www.liulongbin.top:3005/api/addproduct
- 返回数据示例
{"status":0,"message":"添加成功"}
3、删除品牌
- 请求方式:get
- 返回数据格式:json
- 请求参数:品牌id
api/delproduct/1
- 请求URL:
http://www.liulongbin.top:3005/api/delproduct/id
- 返回数据示例
{"status":0,"message":"删除成功"}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="./lib/bootstrap-3.3.7.css">
</head>
<body>
<div id="app">
<div class="panel panel-primary">
<div class="panel-body form-inline">
<input type="text" placeholder="品牌名" class="form-control" v-model="name" @keyup.enter="add">
<input type="button" value="添加" class="btn btn-primary" @click="add">
</div>
</div>
<table class="table table-bordered table-hover table-striped">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Ctime</th>
<th>Opration</th>
</tr>
</thead>
<tbody>
<tr v-for="item in list" :key="item.id">
<td>{{ item.id }}</td>
<td>{{ item.name }}</td>
<td>{{ item.ctime }}</td>
<td>
<a href="" @click.prevent="del(item.id)">删除</a>
</td>
</tr>
</tbody>
</table>
</div>
<script src="./lib/vue-2.4.0.js"></script>
<script src="./lib/vue-resource-1.3.4.js"></script>
<script>
// 全局配置根目录
Vue.http.options.root = 'http://www.liulongbin.top:3005/';
// 全局启用 emulateJSON 选项
Vue.http.options.emulateJSON = true;
var vm = new Vue({
el: '#app',
data: {
name: "",
list: [
{ id: 1, name: '奔驰', ctime: new Date() },
{ id: 2, name: '宝马', ctime: new Date() }
]
},
created() {
// 页面初始化时,执行 getinfo() 函数,获取品牌数据
this.getinfo()
},
methods: {
getinfo() {
// 获取品牌信息
this.$http.get('api/getprodlist').then(result => {
// 赋值给 this.list,从而实现数据的显示
if (result.body.status === 0) {
this.list = result.body.message
}
})
},
add() {
// 添加新品牌
// 发送 post 请求,获取
this.$http.post('api/addproduct', { name: this.name }).then(result => {
if (result.body.status === 0) {
console.log('添加成功!')
// 重新调用获取数据接口,实现页面刷新
this.getinfo()
// 清空输入框
this.name = ''
} else {
alert('添加失败!')
}
})
},
del(id) {
// 根据删除品牌
this.$http.get("api/delproduct/" + id).then(result => {
if (result.body.status === 0) {
this.getinfo()
} else {
alert('删除失败!')
}
})
}
}
})
</script>
</body>
</html>
参考文章: