当前位置:   article > 正文

vue购物车案例、v-model进阶、与后端交互_购物车前后端交互

购物车前后端交互

一 购物车案例

- 结算

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>购物车结算</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  7. <style>
  8. table, td {
  9. border: 1px solid black;
  10. text-align: center;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <div id="box">
  16. <table>
  17. <tr>
  18. <td>商品名称</td>
  19. <td>价格</td>
  20. <td>数量</td>
  21. <td>选择</td>
  22. </tr>
  23. <tr v-for="item in dataList">
  24. <td>{{item.name}}</td>
  25. <td>{{item.price}}</td>
  26. <td>{{item.number}}</td>
  27. <td><input type="checkbox" :value="item" v-model="checkGroup"></td>
  28. </tr>
  29. </table>
  30. <br>已选商品:{{checkGroup}}
  31. <br>总价:{{getPrice()}}
  32. </div>
  33. </body>
  34. <script>
  35. var vm = new Vue({
  36. el: '#box',
  37. data: {
  38. dataList: [
  39. {name: '今瓶没', price: 99, number: 2},
  40. {name: '西柚记', price: 59, number: 1},
  41. {name: '水壶转', price: 89, number: 5},
  42. ],
  43. checkGroup: [],
  44. },
  45. methods: {
  46. getPrice() {
  47. let sum_price = 0
  48. for (i in this.checkGroup) { // 这里的 i 是索引
  49. sum_price += this.checkGroup[i]['number'] * this.checkGroup[i]['price']
  50. }
  51. return sum_price
  52. }
  53. }
  54. })
  55. </script>
  56. </html>

img

- 全选/全不选

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>全选/全不选</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  7. <style>
  8. table, td {
  9. border: 1px solid black;
  10. text-align: center;
  11. }
  12. </style>
  13. </head>
  14. <body>
  15. <div id="box">
  16. <table>
  17. <tr>
  18. <td>商品名称</td>
  19. <td>价格</td>
  20. <td>数量</td>
  21. <td>全选/全不选<input type="checkbox" v-model="allChecked" @change="checkAll"></td>
  22. </tr>
  23. <tr v-for="item in dataList">
  24. <td>{{item.name}}</td>
  25. <td>{{item.price}}</td>
  26. <td>{{item.number}}</td>
  27. <td><input type="checkbox" :value="item" v-model="checkGroup" @change="checkOne"></td>
  28. </tr>
  29. </table>
  30. <br>已选商品:{{checkGroup}}
  31. <br>总价:{{getPrice()}}
  32. </div>
  33. </body>
  34. <script>
  35. var vm = new Vue({
  36. el: '#box',
  37. data: {
  38. dataList: [
  39. {name: '今瓶没', price: 99, number: 2},
  40. {name: '西柚记', price: 59, number: 1},
  41. {name: '水壶转', price: 89, number: 5},
  42. ],
  43. checkGroup: [],
  44. allChecked: false,
  45. },
  46. methods: {
  47. getPrice() {
  48. let sum_price = 0
  49. for (i in this.checkGroup) { // 这里的 i 是索引
  50. sum_price += this.checkGroup[i]['number'] * this.checkGroup[i]['price']
  51. }
  52. return sum_price
  53. },
  54. checkAll() {
  55. if (this.checkGroup.length > 0) {
  56. this.checkGroup = []
  57. } else {
  58. this.checkGroup = this.dataList
  59. }
  60. },
  61. checkOne() {
  62. // if (this.checkGroup.length === this.dataList.length) {
  63. // this.allChecked = true
  64. // } else {
  65. // this.allChecked = false
  66. // }
  67. this.allChecked = this.checkGroup.length === this.dataList.length;
  68. }
  69. }
  70. })
  71. </script>
  72. </html>

img

- 数量加减

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>控制加减</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  7. <link href="https://cdn.bootcdn.net/ajax/libs/twitter-bootstrap/4.5.3/css/bootstrap.min.css" rel="stylesheet">
  8. </head>
  9. <body>
  10. <div class="row">
  11. <div id="box" class="col-md-4 offset-md-1 text-center mt-5 ">
  12. <table class="table table-bordered">
  13. <thead>
  14. <tr>
  15. <th scope="col">商品名称</th>
  16. <th scope="col">单价</th>
  17. <th scope="col">数量</th>
  18. <th scope="col">全选/全不选 <input type="checkbox" v-model="allChecked" @change="checkAll"></th>
  19. </tr>
  20. </thead>
  21. <tbody>
  22. <tr v-for="item in dataList">
  23. <td>{{item.name}}</td>
  24. <td>{{item.price}}</td>
  25. <td>
  26. <button class="btn link btn-sm" @click="reduceNum(item)">-</button>
  27. {{item.number}}
  28. <button class="btn link btn-sm" @click="item.number++">+</button>
  29. </td>
  30. <td><input type="checkbox" :value="item" v-model="checkGroup" @change="checkOne"></td>
  31. </tr>
  32. <tr class="text-left">
  33. <td colspan="4">总价:{{getPrice()}}
  34. </tr>
  35. </tbody>
  36. </table>
  37. </div>
  38. </div>
  39. </body>
  40. <script>
  41. var vm = new Vue({
  42. el: '#box',
  43. data: {
  44. dataList: [
  45. {name: '今瓶没', price: 99, number: 1},
  46. {name: '西柚记', price: 59, number: 1},
  47. {name: '水壶转', price: 89, number: 1},
  48. ],
  49. checkGroup: [],
  50. allChecked: false,
  51. },
  52. methods: {
  53. getPrice() {
  54. let sum_price = 0
  55. for (i in this.checkGroup) {
  56. sum_price += this.checkGroup[i]['number'] * this.checkGroup[i]['price']
  57. }
  58. return sum_price
  59. },
  60. checkAll() {
  61. if (this.checkGroup.length > 0) {
  62. this.checkGroup = []
  63. } else {
  64. this.checkGroup = this.dataList
  65. }
  66. },
  67. checkOne() {
  68. // if (this.checkGroup.length === this.dataList.length) {
  69. // this.allChecked = true
  70. // } else {
  71. // this.allChecked = false
  72. // }
  73. this.allChecked = this.checkGroup.length === this.dataList.length;
  74. },
  75. reduceNum(item) {
  76. if (item.number === 1) {
  77. item.number = 1
  78. } else {
  79. item.number--
  80. }
  81. }
  82. }
  83. })
  84. </script>
  85. </html>

img

二:v-model进阶

v-model 之 lazy、number、trim

  • lazy:等待input框的数据绑定时区焦点之后再变化
  • number:数字开头,只保留数字,后面的字母不保留;字母开头,都保留
  • trim:去除首位的空格
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>v-model 之 lazy、number、trim</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  7. </head>
  8. <body>
  9. <div id="box">
  10. <input type="text" v-model="myText1" placeholder="normal"> {{myText1}}
  11. <br>
  12. <input type="text" v-model.lazy="myText2" placeholder="lazy"> {{myText2}}
  13. <br>
  14. <input type="text" v-model.number="myText3" placeholder="number"> {{myText3}}
  15. <br>
  16. <input type="text" v-model.trim="myText4" placeholder="trim"> {{myText4}}
  17. </div>
  18. </body>
  19. <script>
  20. var vm = new Vue({
  21. el: '#box',
  22. data: {
  23. myText1: '',
  24. myText2: '',
  25. myText3: '',
  26. myText4: '',
  27. },
  28. })
  29. </script>
  30. </html>

img

 

三 与后端交互 - ajax

版本1 - 出现了跨域问题

前端:index.html
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Vue与后端交互 - 出现了跨域问题</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  7. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  8. </head>
  9. <body>
  10. <div id="box">
  11. <button @click="handleClick">加载数据</button>
  12. </div>
  13. </body>
  14. <script>
  15. let vm = new Vue({
  16. el: '#box',
  17. data: {},
  18. methods: {
  19. handleClick() {
  20. $.ajax({
  21. url: 'http://127.0.0.1:5000/', // 发送请求的url,本地的5000端口,是flask的默认端口
  22. method: 'get',
  23. success: (data) => {
  24. console.log(data)
  25. }
  26. })
  27. }
  28. }
  29. })
  30. </script>
  31. </html>
后端:main.py
  1. from flask import Flask # 这里用轻量级的Flask框架来测试
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def index():
  5. print('请求来了')
  6. return 'Hello World'
  7. if __name__ == '__main__':
  8. app.run()

img

这里可以看出:前端向后端成功发送了请求,后端也成功响应了,但是前端却报错了

这是因为:跨域问题的存在,浏览器检测到前端和后端不是来自同一个,所以认为这是不安全的,所以就拦截了该资源的传递

想要解决这个问题,就要实现:CORS,也就是 跨域资源共享

版本2 - 解决了跨域问题

前端:index.html
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Vue与后端交互 - 解决了跨域问题</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  7. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  8. </head>
  9. <body>
  10. <div id="box">
  11. <button @click="handleClick">加载数据</button>
  12. <p>加载的数据:{{myText}}</p>
  13. </div>
  14. </body>
  15. <script>
  16. let vm = new Vue({
  17. el: '#box',
  18. data: {
  19. myText: ''
  20. },
  21. methods: {
  22. handleClick() {
  23. $.ajax({
  24. url: 'http://127.0.0.1:5000/',
  25. method: 'get',
  26. success: (data) => {
  27. console.log(data)
  28. this.myText = data
  29. }
  30. })
  31. }
  32. }
  33. })
  34. </script>
  35. </html>
后端:main.py
  1. from flask import Flask, make_response
  2. app = Flask(__name__)
  3. @app.route('/')
  4. def index():
  5. print('请求来了')
  6. res = make_response('Hello World')
  7. res.headers['Access-Control-Allow-Origin'] = '*' # 访问控制允许的源 设置为全部
  8. return res
  9. if __name__ == '__main__':
  10. app.run()

img

版本3 - 后端读取json文件传到前端

json文件:file.json
  1. {
  2. "name": "Darker",
  3. "age": "18",
  4. "gender": "male"
  5. }
前端:index.html
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Vue与后端交互 - json</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  7. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  8. </head>
  9. <body>
  10. <div id="box">
  11. <button @click="handleClick">加载数据</button>
  12. <p>加载的数据:{{myText}}</p>
  13. </div>
  14. </body>
  15. <script>
  16. let vm = new Vue({
  17. el: '#box',
  18. data: {
  19. myText: ''
  20. },
  21. methods: {
  22. handleClick() {
  23. $.ajax({
  24. url: 'http://127.0.0.1:5000/',
  25. method: 'get',
  26. success: (data) => {
  27. console.log(data)
  28. this.myText = data
  29. }
  30. })
  31. }
  32. }
  33. })
  34. </script>
  35. </html>
后端:main.py
  1. import json
  2. from flask import Flask, jsonify
  3. app = Flask(__name__)
  4. @app.route('/')
  5. def index():
  6. print('请求来了')
  7. with open('file.json', mode='rt', encoding='utf-8') as f:
  8. dic = json.load(f)
  9. res = jsonify(dic)
  10. res.headers['Access-Control-Allow-Origin'] = '*'
  11. return res
  12. if __name__ == '__main__':
  13. app.run()

img

fetch

1.简介

① fetch介绍

提供了一个 JavaScript 接口,用于访问和操纵 HTTP 管道的一些具体部分,例如请求和响应

它还提供了一个全局 fetch() 方法,该方法提供了一种简单,合理的方式来跨网络异步获取资源

② fetch基本格式
  1. fetch('http://example.com/movies.json')
  2. .then(function(response) {
  3. return response.json();
  4. })
  5. .then(function(myJson) {
  6. console.log(myJson);
  7. });

2.实例

json文件:file.json
  1. {
  2. "name": "Darker",
  3. "age": "18",
  4. "gender": "male"
  5. }
后端:main.py
  1. import json
  2. from flask import Flask, jsonify
  3. app = Flask(__name__)
  4. @app.route('/')
  5. def index():
  6. print('请求来了')
  7. with open('file.json', mode='rt', encoding='utf-8') as f:
  8. dic = json.load(f)
  9. res = jsonify(dic)
  10. res.headers['Access-Control-Allow-Origin'] = '*'
  11. return res
  12. if __name__ == '__main__':
  13. app.run()
前端:index.html
  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <title>Vue与后端交互 - fetch</title>
  6. <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  7. <script src="https://cdn.bootcdn.net/ajax/libs/vue/2.6.12/vue.min.js"></script>
  8. </head>
  9. <body>
  10. <div id="box">
  11. <button @click="handleClick">加载数据</button>
  12. <p>加载的数据:</p>
  13. <ul>
  14. <li >姓名:{{name}}</li>
  15. <li >年龄:{{age}}</li>
  16. <li >性别:{{gender}}</li>
  17. </ul>
  18. </div>
  19. </body>
  20. <script>
  21. let vm = new Vue({
  22. el: '#box',
  23. data: {
  24. name:'',
  25. age: '',
  26. gender: ''
  27. },
  28. methods: {
  29. handleClick() {
  30. fetch('http://127.0.0.1:5000/').then(response => {
  31. return response.json()
  32. }).then(json => {
  33. console.log('从后端获取的json数据', json) // success 获取的数据
  34. this.name = json.name
  35. this.age = json.age
  36. this.gender = json.gender
  37. }).catch(ex => {
  38. console.log('出现了异常', ex) // 抛出异常
  39. })
  40. }
  41. }
  42. })
  43. </script>
  44. </html>

img

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

闽ICP备14008679号