Vue之与后端交互的三种方式、显示小电影案例、计算属性、监听属性、Vue生命周期、组件介绍和使用、组件间通信、ref属性

发布时间 2023-09-19 21:39:19作者: 吼尼尼痛

与后端交互的三种方式

后端写了一堆接口

前段会了

前后端要打通===》从前端发送 ajax ===》核心:用js发送http请求,接收返回

  原生js,可以开启可以开启ajax,但是原生js开启,比较麻烦,需要做浏览器兼容,有坑(基本不写)

  jq,写了个兼容所有浏览器的 $.ajax(),不仅仅有ajax,还封装了很多dom操作

    如果vue中使用它,不合适

  axios:第三方的ajax包(咱们用)

  fetch:原生js发送ajax请求,有的浏览器也不兼容

方式一:jq的ajax

前端

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>与后端交互的三种方式</title>
    <script src="../js/vue.js"></script>
    <script src="https://code.jquery.com/jquery-3.7.0.min.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div class="text-center">
                    <h1>与后端交互的三种方式</h1>
                    <button @click="handleLoad">点击加载数据</button>
                    <hr>
                    你的名字是:{{ name }}
                    你的年龄是:{{ age }}
                </div>
            </div>
        </div>


    </div>

</div>
</body>


<script>
    var vm = new Vue({
            el: '#app',
            data: {
                name: '',
                age: '',
            },
            methods: {
                handleLoad() {
                    // 请求发送成功,后端执行了,但是被浏览器拦截了,因为有跨域问题
                    // 当前地址,如果向非浏览器地址栏中的地址发送请求,就会出现跨域
                    // 1 ajax请求方式 1     jQuery的ajax
                    var _this = this
                    $.ajax({
                        url: 'http://127.0.0.1:8000/',
                        type: 'get',
                        dataType: 'json',
                        success: function (data) {
                            _this.name = data.name
                            _this.age = data.age
                        }
                    })
                }
            }
        }
    )

    // :value="username" 对input标签做绑定,他只能做单向的绑定,js变量变,页面会变;页面变,js变量不会变
</script>
</html>

Djang后端

from django.http import JsonResponse


# Create your views here.

def index(request):
    if request.method == 'GET':
        print('来了,老弟')
        res = JsonResponse({'name': 'zfq', 'age': 18})
        res['Access-Control-Allow-Origin'] = '*'
    return res

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

<script>
// 3 使用axios(以后都用这个)
                handleLoad() {
                    var _this = this
                    axios.get('http://127.0.0.1:8000/').then(function (res) {
                        console.log(res.data)
                        _this.name = res.data.name
                        _this.age = res.data.age
                    })
                },

// 箭头函数版本
handleLoad() {
                    axios.get('http://127.0.0.1:8000/').then(res => {
                        this.name = res.data.name
                        this.age = res.data.age
                    })
                },
</script>

显示电影小案例

前端Vue

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <script src="https://unpkg.com/axios/dist/axios.min.js"></script>

</head>
<body>
<div id="app">
    <button @click="handleLoad">点我,加载小电影</button>
    <hr>
    <ul>
        <li v-for="item in dataList">
            <h3>电影名字:{{item.name}}</h3>
            <h3>导演:{{item.director}}</h3>
            <p>电影介绍:{{item.synopsis}}</p>
            <p><img :src="item.poster" alt="" height="300px"></p>
        </li>
    </ul>


</div>
</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            dataList: []
        },
        methods: {
            handleLoad() {
                axios.get('http://127.0.0.1:5000/films').then(res => {
                    console.log(res.data)
                    this.dataList = res.data.data.films
                })

            }
        }

    })


</script>
</html>

 

flask版本后端

from flask import Flask, jsonify
import json

app = Flask(__name__)

@app.route('/films')
def films():
    with open('./filme.json', 'rt', encoding='utf-8') as f:
        res = json.load(f)

    res = jsonify(res)
    res.headers = {'Access-Control-Allow-Origin': '*'}
    return res


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

Djang版本后端

import json
from django.http import JsonResponse


def filmes(request):
    with open(r'E:\软件\pythonProject\Vueday04\static\filme.json', 'rt', encoding='utf8') as z:
        filme = json.load(z)

    res = JsonResponse(filme)
    print(res)
    # res.headers = {'Access-Control-Allow-Origin': '*'}
    res['Access-Control-Allow-Origin'] = '*'
    return res

 

计算属性

1 计算属性是基于它们的依赖变量进行缓存的

2 计算属性只有在它的相关依赖变量发生改变时才会重新求值,否则不会变(函数只要页面变化,就会重新运行)

3 计算属性就像Python中的property,可以把方法/函数伪装成属性

4 计算属性必须要有返回值

<!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>
    <script src="./js/vue.js"></script>
    <link rel="stylesheet" href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/3.4.1/css/bootstrap.min.css"
          integrity="sha384-HSMxcRTRxnN+Bdg0JdbxYKrThecOKuH5zCYotlSAcp1+c8xmyTe9GYg1l9a69psu" crossorigin="anonymous">
</head>
<body>
<div id="app">
    <div class="container-fluid">
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <div class="text-center">
                    <h1>计算属性重写过滤案例</h1>
                    <input type="text" v-model="myText" >
                    <hr>
                    <li v-for="item in newdatalist">{{item}}</li>
                </div>
            </div>
        </div>


    </div>

</div>
</body>


<script>
    var vm = new Vue({
        el: '#app',
        data: {
            myText: '',
            datalist: ['a', 'at', 'atom', 'be', 'beyond', 'cs', 'csrf', 'e', 'egg', 'eabc'],

        },
        computed: {
            newdatalist() {
                return this.datalist.filter(item => item.indexOf(this.myText) >= 0)
            }
        }
    })

</script>
</html>

监听属性

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

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <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>
    let 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请求

  beforeDestory:组件销毁之前会执行

    组件创建,就执行一个定时任务(每隔1s,打印一个helloworld)

    组件销毁,定时任务要销毁,如果定时任务不销毁,会一直执行

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Vue生命周期钩子</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>Vue生命周期钩子</h1>
    <input type="text" v-model="username">--->{{username}}

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

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

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

    })
</script>
</html>

组件介绍和使用

组件就是:扩展 HTML 元素,封装可重用的代码,目的是复用

例如:有一个轮播图,可以在很多页面中使用,一个轮播有js,css,html

组件把js,css,html放到一起,有逻辑,有样式,有html

 

组件的分类:

  全局组件:可以放在根中,可以在所有组件中使用

  局部组件:只能在当前组件中使用

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>局部组件和全局组件</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>局部组件和全局组件</h1>

    <h1>使用组件</h1>
    <child>

    </child>

    <hr>
    <h1>第二次出现</h1>
    <child></child>
    <hr>
    <zfq></zfq>


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


    })
    // 根组件
    let vm = new Vue({
        el: '#app',
        data: {},
        methods: {},
        // 局部组件是定义在某个组件内,可以定义多个,只能在它父组件中使用,不能到别的地方使用
        components: {
            'zfq': {
                template: `
                  <div><h1>我是局部组件</h1>
                  <img :src="url" alt="" height="400px">
                  </div>`,
                data() {
                    return {
                        url: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.OmSRUFqgbOybdhSkhOsLFgAAAA?w=199&h=298&c=7&r=0&o=5&dpr=1.3&pid=1.7'
                    }
                },
                methods: {},
            }
        },

    })
</script>
</html>

组件总结

1 全局组件是使用Vue.component 定义的,可以在全局任意组件中使用

2 局部组件是定义在某个组件内的:components,只能用在当前组件中

3 组件可以嵌套定义和使用

 

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

组件间通信

组件嵌套:

  父组件被传递给子组件

    自定义属性

    1 在子组件中自定义属性,使用属性指令绑定父组件的变量

    2 崽子组件中,使用props接收['属性名','属性名']

    3 在子组件中,使用属性名即可

  子组件把数据传递给父组件

    自定义属性

    1 父组件中自定义事件:<zfq @myevent="handelEvent"></zfq>

    2 子组件中只要执行 this.$emit('myevent'),就会触发自定义事件对应的函数

组件间通信之父传子

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件间通信</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>组件间通信</h1>
    <h2>父传子</h2>

    <zfq :url="url" :myshow="true"></zfq>


</div>
</body>
<script>
    var zfq = {
        template: `
          <div>
          <h1>我是局部组件</h1>
          <img :src="url" alt="" >
          <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: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.OmSRUFqgbOybdhSkhOsLFgAAAA?w=199&h=298&c=7&r=0&o=5&dpr=1.3&pid=1.7'


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

        }


    })
</script>
</html>

组件间通信之子传父

 

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>组件间通信</title>
    <script src="./js/vue.js"></script>
</head>
<body>
<div id="app">
    <h1>组件间通信</h1>
    <h2>子传父</h2>
    接受到的子组件输入的内容是:{{username}}
    <hr>
    <zfq @myevent="handleEvent"></zfq>
    <hr>

</div>
</body>
<script>
    var zfq = {
        template: `
          <div>
          <h1>我是局部组件</h1>
          <img :src="url" alt="">
          <br>
          <input type="text" v-model="username">
          <button @click="handleSend">传递到父组件</button>
          </div>`,
        data() {
            return {
                url: 'https://tse4-mm.cn.bing.net/th/id/OIP-C.OmSRUFqgbOybdhSkhOsLFgAAAA?w=199&h=298&c=7&r=0&o=5&dpr=1.3&pid=1.7',
                username: '',

            }
        },
        methods: {
            handleSend() {
                // 传递给父组件
                this.$emit('myevent', this.username)
            }
        },
    }

    // 根组件

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

        }


    })
</script>
</html>

补充:

以后前后端分离

  前端是前端(小程序)

  后端是后端,完全没联系

 

  后端只写接口,没有template和static

 

  media 要有

ref属性

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

  可以写在普通标签上,在Vue中使用 this.$refs.名字  拿到dom对象,可以原生操作

  可以写在组件上:在vue中使用 this.$refs.名字  拿到[组件]对象,组件属性,方法直接

用即可

<!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>
    <zfq ref="myzfq"></zfq>
    <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 = 'zfq'
                this.$refs.myimg.src = 'https://tse4-mm.cn.bing.net/th/id/OIP-C.OmSRUFqgbOybdhSkhOsLFgAAAA?w=199&h=298&c=7&r=0&o=5&dpr=1.3&pid=1.7'

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


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

    })
</script>
</html>