Vue.js 基础入门(二)

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 函数简写

在很多时候,你可能想在 bindupdate 时触发相同行为,而不关心其它的钩子。比如这样写:

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>

参考文章:

原文地址:https://www.cnblogs.com/midworld/p/13611024.html