vue之vue生命周期和ajax请求


一、表单控制

# 我们之前所学的input标签中有很多类型 checkbox和radio 这些都是单选或则多选的那么绑定的变量 该是什么类型为好呢?

# input:checkbox(单选,多选),radio(单选)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>表单控制</h1>
    <p>用户名:<input type="text" v-model="name"></p>
    <p>密码:<input type="text" v-model="password"></p>
    <p><input type="checkbox" v-model="isRemember"> 记住密码</p>
    <!--因为记住密码只有两种状态 所以可以是布尔值 checkbox可以单选-->
    <p>
        <input type="radio" v-model="gender" value="1"><input type="radio" v-model="gender" value="2"><input type="radio" v-model="gender" value="0"> 未知
        <!--因为radio是单选 所以可以是字符串来判断 选择了什么  传递给后端的值 是value的值-->
    </p>
    <p>
        爱好:
        <input type="checkbox" value="篮球" v-model="hobby"> 篮球
        <input type="checkbox" value="足球" v-model="hobby"> 足球
        <input type="checkbox" value="乒乓球" v-model="hobby"> 乒乓球
        <input type="checkbox" value="橄榄球" v-model="hobby"> 橄榄球
        <!--checkbox如果是多选的话 可以使用数组  传递给后端的值 是value的值 其实也可以用数字--> 
    </p>
</div>
</body>
<script>
    new Vue({
        el: '#app',
        data: {
            name: '',
            password: '',
            isRemember: false,  // checkbox单选,使用布尔类型
            gender: '',  // radio单选,使用字符串
            hobby: [],  // checkbox 多选使用数组
        },
    })
</script>
</html>

二、购物车案例

1 补充

python中只有基于迭代的循环,没有基于索引的循环

java,go,js中是既有基于迭代的循环,也有基于索引的循环

js中的for循环

1 for(i=0;i<checkGroup.length;i++)     # 基于索引的循环
2 for (i in checkGroup)                # 基于迭代的循环
3 for (i of checkGroup)                # es6中 循环
4 数组内置方法.forEach()
5 jquery  $.each 循环

# 代码演示
# 定义一个数组
var goodList = [                
    {name: '今瓶没', price: 99, number: 2},
    {name: '西柚记', price: 59, number: 1},
    {name: '水壶转', price: 89, number: 5},
    {name: '特斯拉', price: 230000, number: 5},]
1 方式一:js的基于索引的循环  # 原生js基于索引的循环
    for (var i = 0; i< goodList.length; i++) {
         console.log(goodList[i])  # i就是索引,不能拿到数组中的值
     }
2 方式二:基于迭代的循环  # 原生js基于迭代的循环
    for (i in goodList){
         console.log(goodList[i])
        }  # i 也是索引,不能拿到数组中的值

 3 方式三:of 循环,基于迭代的  # 原生of循环
    for (i of goodList){
          console.log(i)
         }   # i就是数组中一个一个的值
 4 方式四:数组的循环方法  # 数组的内置方法
    goodList.forEach(item => {
           console.log('---', item)
     })    # item就是数组中一个一个的值

5 jquery:引入  # jquery方法
    $.each(goodList, (i, v) => {
          console.log(v)  # 可以有两个值 i是所以,v是数组中一个一个的值
 })

2 购物车代码

<div id="app">
    <div class="container-fluid">
        <h2 class="text-center">购物车案例</h2>
        <div class="col-md-6 col-md-offset-3">
            <table class="table-hover table table-striped">
                <thead>
                <tr>
                    <th>商品名称</th>
                    <th>商品单价</th>
                    <th>商品数量</th>
                    <th><input type="checkbox" v-model="checkAll" @change="handleChange">全选/取消</th>
                </tr>
                </thead>
                <tbody>
                <tr v-for="item in goodList">
                    <td>{{item.name}}</td>
                    <td>{{item.price}}</td>
                    <td><span class="btn link btn-sm" @click="handleClick(item)">-</span>{{item.number}}<span
                            class="btn link btn-sm"
                            @click="item.number++">+</span></td>  <!--这里++应该要传到后端判断有没有库存的 这里没有判断直接加了-->
                    <td><input type="checkbox" v-model="checkGroup" :value="item" @change="handleOne"></td>
                </tr>
                </tbody>
            </table>
            <br>
            <span>选中的商品:{{checkGroup}}</span>
            <br>
            <span>总价格:{{getPrice()}}</span>
        </div>
    </div>
</div>

<!--vm实例-->
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            goodList: [
                {name: '今瓶没', price: 99, number: 2},
                {name: '西柚记', price: 59, number: 1},
                {name: '水壶转', price: 89, number: 5},
                {name: '特斯拉', price: 230000, number: 5},],
            checkGroup: [],
            checkAll: false,
        },
        methods: {
            handleChange() {
                if (this.checkAll) {  // 如果全选 直接让选择的数组等于循环的数组
                    this.checkGroup = this.goodList
                } else {
                    this.checkGroup = [] // 取消就直接为空即可
                }
            },
            handleOne() {
                // if (this.checkGroup.length === this.goodList.length) {  // 就是判断两个数组是否相等
                //     this.checkAll = true  // 相等就是全选
                // } else {
                //     this.checkAll = false  // 没有就是没有全选 用户只选择了几个商品
                // }
                // 可以简写成这样
                this.checkAll = this.checkGroup.length === this.goodList.length
            },
            getPrice() {
                var total = 0
                for (item of this.checkGroup) {
                    total += item.price * item.number  // 计算总价格
                }
                return total
            },
            handleClick(item) {
                if (item.number > 1) {  // 不能让数量为小于0
                    item.number--
                } else {
                    alert('太少了,受不了了')
                }
            }
        },
    })
</script>

三、v-model进阶

lazy:等待input框的数据绑定时区焦点之后再变化
number:数字开头,只保留数字,后面的字母不保留;字母开头,都保留
trim:去除首尾的空格
<div id="app">
    <h1>v-model进阶</h1>
    <input type="text" v-model.lazy="name1"> ---->{{name1}}  
    <!--就是输入框失去焦点的时候 数据绑定才会把用户输入的值绑定 -->
    <br>
    <input type="text" v-model.number="name2"> ---->{{name2}}
    <!--就是如果开头是数字 那么不管后面写什么字符 只会保留数字  但是开头是字母的话 就会都保留-->
        <br>
    <input type="text" v-model.trim="name3"> ---->{{name3}}
    <!--这个就是取出首尾的空格-->
</div>

<script>
    new Vue({
        el: '#app',
        data: {
            name1: '',
            name2: '',
            name3: '',
        },
    })
</script>

四、vue的生命周期

# var vm = new Vue()
    -1 实例创建,数据放到实例中
    -2 挂在模板:el---》div
    -3 改页面,改变量,都会相互影响 update
    -4 销毁实例

# 这四个过程,对应八个函数,依次执行(到某个过程就会执行某个函数)
    beforeCreate    创建Vue实例之前调用,data,el都没有
    created            创建Vue实例成功后调用(可以在此处发送异步请求后端数据),data有了,el没有的
    beforeMount        渲染DOM之前调用 ,data有了,el没有
    mounted            渲染DOM之后调用
    beforeUpdate    重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
    updated            重新渲染完成之后调用
    beforeDestroy    销毁之前调用
    destroyed        销毁之后调用
# 如果写了这些钩子函数 那么一个组件的创建到销毁的过程中 到那个时间点就会触发对应的钩子函数

一个实例只能看到前面六个钩子函数,销毁是看不到的 所以需要组件

一个组件的创建到销毁是能看到八个钩子函数的  只要写了的话

 

1. 代码实现

<div id="app">
    <span>{{name}}</span>
</div>

<script>
    var vm = new Vue({
        el:'#app',
        data:{
            name:'jason'
        },
        beforeCreate() {
            console.log('beforeCreate')  // 实例前触发该钩子函数
        },
        created() {
            console.log('created')  // 实例创建后触发该钩子函数
        },
        beforeMount() {
            console.log('beforeMount')  // 渲染DOM之前, 渲染页面之前触发该钩子函数
        },
        mounted() {
            console.log('mounted')
        },  // 渲染DOM之后, 渲染页面之后触发 该钩子函数
        beforeUpdate() {
            console.log('beforeUpdate')
        },  // 重新渲染之前触发  就是修改了组件的内的东西之前 就会触发
        updated() {
            console.log('updated')
        },  // 重新渲染之后触发  就是修改之后
        beforeDestroy() {
            console.log('beforeDestroy')  // 销毁实例之前触发
        },
        destroyed() {
            console.log('destroyed') // 销毁实例之后触发
        },
    })
</script>

 

 2.创建组件

<div id="app">
    <button @click="handleClick">点击显示或取消组件</button>  <!--通过点击按钮模拟创建和销毁组件-->
    <div v-if="res">  <!--上面的点击事件和该变量都是 实例中的事件和变量 不是组件的-->
        <hr>
        <child></child>  <!--在实例中创建组件-->
        <hr>
    </div>
</div>

<script>
    Vue.component('child', {  // 创建组件 组件名为 child
        template: `
          <div>
          <h1>{{ name }}</h1>
          <button @click="handleClick">点我</button>  <!--该点击事件和变量 是组件中的 不是实例的-->
          </div>
        `,  // 组件的内容
        data() {
            return {  // 组件的变量需要返回才行
                name:'lqz'  
            }
        },
        methods: {
            handleClick(){
                this.name='tony'  // 点击事件 让name变成tony
            }
        },  // 也可以写methods
        // 也可以写钩子函数
        beforeCreate() {
            console.log('beforeCreate')  // 组件创建前触发该钩子函数
        },
        created() {
            console.log('created')  // 组件创建后触发该钩子函数
        },
        beforeMount() {
            console.log('beforeMount')  // 渲染DOM之前, 渲染页面之前触发该钩子函数
        },
        mounted() {
            console.log('mounted')
        },  // 渲染DOM之后, 渲染页面之后触发 该钩子函数
        beforeUpdate() {
            console.log('beforeUpdate')
        },  // 重新渲染之前触发  就是修改了组件的内的东西之前 就会触发
        updated() {
            console.log('updated')
        },  // 重新渲染之后触发  就是修改之后
        beforeDestroy() {
            console.log('beforeDestroy')  // 销毁组件之前触发
        },
        destroyed() {
            console.log('destroyed') // 销毁组件之后触发
        },
    })
var vm = new Vue({ el: '#app', data: { res: true, }, methods: { handleClick() { this.res = !this.res } }, }) </script>

                 

3 小案例

组件创建,开启定时器,不停的打印hello,在destroyed中对定时器进行销毁

-补充:js 定时任务和延时任务

# 延时任务
setTimeout(()=>{
    console.log('3s后执行我')   # 这个就三秒之后执行一次
},3000)

#定时任务
setInterval(()=>{
    console.log('hello')  # 这个是每三秒执行一次
},3000)

代码演示

<div id="app">
    <button @click="handleClick">点击显示或取消组件</button>  <!--通过点击按钮模拟创建和销毁组件-->
    <div v-if="res">  <!--上面的点击事件和该变量都是 实例中的事件和变量 不是组件的-->
        <hr>
        <child></child>  <!--在实例中创建组件-->
        <hr>
    </div>
</div>

<script>
    Vue.component('child', {  // 创建组件 组件名为 child
        template: `
          <div>
          <h1>name:{{ name }}</h1>
          <button @click="handleClick">
          </div>
        `,  // 组件的内容
        data() {
            return {  // 组件的变量需要返回才行
                name: 'lqz',
                t:''
            }
        },
        methods: {
            handleClick() {
                this.name = 'tony'  // 点击事件 让name变成tony
            }
        },  // 也可以写methods
        // 也可以写钩子函数
        beforeCreate() {
            console.log('beforeCreate')  // 组件创建前触发该钩子函数
        },
        created() {
            console.log('created')  // 组件创建后触发该钩子函数
            this.t = setInterval(() => {  
                console.log('hello')
            }, 3000)
        },
        beforeDestroy() {
            console.log('beforeDestroy')  // 销毁组件之前触发
            clearTimeout(this.t)  
            // 定时任务开启之后 就算销毁组件 还是会继续执行 这是不合理的 所以我们需要在组件销毁之后把 定时任务给取消了
            this.t = ''
        },
        destroyed() {
            console.log('destroyed') // 销毁组件之后触发
        },
    })

    var vm = new Vue({
        el: '#app',
        data: {
            res: true,
        },
        methods: {
            handleClick() {
                this.res = !this.res
            }
        },
    })
</script>

五、ajax请求

# 向后端发送ajax请求---》jq的ajax方法 我们之前学的ajax其实是jquery的方法 只是该方法名字叫做ajax
    -方案一: jq的ajax---》在vue中不推荐 jquery与vue是一个东西 两个的操作有点相违背
        jquery是为了方便我们去DOM
        vue是不用我们自己去操作DOM
        # 所以不推荐
    -方案二:js原生官方提供了一个 fetch方法
    -方案三:axios第三方 专门发送ajax请求第三方模块

后端

# 路由匹配
from django.urls import path
from app01 import views
urlpatterns = [
    path('index/', views.index)
]

# 试图函数
from django.http import JsonResponse

def index(request):
    response = JsonResponse({'name': 'lqz', 'age': 18})
    response['Access-Control-Allow-Origin'] = '*'  # 因为跨域问题 所以响应头需要加上这个东西
    return response

1 jquery发送ajax

<div id="app">
    <p><span>name:{{name}}</span></p>
    <p><span>age:{{age}}</span></p>
    <p>
        <button @click="handleClick">点击向后端发送ajax请求</button>
    </p>
</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: '',
            age: 0
        },
        methods: {
            handleClick() {
                // 第一种使用jquery发送ajax
                $.ajax({
                    url: 'http://127.0.0.1:8000/index/',
                    type: 'get',
                    success: data => {
                        this.name = data.name  // 从后端获取name和age
                        this.age = data.age
                    }
                })
            }
        },
    })
</script>

 2.原生fetch发送ajax

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: '',
            age: 0
        },
        methods: {
            handleClick() {
                // fetch('http://127.0.0.1:5000/index').then(function (res) {return res.json})
                // fetch('http://127.0.0.1:5000/index').then(res => res.json())  //还可以这样写
                fetch('http://127.0.0.1:8000/index/').then(res => res.json()).then(res => {
                    console.log(res)
                    this.name = res.name
                    this.age = res.age
})
            }
        },
    })
</script>

3.使用axios发送ajax请求

<script src="https://unpkg.com/axios/dist/axios.min.js"></script>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: '',
            age: 0
        },
        methods: {
            handleClick() {
                // 方式3:使用axios发送ajax请求  使用axios需要先导入链接
                axios.get('http://127.0.0.1:8000/index/').then(res => {
                console.log(res)
                this.name = res.data.name
                this.age = res.data.age
            })
            }
        },
    })
</script>

4 使用axios下载电影案例

4.1 后端

from django.http import JsonResponse
import json


def index(request):
    with open(r'./data.json', 'r', encoding='utf8') as f:  # 这个文件是提前爬出来的一些电影数据
        data = json.load(f)
    response = JsonResponse(data)
    response['Access-Control-Allow-Origin'] = '*'  # 因为跨域问题 所以响应头需要加上这个东西
    return response

5.2 前端

<div id="app">
    <ul>
        <li v-for="item in file_data">
            <h2>电影名字:{{item.name}}</h2>
            <p>电影简介:{{item.synopsis}}</p>
            <img :src="item.poster" alt="" height="200px" width="100px">
        </li>
    </ul>
</div>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            file_data: ''
        },
        created() {
            axios.get('http://127.0.0.1:8000/index/').then(res => {
                this.file_data = res.data.data.films
            })
        }
    })
</script>

 

posted @ 2022-10-26 18:48  stephen_hao  阅读(227)  评论(0编辑  收藏  举报