当前位置:   article > 正文

【前端 VUE 框架】vue004---购物车案例、Vue生命周期钩子函数、axios跟后端交互、前端显示电影、计算属性、组件化开发及通讯、ref属性、动态组件、Vue脚手架创建Vue项目_vue案例代码

vue案例代码

上次内容回顾

1.v-for循环数字,数组,对象

-<标签 v-for='i in 变量'>{{i}}----{{变量}}<标签>
  • 1

2.事件处理

-input标签的事件: change(input框里面的数据发生变化,光标移开,才会触发),blur(input框只要光标移开,才会触发),input(只要输入一个东西,光标移开,就会触发)
  • 1

3.数据双向绑定

-input标签  v-model
  • 1

4.过滤案例

-触发input事件,让新的数组变化
-变量=数组.filter(item=>{})
-字符串.indeOf('子字符串')
  • 1
  • 2
  • 3

5.事件修饰符

-stop:阻止事件冒泡
-self:只执行自己的事件
-prevent:阻止a标签跳转
-once:只执行一次
  • 1
  • 2
  • 3
  • 4

6.按键修饰符

-@keyUp   enter用的最多
  • 1

7.input标签

-checkbox:作为单选的时候---》js变量 的布尔值
-radio:js变量的字符串
-checkbox 多选:js变量的数组
  • 1
  • 2
  • 3

购物车案例

在这里插入图片描述

下面这种写法也是可以的
  • 1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码:
  • 1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <style>
        table, td {
            border: 1px solid black;
            text-align: center;
        }
    </style>
</head>
<body>
<div id="app">
    <h1>购物车</h1>
    <table>
        <tr>
            <td>商品名称</td>
            <td>价格</td>
            <td>数量</td>
            <td>选择</td>
        </tr>
        <tr v-for="item in dataList">
            <td>{{item.name}}</td>
            <td>{{item.price}}</td>
            <td>{{item.number}}</td>
            <td><input type="checkbox" v-model="choice" :value="item"></td>
        </tr>
    </table>
    选中的商品是:{{choice}}
    <br>
    <!--    插值语法里面,写函数加括号,就会执行这个函数-->
    商品价格:{{getPrice()}}
</div>
</body>

<script>
    let vm = new Vue({  //ES6之后,都是推荐时间let
        el: "#app",
        data: {
            dataList: [
                {name: '今瓶没', price: 99, number: 2},
                {name: '西柚记', price: 59, number: 1},
                {name: '水壶转', price: 89, number: 5},
            ],//这个数据是后端返回的
            choice: []
        },
        methods: {
            getPrice() {
                // 价格的逻辑,就是拿到choice里面的数据,然后拿出价格,乘以数量
                let totle = 0
                // for (let i = 0; i < this.choice.length; i++) {
                //     totle = totle + this.choice[i].price * this.choice[i].number;
                // }
                // return totle
                // 还有别的写法
                // for (i in this.choice) { // 这里的i是索引
                //     totle += this.choice[i]['number'] * this.choice[i]['price'] // ['price'],用点也可以
                // }
                // return totle
                // 还有别的写法:es6的循环方式
                // for (v of this.choice) { // 这里的v是数组中的每一个对象
                //     totle += v.price * v.number
                // }
                // return totle
                // 还有别的写法:对象的迭代方法(了解)
                this.choice.forEach(function (value, index) {   //  匿名函数,亦可以用箭头 this.choice.forEach((value, index)=>{
                    totle += value.price * value.number
                })
                return totle

            }
        }
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77

下面再实现一个:购物车案例加上全选,全不选的按钮
在这里插入图片描述
在这里插入图片描述

还有一个问题是,当我把所有的枚举值都选中的时候,上面的全选也应该勾选
所以得加上一个逻辑:就是下面的枚举值,被选上的时候,要检查一下上面的全选勾的状态

在这里插入图片描述
在这里插入图片描述

代码
  • 1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <style>
        table, td {
            border: 1px solid black;
            text-align: center;
        }
    </style>
</head>
<body>
<div id="app">
    <h1>购物车</h1>
    <table>
        <tr>
            <td>商品名称</td>
            <td>价格</td>
            <td>数量</td>
            <td>选择 <input type="checkbox" v-model="checkAll" @change="handleAll"></td>
        </tr>
        <tr v-for="item in dataList">
            <td>{{item.name}}</td>
            <td>{{item.price}}</td>
            <td>{{item.number}}</td>
            <td><input type="checkbox" v-model="choice" :value="item" @change="checkOne"></td>
        </tr>
    </table>
    选中的商品是:{{choice}}
    <br>
    <!--    插值语法里面,写函数加括号,就会执行这个函数-->
    商品价格:{{getPrice()}}
</div>
</body>

<script>
    let vm = new Vue({  //ES6之后,都是推荐时间let
        el: "#app",
        data: {
            dataList: [
                {name: '今瓶没', price: 99, number: 2},
                {name: '西柚记', price: 59, number: 1},
                {name: '水壶转', price: 89, number: 5},
            ],//这个数据是后端返回的
            choice: [],
            checkAll: false
        },
        methods: {
            getPrice() {
                // 价格的逻辑,就是拿到choice里面的数据,然后拿出价格,乘以数量
                let totle = 0
                //es6的循环方式
                for (v of this.choice) { // 这里的v是数组中的每一个对象
                    totle += v.price * v.number
                }
                return totle

            },
            handleAll() {
                if (this.checkAll) {
                    this.choice = this.dataList  //这个是全选的时候
                } else {
                    this.choice = []//这个是全不选的时候

                }
            },
            checkOne() {
                //逻辑就是:this.choice = this.dataList的长度,就全选中,全选中的话,就让checkAll变成true
                if (this.choice.length == this.dataList.length) {
                    this.checkAll=true
                }else{
                    this.checkAll=false
                }


            }
        },
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82

功能车功能完成

实现在数量前面加上+—号,用来调整数量,当数量减到1的时候,就不能减了

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

代码:
  • 1
   <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <script src="./js/vue.js"></script>
        <style>
            table, td {
                border: 1px solid black;
                text-align: center;
            }
        </style>
    </head>
    <body>
    <div id="app">
        <h1>购物车</h1>
        <table>
            <tr>
                <td>商品名称</td>
                <td>价格</td>
                <td>数量</td>
                <td>选择 <input type="checkbox" v-model="checkAll" @change="handleAll"></td>
            </tr>
            <tr v-for="item in dataList">
                <td>{{item.name}}</td>
                <td>{{item.price}}</td>
    <!--            @click="item.number++">:这里也可以写简单的js代码,跟插值一样-->
    <!--            这里可以写item.number++  写减减@click="item.number&#45;&#45;"的话,会出现负数,所以不能这样写-->
    <!--            handleJ(item),参数是要减的对象,得传进去-->
                <td><button @click="handleJ(item)">-</button>{{item.number}}<button @click="item.number++">+</button></td>
                <td><input type="checkbox" v-model="choice" :value="item" @change="checkOne"></td>
            </tr>
        </table>
        选中的商品是:{{choice}}
        <br>
        <!--    插值语法里面,写函数加括号,就会执行这个函数-->
        商品价格:{{getPrice()}}
    </div>
    </body>

    <script>
        let vm = new Vue({  //ES6之后,都是推荐时间let
            el: "#app",
            data: {
                dataList: [
                    {name: '今瓶没', price: 99, number: 2},
                    {name: '西柚记', price: 59, number: 1},
                    {name: '水壶转', price: 89, number: 5},
                ],//这个数据是后端返回的
                choice: [],
                checkAll: false
            },
            methods: {
                getPrice() {
                    // 价格的逻辑,就是拿到choice里面的数据,然后拿出价格,乘以数量
                    let totle = 0
                    //es6的循环方式
                    for (v of this.choice) { // 这里的v是数组中的每一个对象
                        totle += v.price * v.number
                    }
                    return totle

                },
                handleAll() {
                    if (this.checkAll) {
                        this.choice = this.dataList  //这个是全选的时候
                    } else {
                        this.choice = []//这个是全不选的时候

                    }
                },
                checkOne() {
                    //逻辑就是:this.choice = this.dataList的长度,就全选中,全选中的话,就让checkAll变成true
                    if (this.choice.length == this.dataList.length) {
                        this.checkAll=true
                    }else{
                        this.checkAll=false
                    }
                },
                handleJ(item){
                    if (item.number<=1){
                        alert('不能再少了')
                    }else {
                        item.number--
                    }

                }
            },
        })
    </script>
    </html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91

关于备案(插播):

现在我们用django或其他写了一个项目,项目是在服务器上的。服务器可以是自己电脑,这样的话,别人就不能访问到你,因为没有公网IP,所以访问不到你
一般我们公司都是用的一个公网地址
所以需要去买一台带公网的IP,买一台云服务器(阿里云之内的,就是租了一台服务器,把自己的项目部署在上面),还要再买一个公网ip,需要把ip绑定到这个公网ip上面
但是现在的访问,不是基于ip的访问,还要买一个域名,自己去选
别人访问你的域名,域名在转发到公网ip上,是DNS解析
买的这个域名,在国内必须要备案(说明是干嘛要的)
买阿里云的话,阿里云会协助你在工信部备案,大概两个星期。要身份证正反面
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

V-model进阶

不是特别重要
lazy:等待input框的数据绑定时区焦点之后再变化
    指的是input框,本来数据的双向绑定,只要页面一变,数据就跟着变化、
    现在是焦点失去之后,js的变量在变,相当于懒加载一下,就不是实时的更新,实时的更新的话,是需要消耗一定的资源的
number:数字开头,只保留数字,后面的字母不保留;字母开头,都保留
trim:去除首位的空格
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

lazy
在这里插入图片描述
在这里插入图片描述

number
在这里插入图片描述
在这里插入图片描述

trim

去除前后空格,相当于Python的.strip
  • 1

Vue生命周期钩子函数
指的是Vue的组件,有8个

create  创建
mount   挂载
update  更新

1.bedoreCreate
2.created
3.beforeMount
4.mounted(用得最多)
5.beforeUpdate
6.updated
7.beforeDestroy 销毁之前
8.destroyed 销毁
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

在这里插入图片描述

就是到那个地方,就会触发他的执行
我们的目的是在某一个地方,重写钩子函数,去实现自己的功能
比如:在create的时候,去后端加载数据,数据回来之后,还没有挂载整个页面,这时数据已经过来了,效率上就比较快


beforeCreate	创建Vue实例之前调用
created	创建Vue实例成功后调用(可以在此处发送异步请求后端数据)
beforeMount	渲染DOM之前调用
mounted	渲染DOM之后调用
beforeUpdate	重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
updated	重新渲染完成之后调用
beforeDestroy	销毁之前调用
destroyed	销毁之后调用
记住:有8个东西,用就用created,就行了
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

在这里插入图片描述
在这里插入图片描述

挂载完之后,现在就停在这里了,等待组件里面的数据变化,只要有变化,就会触发updated、beforeUpdate
  • 1

在这里插入图片描述

在这里插入图片描述

重点:

    1、created:在这个里面向后端发送请求,获取数据
    2、mounted:
  • 1
  • 2

定时器:用处很大,轮训。跟后端交互,比如拿后端数据(一种就是像这样向后端轮训,还有一种就是websocket)

this.t = setInterval(function () {
    console.log('daada')
}, 3000) // js代码:每隔3秒钟,干一件事(console.log('daada'))
  • 1
  • 2
  • 3

关掉定时器:

clearInterval(this.t)
  • 1

延迟任务:

this.t = setTimeout(function () {
    console.log('daada')
}, 3000) // js代码:3秒后执行代码console.log('daada')
20
  • 1
  • 2
  • 3
  • 4

在任何一个Vue对象里面,都可以写这8个生命周期函数,跟写的顺序没有关系,跟钩子的名字有关

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>生命周期</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
    <child v-if="isShow"></child>
    <br>
    <button @click="terminate">删除子组件</button>
    <button @click="reborn">显示子组件</button>
</div>
</body>
<script>
    Vue.component('child', {
        template: `
            <div>
                {{name}}
                <button @click="name='Darker1'">更新数据1</button>
                <button @click="name='Darker2'">更新数据2</button>
            </div>`,
        data() {
            return {
                name: 'Darker1',
            }
        },
        beforeCreate() {
            console.group('当前状态:beforeCreate')
            console.log('当前el状态:', this.$el) // 指的是上面的模板:template里面的div
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        created() {
            console.group('当前状态:created')// 可以打印出分组的效果:可以收缩
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        beforeMount() {
            console.group('当前状态:beforeMount')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        mounted() {
            console.group('当前状态:mounted')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
          //用的最多,向后端加载数据,创建定时器等
            console.log("页面已被vue实例渲染, data, methods已更新");
            console.log('mounted')
            this.t = setInterval(function () {
                console.log('daada')
            }, 3000) // js代码:每隔3秒钟,干一件事(console.log('daada'))

        },
        beforeUpdate() {
            console.group('当前状态:beforeUpdate')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        updated() {
            console.group('当前状态:updated')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        beforeDestroy() {
            console.group('当前状态:beforeDestroy')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        destroyed() {
            console.group('当前状态:destroyed')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
          //组件销毁,清理定时器
            clearInterval(this.t)
            this.t = null //销毁定时器
            console.log('destoryed')
        },


    })
    let vm = new Vue({
        el: '#box',
        data: {
            isShow: true
        },
        methods: {
            terminate() {
                this.isShow = false
            },
            reborn() {
                this.isShow = true
            }
        }
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106

axios跟后端交互

并不是只有jquery能发Ajax,原生的js就可以发ajax请求。问题在于不同的浏览器兼容性不好。jquery处理了这个兼容性的问题
在vue里面不推崇用jquery的ajax发请求了
axios:只有ajax,没有别的。不需要引入jquery
  • 1
  • 2
  • 3

在这里插入图片描述

现在通过前端页面,向这个地址发请求,拿数据
  • 1

在这里插入图片描述

会出现跨域问题。

之前没有出现跨域问题,是因为前后端混合开发,发的请求就是服务器的地址
现在是重一个端口向5000端口发请求,这样就被阻止了,这个是浏览器的一个安全策略
处理这个问题,很简单,需要在响应头里面加一个东西
  • 1
  • 2
  • 3

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

这样前端就能拿到后端的数据了,现在需要把渲染到页面上面
  • 1

在这里插入图片描述

实际项目中,后端的数据,会从数据库之内的地方拿
当然:axios也可以发送post请求
前端代码:
  • 1
  • 2
  • 3
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>跟后端交互</title>
    <script src="./js/vue.js"></script>
<!--    引入axios的cdn,也可以下载下来放在本地-->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="box">
<button @click="handleClick">点我看美女</button>
    <br>
    我的名字是:{{name}}
    <br>
    我的年龄是:{{age}}
</div>
</body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            name : "",
            age : 0
        },
        methods: {
            handleClick(){
                // 会出现跨域问题
                axios.get("http://127.0.0.1:5000").then(res=>{
                console.log(res["data"])
                this.name = res.data.name
                this.age = res.data.age
                })   // 发送get请求;匿名函数,可以用箭头;返回的结果就在这个res里面
            }

        }
    })
</script>
</html>
后端代码:
from flask import Flask, jsonify, make_response

app = Flask(__name__)


@app.route("/")
def index():
    # return jsonify({"name": "lqz", "age": 19})
    obj = make_response(jsonify({"name": "lqz", "age": 19}))
    obj.headers["Access-Control-Allow-Origin"] = "*"  # 往消息头里面加东西
    return obj


if __name__ == '__main__':
    app.run()

# 访问根路径,就返回一个{"name": "lqz", "age": 19}的接口
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

前端显示电影

页面什么时候加载?我们放在生命周期的钩子函数上面,当页面created的时候
后端代码:
  • 1
  • 2
from flask import Flask, jsonify, make_response
import json

app = Flask(__name__)


@app.route("/")
def index():
    with open("a.json", "r", encoding="utf8") as f:
        res = json.load(f)

    obj = make_response(jsonify(res))
    obj.headers["Access-Control-Allow-Origin"] = "*"  # 往消息头里面加东西
    return obj


if __name__ == '__main__':
    app.run()

# 访问根路径,就返回一个{"name": "lqz", "age": 19}的接口
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
前端代码:
  • 1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>跟后端交互</title>
    <script src="./js/vue.js"></script>
<!--    引入axios的cdn,也可以下载下来放在本地-->
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="box">
    <ul>
        <li v-for="item in datalist">
            <p>电影标题:{{item.name}}</p>
            <p>电影主演:{{item.director}}</p>
            <img :src="item.poster" alt="">

        </li>
    </ul>

</div>
</body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {
            datalist : []
        },
        created(){
            axios.get("http://127.0.0.1:5000/").then(res =>{
                this.datalist= res.data.data.films
            })
        }
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
向后端发送请求,就在created里面写
  • 1

计算属性

先实现一个需求,一输入内容,就将首字母变成大写
  • 1

在这里插入图片描述

这样实现的话,里面的逻辑太多了,不好。可以写一个方法
  • 1

在这里插入图片描述

上面写在插值里面和写成函数都是OK的
写成函数不好的地方就是,如果再调用一次,就又要执行,这样就不太好,最好写成计算属性
计算属性的意思是把这个东西当做属性来用,里面用多次之后,不会重复计算
  • 1
  • 2
  • 3

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

代码:
  • 1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>计算属性</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
    <!--    现在想要实现一输入内容,就将首字母变成大写,后面直接写msg,肯定不行-->
    <!--    希望能有一些js代码来支持:msg.substring(0,1)获取从0到第一个字母,.toUpperCase()转大写,msg.substring(1)是1到最后都截-->
    <input type="text" v-model="msg">
    <br> 直接在插值中写代码:
    {{msg.substring(0, 1).toUpperCase() + msg.substring(1)}}
    <br> 写成一个函数:
    {{getMsg()}}
    <br> 使用计算属性
    {{getMsg}}



</div>
</body>
<script>
    let vm = new Vue({
        el: '#box',
        data: {},
        methods : {
            getMsg(){
            return this.msg.substring(0, 1).toUpperCase() + this.msg.substring(1)
        }
        },
        computed : {
            getMsg() {
                return this.msg.substring(0, 1).toUpperCase() + this.msg.substring(1)
            }
        }

    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41

组件化开发

全局组件

后面开发的时候,头部、中间、侧部的东西可以直接引过来用。
组件分为全局组件和局部组件

定义一个全局组件
组件名字是child,template(必须是template,可以不加引号)里面写html内容(反引号可以换行)
template里面只能有一个闭合标签,下面写的是div
组件里面的data必须是函数,返回对象
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

在这里插入图片描述
在这里插入图片描述

组件有自己的样式,数据,方法
这个就是组件化开发
  • 1
  • 2

局部组件

局部组件要么定义在根Vue里面,要么定义在Vue组件里面
  • 1

在这里插入图片描述
在这里插入图片描述

类似于上面的这个图,头可以有组件,导航可以有组件,里面的任何都可以做成组件
全局组件的定义,可以用在跟组件上面
局部组件的定义,只能用在内部
组件都有自己的生命周期,包括计算属性

代码:
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
   <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>组件化开发</title>
        <script src="./js/vue.js"></script>
    </head>
    <body>
    <div id="box">

        <child></child>
        <hr>
    </div>
    </body>
    <script>
        // 定义一个全局组件,在全局组件中定义一个局部组件
        Vue.component('child', {
            template: `
              <div>
                  <h1>我是子组件</h1>
                  <br>
                  <button @click="handleClick">点我看美女--{{ name }}</button>
                  <hr>
                  <header1></header1>
              </div>
            `,
            data() {
                return {
                    name: 'lqz'
                }
            },
            methods: {
                handleClick() {
                    alert('美女')
                }

            },

            components: {
                'Header1': {
                    template: `<h2>我是局部组件---{{ msg }}</h2>`,// 组件只能用自己的值,不能用别的组件的数据
                    data() {
                        return {
                            msg: 'SB'
                        }
                    },
                    methods: {},
                }
            }

        })
        // 上面定义的子组件Header1,只能用在局部child里面

        let vm = new Vue({
            el: '#box',
            data: {},
        })
    </script>
    </html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59

组件通讯之父传子(通过属性)

上面讲了全局组件和局部组件,两者之间的数据是不能共享的,现在就需要实现这个共享
上面的代码里面:child是父,Header1是子;
也可以是:上面的vue div是父,child是子
现在想实现将Vue里面的数据传到child里面,就是父传子
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

1、在子组件上自定义一个属性,绑定好一个变量  <child :mymsg="msg"></child>,这个变量msg是父组件的变量
2、在子组件里面写一个props,后面接数组,有几个可以写几个:props:['mymsg'],数组里面是属性的名字。写了属性名字之后,就可以当做变量来用了

通过自定义属性实现父传子

再传一个数据过来
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

在这里插入图片描述

代码:
  • 1
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化开发</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!--    在组件上自定义属性,使用属性指令,绑定好变量-->
    <child :mymsg="msg" :age="age"></child>
    <hr>
</div>
</body>
<script>
    // 定义一个全局组件,在全局组件中定义一个局部组件
    Vue.component('child', {
        template: `
          <div>
          <h1>我是子组件---从父组件传值过来--{{mymsg}}---{{age}}</h1>
          <br>
          <button @click="handleClick">点我看美女--{{ name }}</button>
          <hr>
          </div>
        `,
        data() {
            return {
                name: 'lqz'
            }
        },
        methods: {
            handleClick() {
                alert('美女')
            }

        },
        props:['mymsg','age']

    })
    // 上面定义的子组件Header1,只能用在局部child里面

    let vm = new Vue({
        el: '#box',
        data: {
            msg: '我是父组件的数据',
            age : 999
        },
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50

父传子之属性认证
将props写成对象的形式:key是变量名,value是数据类型
如果传的值,不是指定的数据类型,就会报错
在这里插入图片描述

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化开发</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
    <!--    在组件上自定义属性,使用属性指令,绑定好变量-->
    <child :mymsg="msg" :age="age"></child>
    <hr>
</div>
</body>
<script>
    // 定义一个全局组件,在全局组件中定义一个局部组件
    Vue.component('child', {
        template: `
          <div>
          <h1>我是子组件---从父组件传值过来--{{ mymsg }}---{{ age }}</h1>
          <br>
          <button @click="handleClick">点我看美女--{{ name }}</button>
          <hr>
          </div>
        `,
        data() {
            return {
                name: 'lqz'
            }
        },
        methods: {
            handleClick() {
                alert('美女')
            }

        },
        props: {
            mymsg: String,
            age: Number
        }// 写属性名字,就属性认证

    })
    // 上面定义的子组件Header1,只能用在局部child里面

    let vm = new Vue({
        el: '#box',
        data: {
            msg: '我是父组件的数据',
            age: "999"
        },
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

组件通讯之子传父(通过事件)

通过事件传,不能随件传。一般需要点击按钮子类的事件去传
实现一个在子组件中点击按钮,子组件按钮点击一下,整个组件就消失:父组件里面的变量isShow变成false
isShow是父组件的变量,但是点的是子组件的按钮
就是点的是子组件的按钮,让父组件消失,这样就实现了从子传父
  • 1
  • 2
  • 3
  • 4

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化开发</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!--    通过自定义事件,绑定方法-->
    <child v-if="isShow" @myevent="handleShow"></child>
    <hr>

</div>
</body>
<script>
    // 定义一个全局组件,在全局组件中定义一个局部组件
    Vue.component('child', {
        template: `
          <div>
          <h1>我是子组件</h1>
          <br>
          <button @click="handleClick">点我消失和显示</button>
          <hr>
          </div>
        `,
        data() {
            return {
                b: false
            }
        },
        methods: {
            handleClick() {
            // 触发myevent的执行,把子组件的变量b,传入到事件对应的方法上
                this.$emit('myevent',this.b)
            }
        },
    })
    // 上面定义的子组件Header1,只能用在局部child里面

    let vm = new Vue({
        el: '#box',
        data: {
            isShow: true,
        },
        methods: {
            handleShow(b) {
                this.isShow = b
            }
        }
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53

捋一下逻辑

现在就是想点击子组件的时候,让子组件消失;通过自定义事件    <child v-if="isShow" @myevent="handleShow"></child>
 @myevent是随便写的事件名,事件前面就是@符号。对着一个方法handleShow,handleShow是父组件里面的一个方法,再去父组件里面写这个方法
 这里的handleShow传了一个参数,传不传都可以。让data里面的isShow等于b。
 现在就相当于在父组件里面写了一个事件@myevent,并且给他绑定了一个方法handleShow
 现在要做的是,点击子组件的button按钮的时候<button @click="handleClick">点我消失和显示</button>,触发子组件里面的methods里面的handleClick() 执行
 在handleClick()里面触发父组件事件的执行:触发@myevent执行
 这里是固定写法:this.$emit('myevent',this.b),  this.b是参数。意思是触发myevent事件,把子组件中的变量b,传入到事件对应的方法上
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

ref属性

可以实现组件间通信。这个ref属性是Vue提供的
  • 1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在Vue中通过this.$refs.属性值 拿到的是
    如果放在普通标签上,拿到的就是普通标签本身(就是上面的input框,拿到input框就能点出name,value属性)
    如果放在子组件上,拿到的就是子组件对象(如下)
        通过组件对象,直接获取,修改属性,直接执行方法,传值,返回值
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述

如上:this.$refs.mychild这个是子组件对象,this.$refs.mychild.b就是这个对象里面的属性
  • 1

在这里插入图片描述

上面的是拿值,还可以改值。但是,直接改了,我们看不到。我们加一个v-if
  • 1

在这里插入图片描述
在这里插入图片描述

通过父组件的点击,控制子组件的显示

上面除了可以改,可以打印子组件的值,还可以调用子组件的方法
  • 1
  • 2
  • 3

在这里插入图片描述

用了这个之后发现:this.$refs.mychild,能拿到里面的对象了。里面的属性、方法就都可以拿到了。直接用、直接改就行了。有返回值的话,可以拿到(如下)
就不需要考虑是父传子,还是子传父了
也可以有结果,是在子组件里面return的数据,现在在父组件里面打印了出来
  • 1
  • 2
  • 3

在这里插入图片描述

所以:用了ref属性之后,根本就不需要考虑子传父、父传子了。因为对象都能拿到了。
  • 1

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化开发</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
    <input type="text" ref="myinput" name="lqz">
    <child ref="mychild"></child>
    <hr>
    <button @click="handleClick">点我试一下</button>

</div>
</body>
<script>
    // 定义一个全局组件,在全局组件中定义一个局部组件
    Vue.component('child', {
        template: `
          <div>
          <h1 v-if="b">我是子组件</h1>
          <br>
          <button>点我消失和显示</button>
          <hr>
          </div>
        `,
        data() {
            return {
                b: true
            }
        },
        methods: {
            handle1(msg){
                // alert(msg)
                return 'xf'
            }
        },
    })
    // 上面定义的子组件Header1,只能用在局部child里面

    let vm = new Vue({
        el: '#box',
        data: {
        },
        methods: {
            handleClick(){
                // console.log(this.$refs.myinput.name)
                // console.log(this.$refs.mychild.b)
                // this.$refs.mychild.b = !this.$refs.mychild.b
                // 调用子组件的方法
                let res = this.$refs.mychild.handle1('致命诱惑')
                console.log(res)
            }
        }
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

动态组件

在这里插入图片描述
在这里插入图片描述

现在想要实现的是:点击上面的时候,下面就显示对应的组件
绑定事件就行
  • 1
  • 2

代码

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化开发</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
<!--    这里可以写简单的语法   "who='index'"-->
    <span @click="who='index'">首页</span>&nbsp&nbsp
    <span @click="who='girl'">美女</span>&nbsp&nbsp
    <span @click="who='boy'">帅哥</span>&nbsp&nbsp
    <hr>
<!--    加:是绑定;who是一个变量;根组件里面要有这个-->
    <component :is="who"></component>

</div>
</body>
<script>
    Vue.component('index', {
        template: `<div>
          首页
        </div>`,

    })
    Vue.component('girl', {
        template: `<div>
                   美女
                    </div>`,
    })
    Vue.component('boy', {
        template: `<div>
                   帅哥
                    </div>`,
    })

    let vm = new Vue({
        el: '#box',
        data: {
            who:'index'
        },
        methods: {}
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

keep-alive的使用

在这里插入图片描述

现在就想实现,当我切过来的时候,这个值还在
只需要用keep-alive包上这个组件就行了
  • 1
  • 2

在这里插入图片描述
在这里插入图片描述

代码:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件化开发</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="box">
    <!--    这里可以写简单的语法   "who='index'"-->
    <span @click="who='index'">首页</span>&nbsp&nbsp
    <span @click="who='girl'">美女</span>&nbsp&nbsp
    <span @click="who='boy'">帅哥</span>&nbsp&nbsp
    <hr>
    <!--    加:是绑定;who是一个变量;根组件里面要有这个-->
    <keep-alive>
        <component :is="who"></component>
    </keep-alive>

</div>
</body>
<script>
    Vue.component('index', {
        template: `<div>
          首页
        </div>`,

    })
    Vue.component('girl', {
        template: `
          <div>
          美女
          <input type="text" v-model="name">
          </div>`,
        data() {
            return {
                name: ""
            } //在组件里面data必须是一个方法
        }
    })
    Vue.component('boy', {
        template: `<div>
                   帅哥
                    </div>`,
    })

    let vm = new Vue({
        el: '#box',
        data: {
            who: 'index'
        },
        methods: {}
    })
</script>
</html>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55

Vue脚手架创建Vue项目

我们现在想把前端做成一个项目,用到Vue脚手架
类似于工地上面盖楼的时候,先在搭上架子,再在固定地方填砖就行
Vue的脚手架:帮我创建一些空的文件,我需要在文件的固定地方填代码就行,其实就是一个框架(django创建的那个项目,也可以叫django的脚手架)
  • 1
  • 2
  • 3

安装

先安装node
    1、去node的官网:https://nodejs.org/zh-cn/ 下载node的解释器
  • 1
  • 2

在这里插入图片描述

    2、直接下一步

    装好了之后,就多了两个命令
        node(类似于Python)
        npm(类似于pip)
  • 1
  • 2
  • 3
  • 4
  • 5

安装脚手架

    1、npm install -g @vue/cli
        -g :装全局
    2、使用npm安装第三方模块,速度慢一些,换成淘宝镜像:cnpm(这个是在国内下载的)
        先用npm下载cnpm
            npm install -g cnpm --registry=https://registry.npm.taobao.org
        以后都用cnpm代替npm,做包管理

        用cnpm安装脚手架
            cnpm install -g @vue/cli
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

创建Vue项目

    vue create 项目名
    或
    vue ui  (图像化界面的创建)

    vue ui
  • 1
  • 2
  • 3
  • 4
  • 5

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    Bable:建项目之后,写一些新的语法(es6,es7),Bable把新的语法转成es5。主要是对低版本语法的兼容
    Router:路由
    Vuex:状态管理器
  • 1
  • 2
  • 3

在这里插入图片描述
在这里插入图片描述

    点击【保存预设并创建项目】
  • 1

上面的是图形化界面创建,下面用命令行创建

    vue create 项目名
        在指定目录下敲:vue create mysecendvue
  • 1
  • 2

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

    跟图形化界面是一样的
    最后有点慢,是因为要去GitHub上面拉一个空的项目,没有网的话,别人拷贝也行
  • 1
  • 2

我们用pycharm开发Vue项目

在这里插入图片描述
在这里插入图片描述

    这样项目就起来了。但是我们想向运行Python一下,点一下run就运行
  • 1

在这里插入图片描述
在这里插入图片描述

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/运维做开发/article/detail/801324
推荐阅读
相关标签
  

闽ICP备14008679号

        
cppcmd=keepalive&