【vue2】表单控制,购物车案例,vue生命周期,与后端交互ajax

1. 表单控制

<!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>

    <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">未知
    </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">网球
    </p>
    {{hobby}}
</div>
</body>

<script>
  new Vue({
    el:'#app',
    data:{
      name:'',
      password:'',
      isRemember:false, // checkbox单选,使用布尔类型
      gender:'', // radio单选,使用字符串
      hobby:[], // checkbox 多选使用数组
    }
  })
</script>
</html>

2. 购物车案例

2.1 js中for

python中只有基于迭代的循环,没有基于索引的循环
js、java、go中有基于迭代和索引的两种
js中for循环
1 for(i=0;i<checkGroup.lengtgh;i++)  # 基于索引的循环
2 for (i in checkGroup)              # 基于迭代的循环
3 for (i of checkGroup)              # es6中  循环
4 数组内置方法.forEach()  
5 jquery  $.each 循环

2.2 for案列

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>

</body>
<script>
    var goodList = [
        {id: 1, name: '小汽车', price: 12, count: 1},
        {id: 2, name: '钢笔', price: 12, count: 34},
        {id: 3, name: '鸡蛋', price: 2, count: 4},
        {id: 4, name: '面包', price: 9, count: 10},
    ]
    // 1 方式一:js的基于索引的循环
    // for (var i = 0; i< goodList.length; i++) {
    //     console.log(goodList[i])
    // }
    // 方式二:基于迭代的循环
    // for (i in goodList) {
    //     console.log(goodList[1])
    // }
    // 方式三:of循环,基于迭代的
    // for (i of goodList){
    //     console.log(i)
    // }
    // 方式四:数组的循环方法
    // goodList.forEach(item=>{
    //     console.log('---',item)
    // })
    // 5 jquery:引入
    // $.each(goodList,(i,v)=>{
    //     console.log(v)
    // })
</script>
</html>

2.3 购物车案列

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div id="app">
    <div class="container-fluid">
        <h1 class="text-center">购物车</h1>
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <table class="table table-bordered">
                    <thead>
                    <tr>
                        <th>商品id</th>
                        <th>商品名字</th>
                        <th>商品价格</th>
                        <th>商品数量</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="good in goodList">
                        <th>{{good.id}}</th>
                        <td>{{good.name}}</td>
                        <td>{{good.price}}</td>
                        <td>{{good.count}}</td>
                        <td><input type="checkbox" v-model="checkGroup" :value="good"></td>
                    </tr>

                    </tbody>
                </table>
                <hr>
                选中的商品是:{{checkGroup}}
                <br>
                总价格是:{{getPrice()}}

            </div>
        </div>

    </div>

</div>
</body>

<script>

    new Vue({
        el: '#app',
        data: {
            goodList: [
                {id: 1, name: '小汽车', price: 12, count: 1},
                {id: 2, name: '钢笔', price: 12, count: 2},
                {id: 3, name: '鸡蛋', price: 2, count: 4},
                {id: 4, name: '面包', price: 9, count: 7},
            ],
            checkGroup: []


        },
        methods: {
            getPrice() {
                // 取出checkGroup中得商品数量和商品价格相乘 做累加
                // js 中 for 循环
                var total = 0
                for (item of this.checkGroup) {
                    total += item.price * item.count
                }
                return total
            }
        }
    })
</script>
</html>

2.4 购物车全选,全不选

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div id="app">
    <div class="container-fluid">
        <h1 class="text-center">购物车</h1>
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <table class="table table-bordered">
                    <thead>
                    <tr>
                        <th>商品id</th>
                        <th>商品名字</th>
                        <th>商品价格</th>
                        <th>商品数量</th>
                        <th><input type="checkbox" v-model="checkAll" @change="handleChange">全选/全不选</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="good in goodList">
                        <th>{{good.id}}</th>
                        <td>{{good.name}}</td>
                        <td>{{good.price}}</td>
                        <td>{{good.count}}</td>
                        <td><input type="checkbox" v-model="checkGroup" :value="good" @change="handleCheckOne"></td>
                    </tr>

                    </tbody>
                </table>
                <hr>
                选中的商品是:{{checkGroup}}
                <br>
                总价格是:{{getPrice()}}

            </div>
        </div>

    </div>

</div>
</body>

<script>

    new Vue({
        el: '#app',
        data: {
            goodList: [
                {id: 1, name: '小汽车', price: 12, count: 1},
                {id: 2, name: '钢笔', price: 12, count: 2},
                {id: 3, name: '鸡蛋', price: 2, count: 4},
                {id: 4, name: '面包', price: 9, count: 7},
            ],
            checkGroup: []


        },
        methods: {
            getPrice() {
                // 取出checkGroup中得商品数量和商品价格相乘 做累加
                // js 中 for 循环
                var total = 0
                for (item of this.checkGroup) {
                    total += item.price * item.count
                }
                return total
            },
            handleChange(){
                if (this.checkAll){
                    this.checkGroup = this.goodList
                }else{
                    this.checkGroup=[]
                }
            },
            handleCheckOne(){
                // 如果checkGroup的长度等于goodList的长度,说明全选了,checkAll就应该变为true,否则就是false
                // if (this.checkGroup.length == this.goodList.length){
                //     this.checkAll = true
                // }else{
                //     this.checkAll = false
                // }
                //变短
                this.checkAll = this.checkGroup.length == this.goodList.length
            }
        }
    })
</script>
</html>

2.5 购物车数量加减

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="./js/vue.js"></script>
    <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
</head>
<body>
<div id="app">
    <div class="container-fluid">
        <h1 class="text-center">购物车</h1>
        <div class="row">
            <div class="col-md-6 col-md-offset-3">
                <table class="table table-bordered">
                    <thead>
                    <tr>
                        <th>商品id</th>
                        <th>商品名字</th>
                        <th>商品价格</th>
                        <th>商品数量</th>
                        <th><input type="checkbox" v-model="checkAll" @change="handleChange">全选/全不选</th>
                    </tr>
                    </thead>
                    <tbody>
                    <tr v-for="good in goodList">
                        <th>{{good.id}}</th>
                        <td>{{good.name}}</td>
                        <td>{{good.price}}</td>
                        <td><span class="btn link btn-sm" @click="handleDown(good)">-</span>{{good.count}}<span
                                class="btn link btn-sm" @click="good.count++">+</span>
                        </td>
                        <td><input type="checkbox" v-model="checkGroup" :value="good" @change="handleCheckOne"></td>
                    </tr>

                    </tbody>
                </table>
                <hr>
                选中的商品是:{{checkGroup}}
                <br>
                总价格是:{{getPrice()}}

            </div>
        </div>

    </div>

</div>
</body>

<script>

    new Vue({
        el: '#app',
        data: {
            goodList: [
                {id: 1, name: '小汽车', price: 1200000, count: 1},
                {id: 2, name: '钢笔', price: 12, count: 34},
                {id: 3, name: '鸡蛋', price: 2, count: 4},
                {id: 4, name: '面包', price: 9, count: 10},
            ],
            checkGroup: [],
            checkAll: false,


        },
        methods: {
            getPrice() {
                var total = 0
                for (item of this.checkGroup) {
                    total += item.price * item.count
                }
                return total
            },
            handleChange() {
                if (this.checkAll) {
                    this.checkGroup = this.goodList
                } else {
                    this.checkGroup = []
                }
            },
            handleCheckOne() {
                this.checkAll = this.checkGroup.length == this.goodList.length
            },
            handleDown(good) {
                if (good.count > 1) {
                    good.count--
                } else {
                    alert('不能再少了,受不了了')
                }

            }
        }
    })

</script>
</html>

3. v-model进阶

lazy: 等待input框的数据绑定时区焦点之后再变化
number: 数字开头,只保留数字,后面的字母不保留,字母开头,都保留
trim: 去除首位的空格
<!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>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>
</body>
<script>
    new Vue({
        el: '#app',
        data:{
            name1:'',
            name2:'',
            name3:'',
        }
    })
</script>
</html>

4. vue生命周期

4.1 官方原图与理解图

4.2 vue实例过程()

1. 实例创建,数据放到实例中
2. 挂在模板:el-->div
3. 该页面,改变量,都会相互影响update
4. 销毁实例

4.3 4个过程,对应八个函数,一次执行

钩子函数 描述
beforeCreate 创建Vue实例之前调用,data,el都没有
created 创建Vue实例成功后调用(可以再此处发送异步请求后端数据,data有了,el没有的)
beforeMount 渲染DOM之前调用,data有了,el没有
mounted 渲染DOM之后调用
beforeUpdate 重新渲染之前调用(数据更新等操作时,控制DOM重新渲染)
updated 重新渲染完成之后调用
beforeDestroy 销毁之前调用
destroyed 销毁之后调用
<!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>vue生命周期</h1>
    {{name}}
</div>

</body>
<script>
    var vm = new Vue({
        el: '#app',
        data: {
            name: 'zzz',
        },
        beforeCreate() {
            console.log('我要开始创建了:beforeCreate')
        },
        create() {
            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>

4.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>vue生命周期</h1>
    <button @click="handleShow">点我组件显示和消失</button>
    <hr>
    <child v-if="show"></child>
    <hr>
</div>
</body>
<script>
    // 定义一个全局组件
    Vue.component('child', {
        template: `
          <div>
          <button>后退</button>
          {{ title }}
          <button @click="handleClick">前进</button>
          </div>`,
        data(){
            return{
                title: '好看的首页',
                t:''
            }
        },
        methods:{
            handleClick(){
                // alert('前进')
                this.title='zzz'
            }
        },
        beforeCreate(){
            console.log('beforeCreate')
            console.log(this.$data)
            console.log(this.$el)
        },
        created(){
            console.log('created')
            console.log(this.$data)
            console.log(this.$el)
            // 开启定时器,每隔3s,打印hello
            this.t=setInterval(()=>{
                console.log('hello')
            },3000)
        },
        beforeMount() {
            console.log('beforeMount')
            console.log(this.$data)
            console.log(this.$el)
        },
        mounted() {
            console.log('mounted')
            console.log(this.$data)
            console.log(this.$el)
        },
        beforeUpdate() {
            console.log('beforeUpdate')
        },
        updated() {
            console.log('updated')
        },
        beforeDestroy() {
            console.log('当前状态:beforeDestroy')
        },
        destroyed() {
            console.log('当前状态:destroyed')
            // 销毁定时器
            clearInterval(this.t)
            this.t=null

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

    })
</script>
</html>

1. 组件向后端发送请求,获取数据,应该放在 created 写,此时data已经有数据了
2. destroyed做一些资源清理性的工作
组件创建,开启定时器,不停的打印hello,在destroyed中对定时器进行销毁

补充:js 定时任务和延时任务   
   # 延时任务
   setTimeout(()=>{
      console.log('3s后执行我')
   },3000)
   #定时任务
   setInterval(()=>{
     console.log('hello')
   },3000)

5. 与后端交互

5.1 与后端交互理解

1. js原生发送ajax请求:new XMLHttpRequest(),浏览器器兼容性不好,于是jquery基于它做了封装出了jquery的ajax方法,XMLHttpRequest很多bug
2. jquery的ajax vue中用的少
3. js原生提供的fetch,现在官方主推这个,不执行ie浏览器  promsie风格
4. axios:vue中常用的的,它也是封装了XMLHttpRequest   promsie风格

5.2 使用jquery的ajax与后端交互

<!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>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

</head>
<body>
<div id="app">
    <h1>jquery的ajax与后端交互</h1>
    <button @click="handleLoad1">点击加载数据</button>
    <br>
    <p>名字是:{{name}}</p>
    <p>年龄是:{{age}}</p>
    <hr>
</div>

</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            name:'',
            age:0
        },
        methods:{
            handleLoad1(){
                $.ajax({
                    url:'http://127.0.0.1:5000',
                    type:'get',
                    success:data=>{
                        console.log(typeof data)
                        data = JSON.parse(data) // data是字符串类型,需要转成对象类型
                        console.log(typeof data)
                        this.name=data.name
                        this.age=data.age
                    }
                })
            }
        }
    })
</script>
</html>

a.py

from flask import Flask, jsonify

app = Flask(__name__)


@app.route('/')
def index():
    res = jsonify({'name': 'zzz', 'age': 18})
    # 处理了跨域()  在响应头中加入 django写后端 {'Access-Control-Allow-Origin': '*'}
    res.headers = {'Access-Control-Allow-Origin': '*'}
    return res


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

5.3 js原生的fetch与后端交互

<!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>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

</head>
<body>
<div id="app">
    <h1>js原生的fetch与后端交互</h1>
    <button @click="handleLoad2">点击加载数据</button>
    <br>
    <p>名字是:{{name}}</p>
    <p>年龄是:{{age}}</p>
    <hr>

</div>

</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            name:'',
            age:0
        },
        methods:{
            handleLoad2(){
                fetch('http://127.0.0.1:5000').then(res => res.json()).then(res=>{
                    console.log(res)
                    console.log(typeof res)
                    this.name = res.name
                    this.age = res.age
                })
            }
        }
    })
</script>
</html>

5.4 axios与后端交互

<!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>
    <script src="http://libs.baidu.com/jquery/2.0.0/jquery.min.js"></script>

</head>
<body>
<div id="app">
    <h1>axios与后端交互</h1>
    <button @click="handleLoad3">点击加载数据</button>
    <br>
    <p>名字是:{{name}}</p>
    <p>年龄是:{{age}}</p>
    <hr>

</div>

</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            name:'',
            age:0
        },
        methods:{
            handleLoad3() { // 用的很少
                axios.get('http://127.0.0.1:5000/').then(res => {
                    console.log(res.data)  // 后端真正的数据在res.data中
                    this.name = res.data.name
                    this.age = res.data.age
                })

            },

        }
    })
</script>
</html>

6. 显示电影小案列

<!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">

    <h1>电影小案例</h1>
    <ul>
        <li v-for="film in filmList">
            <h2>电影名:{{film.name}}</h2>
            <img :src="film.poster" alt="" height="400px" width="300px">
        </li>
    </ul>

</div>


</body>

<script>

    var vm = new Vue({
        el: '#app',
        data: {
            filmList: []
        },
        created() {
            axios.get('http://127.0.0.1:5000/films').then(res => {
                this.filmList = res.data.data.films
            })
        }


    })
</script>
</html>

a.py


from flask import Flask, jsonify

app = Flask(__name__)

import json


@app.route('/films')
def films():
    with open('./film.json', 'r', encoding='utf-8') as f:
        data = json.load(f)
    res = jsonify(data)
    res.headers = {'Access-Control-Allow-Origin': '*'}
    return res
if __name__ == '__main__':
    app.run()

7. 跨域请求如何解决?

跨域指的是从一个域名去请求另外一个域名的资源。即跨域名请求!跨域时,浏览器不能执行其他域名网站的脚本,是由浏览器的同源策略造成的,是浏览器施加的安全限制。
## jsonp

- 原理:因为script标签发请求不受同源策略的限制,所以可以通过动态构建script节点,利用节点的src属性,发出get请求,从而绕开ajax引擎
- 具体实现:前端通过在请求的url指定一个回调函数,同时在window上声明这个函数,然后服务器返回该函数调用,同时传入参数,因为是使用script标签请求的,所以会把后端返回的数据当作js脚本执行,那么就调用了原先在window上已经定义了的这个函数
- 有种前端定义函数,服务器端‘调用函数’的感觉
- 缺陷:该方式只能用于get请求

## CORS

- 全称 : “跨域资源共享” (Cross-Origin Resource Sharing)
- 使用cors的方式,需要在服务器端配置
- 浏览器将cors请求分成两类:
- 简单请求:浏览器发出请求,就会在该请求的头信息中,增加一个origin字段,这个origin字段说明了本次请求来自哪个源,服务器端设置Access-Control-Allow-Orgin,指定允许该源允许跨域,这样ajax引擎就不会拦截本次响应,这样就解决了跨域问题了
- 非简单请求:比如发送put请求,那么浏览器会发出一次预检请求,判断该域名是否在服务器的白名单中,如果收到肯定回复后才会发起请求


## postMessage

- 这是一个h5中新增的特性,可以实现多窗口间的信息传递
- 通过获取指定窗口的引用,然后调用postMessage来发送信息,使用 window.onmessage 来接收信息,以此实现不同源之间的信息交换。

## window.name

- 基于同一个窗口中设置了window.name 后不同源的页面也可以访问
- 假如有:a b 页面同源、 c 不同源
- 实现原理:先在不同源的子页面(c页面)设置window.name=xxx,然后跳转到一个和父级同源的页面(b页面),这个时候父级页面(a页面)就可以访问同源的子页面中window.name的数据了
- 该方式的好处:可以传输的数据量大

## location.hash

- 在主页面中,通过iframe给不同源的窗口传递hash值,这样单向通信就实现了
- 那么如果实现双向通信呢?
- 由于iframe是没有办法访问到不同源的父级窗口的,所以不能直接修改父级窗口的hash值来实现双向通信,这是需要iframe中再加入一个iframe,该iframe和主页面是同源的,然后通过window.parent.parent.location.hash 来修改主页面的hash值。

## document.domain

- 利用document.domain设置主域名,实现相同子域名的跨域操作,此时主域名下的cookie就能够被子域名所访问。
- 如果有主域名相同,子域名不同的iframe的话,也可以对这个iframe进行操作。

## websocket

- 使用websocket协议,因为这个协议没有同源限制

## http-proxy

- webpack配置代理解决跨域问题
posted @   |相得益张|  阅读(125)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!
点击右上角即可分享
微信分享提示