vue-day04

发布时间 2023-09-19 19:24:48作者: Py玩家

补充1:定时任务和延迟任务,js中如何实现

setTimeout(function(){},3000) # 3s后执行匿名函数
var t=setInterval(function(){},3000) # 每隔3s执行匿名函数
clearInterval(t) # 停止定时任务
t=null
    1 定时切换图片
    2 倒计时效果
    3 定时向后端发请求

 

与后端交互的三种方式

前后端要打通,从前端发送ajax,核心:使用js发送http请求,接收返回
原生js,可以开启ajax,但是原生js开启,比较麻烦,需要做浏览器兼容
jq,写了个兼容所有浏览器的  $.ajax(),不仅仅有ajax,还封装了很多dom操作,vue中使用它,不合适
axios:第三方的ajax包(咱们用)
fetch: 原生js发送ajax请求,有的浏览器也不兼容

后端

views

from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.views import APIView
from rest_framework.viewsets import ViewSet


class Index(ViewSet, APIView):
    @action(methods=['POST'], detail=False)
    def look(self, request, *args, **kwargs):
        print('llnb')
        response = Response({'name': '彭于晏', 'age': 19})
        response['Access-Control-Allow-Origin'] = '*'
        return response

urls

from django.contrib import admin
from django.urls import path
from rest_framework.routers import SimpleRouter

from app01.views import Index

router = SimpleRouter()
router.register('index', Index, 'index')
urlpatterns = [
    path('admin/', admin.site.urls),
]
urlpatterns += router.urls

方式一:使用jq的ajax

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Title</title>
</head>
<body>
<div id="APP">
    <p>name:{{ name }}</p>
    <p>age:{{ age }}</p>
    <button @click="handlerAge">点击显示名字和年龄</button>
</div>
</body>
<script>

    let vm = new Vue({
        el: '#APP',
        data: {
            name: '',
            age: ''
        },
        methods: {
            handlerAge() {
                var _this = this
                $.ajax({
                    url: 'http://127.0.0.1:8000/index/look/',
                    type: 'POST',
                    success: function (data) {
                        console.log(typeof data)

                        _this.name = data.name
                        _this.age = data.age

                    }
                })
            }
        },

    })
</script>
</html>

方式二:使用fetch

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <title>Title</title>
</head>
<body>
<div id="APP">
    <p>name:{{ name }}</p>
    <p>age:{{ age }}</p>
    <button @click="handlerAge">点击显示名字和年龄</button>
</div>
</body>
<script>

    let vm = new Vue({
        el: '#APP',
        data: {
            name: '',
            age: ''
        },
        methods: {
            handlerAge() {
                fetch('http://127.0.0.1:8000/index/look/').then(res => res.json()).then(res1 => this.name = res1.name)

            }
        },

    })
</script>
</html>

方式三:使用axios(以后用这个)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <title>Title</title>
</head>
<body>
<div id="APP">
    <p>name:{{ name }}</p>
    <p>age:{{ age }}</p>
    <button @click="handlerAge">点击显示名字和年龄</button>
</div>
</body>
<script>

    let vm = new Vue({
        el: '#APP',
        data: {
            name: '',
            age: ''
        },
        methods: {

            handlerAge() {
                let _this = this
                axios.get('http://127.0.0.1:8000/index/look/').then(function (res) {
                    console.log(res.data)
                    _this.name = res.data.name
                    _this.age = res.data.age
                })

            }
        },

    })
</script>
</html>

显示小电影案咧

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <script src="https://cdn.staticfile.org/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
    <title>Title</title>
</head>
<body>

<div id="box">
    <button @click="handleClick">加载电影数据</button>
    <p>加载的数据:</p>
    <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: []
        },
        methods: {
            handleClick() {
                axios.get("http://127.0.0.1:8000/show/look/").then(res => {
                    console.log(res.data.data.films) // axios 自动包装data属性 res.data
                    this.dataList=res.data.data.films
                }).catch(err => {
                    console.log(err);
                })
            }
        }
    })
</script>
</html>
</html>

后端

class Show(ViewSet, APIView):
    @action(methods=['GET'], detail=False)
    def look(self, request, *args, **kwargs):
        with open('fliems.json', 'rt', encoding='utf-8') as f:
            res = json.load(f)
        response = Response(res)
        response['Access-Control-Allow-Origin'] = '*'
        return response

路由

from django.contrib import admin
from django.urls import path
from rest_framework.routers import SimpleRouter

from app01.views import Index, Show

router = SimpleRouter()
router.register('show', Show, 'show')
urlpatterns = [
    path('admin/', admin.site.urls),
]
urlpatterns += router.urls

计算属性

1 计算属性是基于它们的依赖变量进行缓存的
2 计算属性只有在它的相关依赖变量发生改变时才会重新求值,否则不会变(函数只要页面变化,就会重新运算)
3 计算属性就像Python中的property,可以把方法/函数伪装成属性
4 计算属性,必须有返回值

HTML

<!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>实现输入input中后名字首字母大写</h1>
    <!--    <input type="text" v-model="username">-&ndash;&gt;{{username.substring(0, 1).toUpperCase() + username.substring(1)}}-->
    <input type="text" v-model="username">--->{{getUpperCase()}}
    <br>
    <input type="text" v-model="age">---->{{age}}

    <h2>通过计算属性实现--->当属性用</h2>
    <input type="text" v-model="username1">--->{{getName}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            username: '',
            age: '',
            username1: ''
        },
        methods: {
            getUpperCase() {
                console.log('函数执行我执行了')
                return this.username.substring(0, 1).toUpperCase() + this.username.substring(1)
            }
        },
        computed: {
            getName() {
                console.log('计算属性执行了')
                return this.username1.substring(0, 1).toUpperCase() + this.username1.substring(1)
            }
        }
    })
</script>
</html>

 

基本使用:实现首字母大写

<!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>实现输入input中后名字首字母大写</h1>
    <!--    <input type="text" v-model="username">-&ndash;&gt;{{username.substring(0, 1).toUpperCase() + username.substring(1)}}-->
    <input type="text" v-model="username">--->{{getUpperCase()}}
    <br>
    <input type="text" v-model="age">---->{{age}}

    <h2>通过计算属性实现--->当属性用</h2>
    <input type="text" v-model="username1">--->{{getName}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            username: '',
            age: '',
            username1: ''
        },
        methods: {
            getUpperCase() {
                console.log('函数执行我执行了')
                return this.username.substring(0, 1).toUpperCase() + this.username.substring(1)
            }
        },
        computed: {
            getName() {
                console.log('计算属性执行了')
                return this.username1.substring(0, 1).toUpperCase() + this.username1.substring(1)
            }
        }
    })
</script>
</html>

重写过滤案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>

</head>
<body>
<div id="app">
    <input type="text" v-model="search">
    <hr>
    <ul>
        <li v-for="item in newdataList">{{item}}</li>
    </ul>


</div>
</body>


<script>
    let vm = new Vue({
        el: '#app',
        data: {
            search: '',
            dataList: ['a', 'at', 'atom', 'attoo', 'be', 'beyond', 'cs', 'csrf'],
        },
        computed: {
            newdataList() {
                return this.dataList.filter(item => item.indexOf(this.search) >= 0)
            }
        }

    })


</script>
</html>

监听属性:属性如果发生变化,就会执行某个函数

<!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>
    <input type="text" v-model="username"> --->{{username}}
</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            username: '',
        },
        watch: {
            username(newValue, oldValue) {
                console.log('老值', oldValue)
                console.log('新值', newValue)
                console.log('我发生变化了')
            }
        }

    })
</script>
</html>

 

Vue生命周期

new Vue()---->创建出来---》页面关闭---》被销毁掉----》整个整个过程经历了一个周期----》vue帮咱们提供了一些钩子函数[写了就会执行,不写就不执行],到某个阶段,就会触发某个函数的执行

8 个生命周期钩子函数
    beforeCreate            创建Vue实例之前调用
    created                    创建Vue实例成功后调用
    beforeMount                渲染DOM之前调用
    mounted                    渲染DOM之后调用
    beforeUpdate            重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
    updated                    重新渲染完成之后调用
    beforeDestroy            销毁之前调用
    destroyed                销毁之后调用
vue实例有生命周期,每个组件也有这8个生命周期

  8个声明周期钩子,什么情况会用到
    created:用的最多,变量初始化完成了(data中得数据),在这里,我们发送ajax请求
    beforeDestroy:组件销毁之前会执行
    组件创建,就执行一个定时任务[每隔1s,打印一个helloworld]
    组件销毁,定时任务要销毁,如果定时任务不销毁,会一直执行

 

 

HTML

<!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>
    <input type="text" v-model="username"> --->{{username}}

    <h1>使用组件</h1>
    <button @click="handleShow">显示组件,隐藏组件</button>
    <hr>
    <child v-if="show"></child>
    <hr>
</div>


</body>
<script>
    // 组件有自己的html,css,js,事件。。。。
    // ``  模板字符串,es6语法
    // 在组件中,data必须是个函数,返回对象
    //1  定义一个全局组件
    Vue.component('child', {
        template: `
          <div>
          <button @click="back">后退</button>
          {{ name }}
          <button @click="forword">前进</button>
          </div>`,
        data() {
            return {
                name: '首页',
                t: null
            }
        },
        methods: {
            back() {
                alert('后退了')
            },
            forword() {
                alert('前进了')
            }
        },
        beforeCreate() {
            console.log('beforeCreate')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        created() {
            console.log('created')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)

            // 启动一个定时器
            this.t = setInterval(() => {
                console.log('hello world')
            }, 1000)
        },
        beforeMount() {
            console.log('beforeMount')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        mounted() {
            console.log('mounted')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        beforeUpdate() {
            console.log('beforeUpdate')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        updated() {
            console.log('updated')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },
        beforeDestroy() {
            console.log('beforeDestroy')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
            // 销毁定时器
            clearInterval(this.t)
            this.t = null
        },
        destroyed() {
            console.log('destroyed')
            console.log('当前el状态:', this.$el)
            console.log('当前data状态:', this.$data)
            console.log('当前name状态:', this.name)
        },


    })


    var vm = new Vue({
        el: '#app',
        data: {
            username: '',
            show: false
        },
        methods: {
            handleShow() {
                this.show = !this.show
            }
        }


        // beforeCreate() {
        //     console.log('beforeCreate')
        // },
        // created() {
        //     console.log('created')
        // },
        // beforeMount() {
        //     console.log('beforeMount')
        // },
        // mounted() {
        //     console.log('mounted')
        // },
        // beforeUpdate() {
        //     console.log('beforeUpdate')
        // },
        // updated() {
        //     console.log('updated')
        // },
        // beforeDestroy() {
        //     console.log('beforeDestroy')
        // },
        // destroyed() {
        //     console.log('destroyed')
        // },


    })
</script>
</html>

组件介绍

组件就是:扩展 HTML 元素,封装可重用的代码,目的是复用
例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html
组件把js,css,html放到一起,有逻辑,有样式,有html


组件的分类:
    全局组件:可以放在根中,可以在所有组件中使用
    局部组件:只能在当前组件中使用

定义全局组件

<!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>
    <hr>
    <child></child>
    <hr>

    <h1>第二次出现</h1>
    <child></child>
</div>


</body>
<script>
    //1  定义一个全局组件,vue2中,组件必须在一个标签中
    Vue.component('child', {
        template: `
          <div>
          <button @click="back">后退</button>
          {{ title }}
          <button>前进</button>
          </div>
        `,
        data() {
            return {
                title: '我是首页'
            }
        },
        methods: {
            back() {
                console.log('退了')
            }
        }
    })

    /

    var vm = new Vue({
        el: '#app',
        data: {},


    })
</script>
</html>

 

定义局部组件

<!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>
    <lqz></lqz>
</div>


</body>
<script>


    //
    var lqz={
                template: `
                  <div>
                  <h1>我是局部组件</h1>
                  <img :src="url" alt="" height="400px">
                  </div>`,
                data() {
                    return {
                        url: 'http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg'
                    }
                },
                methods: {}
            }

    // 根组件
    var vm = new Vue({
        el: '#app',
        data: {},
        // 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使用
        components: {
            lqz
        }
    })
</script>
</html>

总结

1 全局组件是使用Vue.component定义的,可以在全局任意组件中使用
2 局部组件是定义在某个组件内的:components,只能用在当前组件中
3 组件可以嵌套定义和使用

扩展:elementui,提供给咱们很多全局组件

组件间通信

组件嵌套

父组件被数据传递给子组件
        自定义属性
        1 在子组件中自定义属性,使用属性指令绑定父组件的变量
        2 在子组件中,使用props接受 ['属性名','属性名2']
        3 在子组件中,使用属性名即可
    子组件把数据传递给父组件
        自定义事件
        1 父组件中自定义事件:<lqz @myevent="handelEvent"></lqz>
        2 子组件中只要执行 this.$emit('myevent'),就会触发自定义事件对应的函数

组件间通信值父传子

<!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>
    <hr>
    <lqz :url="url" :myshow="true"></lqz>
    <hr>
</div>


</body>
<script>
    // 2
    var lqz = {
        template: `
          <div>
          <h1>我是局部组件</h1>
          <img :src="url" alt="" height="400px">
          <button @click="handleCheck">点我看myshow类型</button>
          </div>`,
        data() {
            return {}
        },
        methods: {
            handleCheck() {
                console.log(this.myshow)
                console.log(typeof this.myshow)
            }
        },
        props: ['url', 'myshow']
    }

    // 根组件
    var vm = new Vue({
        el: '#app',
        data: {
            url: 'http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg',

        },
        // 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使用
        components: {
            lqz,

        }


    })
</script>
</html>

组件间通信之子传父

<!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>
    接受到的子组件输入的内容是:{{username}}
    <hr>
    <lqz @myevent="handelEvent"></lqz>
    <hr>
</div>


</body>
<script>
    // 2
    var lqz = {
        template: `
          <div>
          <h1>我是局部组件</h1>
          <img :src="url" alt="" height="400px">
          <br>
          <input type="text" v-model="username">
          <button @click="handleSend">传递到父组件</button>
          </div>`,
        data() {
            return {
                url: 'http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg',
                username: ''
            }
        },
        methods: {
            handleSend() {
                // 传递给父组件
                this.$emit('myevent', this.username)
            }
        }
    }

    // 根组件
    var vm = new Vue({
        el: '#app',
        data: {
            username: ''
        },
        methods: {
            handelEvent(username) {
                console.log('父组件自定义事件的event执行了')
                console.log(username)
                this.username = username
            }
        },
        // 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使用
        components: {
            lqz,

        }


    })
</script>
</html>

补充

以后前后端分离
    前端是前端(小程序)
    后端是后端,完全没联系
    后端只写接口,没有template和static    
    media 要有

ref属性

ref属性,vue提供的,写在标签上

可以写在普通标签:在vue中使用 this.$refs.名字  拿到dom对象,可以原生操作
可以写在组件上:在vue中使用 this.$refs.名字  拿到[组件]对象,组件属性,方法直接使用即可

HTML


<!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>ref属性放在普通标签上</h1>
<input type="text" v-model="username" ref="myinput">
<br>
<img src="http://pic.imeitou.com/uploads/allimg/230331/7-230331110I0.jpg" alt="" height="300px" ref="myimg">



<h1>ref放在组件上</h1>
<hr>
<lqz ref="mylqz"></lqz>
<hr>


<button @click="handleClick">点我执行函数</button>


<br>
{{username}}


</div>
</body>
<script>
var vm = new Vue({
el: '#app',
data: {
username: ''
},
methods: {
handleClick() {
console.log(this.$refs)
// 通过key,取到标签,拿到原生dom,通过dom操作,控制标签
// this.$refs.myinput.value = 'lqz'
// this.$refs.myimg.src='https://img2.woyaogexing.com/2021/09/22/3c686eb61fe34696840c478584b73d36!400x400.jpeg'


// 放在组件上---》现在在父组件中,能拿到子组件对象,对象中的属性和方法直接用即可
console.log(this.$refs.mylqz)
// this.$refs.mylqz.title = 'sb'
// this.username=this.$refs.mylqz.title
this.$refs.mylqz.handleBack()



}
},
components: {
lqz: {
template: `
<div>
<button @click="handleBack">后退</button>
{{ title }}
<button>前进</button>
</div>`,
data() {
return {
title: "首页"
}
},
methods: {
handleBack() {
alert('后退了')
}
}
}
}


})
</script>
</html>