• ② 尚品汇的前台开发笔记【尚硅谷】【Vue】


    文章目录

    八、加入购物车

    点击 加入购物车 的时候,先发请求,把数据存储到服务器,然后再进行路由跳转

    在这里插入图片描述

    • 当点击 加入购物车 的时候,会跳转到 加入购物车成功的页面,到时候需要配置路由,进行路由跳转
      在这里插入图片描述

    路由跳转之前发请求

    api—请求接口

    //     src/api/index.js
    
    // 将产品添加到购物车中(或者 更新某一个产品个数)
    //   /api/cart/addToCart/{ skuId }/{ skuNum }  POST 带参数
    export const reqAddOrUpdateShopCart = (skuId,skuNum)=>{
       
        return requests({
       url:`/cart/addToCart/${
         skuId}/${
         skuNum}`,method:'POST'})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    将数据存储到服务器里

    1. 派发actions,发请求

      //       src / pages / detail /index.vue
      
      <div class="add">
       
       
            <a @click="addShopcar">加入购物车a>
      div>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
          // 加入购物车的回调函数
      addShopcar() {
           
            // 1. 发请求--将产品加入到数据库(通知服务器)
            //    服务器存储成功----进行路由跳转
            //    失败,给用户提示
           this.$store.dispatch( "detail/addOrUpdateShopCart",{
           skuId:this.$route.params.skuId,skuNum:this.skuNum});
      },
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9

    加入购物车以后(发请求),前台将参数带给服务器

    服务器写入数据成功,并没有返回其他的数据,只是返回code=200,代表这次成功

    ⚠ !!!因为服务器没有返回其余的数据,所以我们不需要vuex来存储数据

    1. 将参数带给服务器

      const actions = {
           
          // 将产品添加到购物车中
          async addOrUpdateShopCart({
            commit},{
            skuId,skuNum}){
           
              // 加入购物车返回的结果
              let result = await reqAddOrUpdateShopCart(skuId,skuNum);
              console.log('购物车',result);
              // 加入购物车以后(发请求),前台将参数带给服务器
              // 服务器写入数据成功,并没有返回其他的数据,只是返回code=200,代表这次成功
              // 因为服务器没有返回其余的数据,所以我们不需要vuex来存储数据
          },
      };
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15

    判断加入成功 或 失败

    async:只要有async返回的就是Promise,Promise返回的不是成功就是失败

    1. 发请求–将产品加入到数据库(通知服务器)

    2. 服务器存储成功----进行路由跳转

    3. 服务器存储失败------给用户提示

    //      src/pages/detail/index.vue
    
    	// 加入购物车的回调函数
        async addShopcar() {
       
          // 1. 发请求--将产品加入到数据库(通知服务器)
          //    服务器存储成功----进行路由跳转
          //    失败------给用户提示
          try {
       
            await this.$store.dispatch("detail/addOrUpdateShopCart", {
       skuId: this.$route.params.skuId,skuNum: this.skuNum,});
            // 成功了进行路由跳转
              .....
          } catch (error) {
       
            alert(error.message);
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    this.$store.dispatch("detail/addOrUpdateShopCart", {skuId: this.$route.params.skuId,skuNum: this.skuNum,});表示调用了addOrUpdateShopCart这个函数,👇调用这个函数,这个函数有async,说明这个函数的返回值是Promise函数

    await返回的是promise成功的值,但是我们要有成功做什么以及失败做什么…如果await的promise失败了,就会抛出异常,我们需要通过try…catch捕获处理

    所以在detail.vue中,给 加入购物车的回调函数加上 async

    //      src/store/detail/index.js
    
    	// 将产品添加到购物车中
        async addOrUpdateShopCart({
         commit }, {
         skuId, skuNum }) {
       
            // 加入购物车返回的结果
            // 加入购物车以后(发请求),前台将参数带给服务器
            // 服务器写入数据成功,并没有返回其他的数据,只是返回code=200,代表这次成功
            // 因为服务器没有返回其余的数据,所以我们不需要vuex来存储数据
            let result = await reqAddOrUpdateShopCart(skuId, skuNum);
            // 当前的这个函数,如果执行,返回promise
            // 👇代表服务器加入购物车成功
            if(result.code==200){
       
                return 'ok'; // 返回的只要是非空字符串就是成功
            }else{
       
                // 代表加入购物车失败
                return Promise.reject(new Error('false'));
            }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23

    成功后进行路由跳转

    注意:路由不是组件!!!??????❓

    路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。

    使用组件的步骤:创建-注册-引用-使用

    1. 创建路由,写到专门放路由的文件夹下

      在这里插入图片描述

    2. 编写路由配置项:src/router/index.js

      // 配置路由的地方
      import Vue from 'vue';
      import VueRouter from 'vue-router';
      // 使用插件
      Vue.use(VueRouter);
      
      // 引入路由组件
      import AddCartSuccess from '../pages/AddCartSuccess'
      
      // 先把VueRouter原型对象的push,先保存一份
      const originalPush = VueRouter.prototype.push
      const originalReplace = VueRouter.prototype.replace
      
      // 重写push | replace
      // 参数:告诉原来的push方法,你往哪里跳转(传递哪些参数)
      VueRouter.prototype.push = function push(location) {
           
          return originalPush.call(this, location).catch(err => err)
      }
      VueRouter.prototype.replace = function replace(location) {
           
          return originalReplace.call(this, location).catch(err => err)
      }
      
      // 配置路由
      export default new VueRouter({
           
          // 配置路由
          routes: [
              ...
              {
           
                  name: 'addcartsuccess',
                  path: '/addcartsuccess',
                  component: AddCartSuccess,
                  meta: {
            showFooter: true }
              },
              // 重定向:在项目跑起来的时候,访问/,立马让他定向到首页!!!
              {
           
                  path: '*',
                  redirect: '/home',
              }
          ],
          // 控制滚动条的滚动行为
          scrollBehavior(to, from, savedPosition) {
           
              // return 期望滚动到哪个的位置
              return {
            y: 0 }; // 始终滚动到顶部
          }
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
      • 53

    开始进行路由跳转,并进行路由传参

    在这里插入图片描述

    路由传参的话数据过多,在skuInfo里面,是个对象,以及还要带参数skuNum,地址栏会有点乱

    在这里插入图片描述

    所以这里我们只带skuNum参数传过去,其余复杂数据用会话存储—不持久化,会话结束数据消失

    浏览器存储功能:HTML5中新增的,分为本地存储和会话存储

    本地存储:持久化的,具有上限-----5M

    会话存储:不是持久化的(浏览器关闭等),

    在这里插入图片描述

        // 加入购物车的回调函数
        async addShopcar() {
       
          // 1. 发请求--将产品加入到数据库(通知服务器)
          //    服务器存储成功----进行路由跳转
          //    失败------给用户提示
          try {
       
            await this.$store.dispatch("detail/addOrUpdateShopCart", {
       
              skuId: this.$route.params.skuId,
              skuNum: this.skuNum,
            });
            // 成功了进行路由跳转,并将产品的信息带给下一级的路由组件
            // 会话存储 | 本地存储,一般存储的是字符串,所以将对象转换为字符串
            sessionStorage.setItem('SKUINFO',JSON.stringify(this.skuInfo))
            this.$router.push({
       
              name: "addcartsuccess",
              query:{
       skuNum:this.skuNum},
            });
          } catch (error) {
       
            alert(error.message);
          }
        },
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27

    本地存储 里面只能存储字符串格式 ,因此需要把对象转换为字符串JSON.stringify()

    获取本地存储数据,需要把里面的字符串转换为对象格式JSON.parse() 我们才能使用里面的数据。

    获取本地存储数据

    在这里插入图片描述

    开始渲染页面

       <div class="left-good">
             <div class="left-pic">
                <img :src="skuInfo.skuDefaultImg" />
             div>
             <div class="right-info">
                <p class="title">{
      { skuInfo.skuName }}p>
                <p class="attr">
                  <span v-for="attrName in skuInfo.skuSaleAttrValueList" :key="attrName.id">{
      { attrName.saleAttrName }} {
      {attrName.saleAttrValueName}}  span>
                  <span>数量:{
      {$route.query.skuNum}}span>
                p>
             div>
           div>
       <div class="right-gocart">
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    在这里插入图片描述

    购物车静态组件与修改

    在这里插入图片描述

    1. 跳转到detail商品详情页,携带参数

       <div class="right-gocart">
                <router-link :to="`/detail/${skuInfo.id}`" class="sui-btn btn-xlarge">查看商品详情router-link>
                <a href="javascript:">去购物车结算 > a>
       div>
      
      • 1
      • 2
      • 3
      • 4
    2. 跳转到购物车页面ShopCart

    九、完成ShopCart购物车模块业务

    在这里插入图片描述

    1. 引入和配置路由

      // 配置路由的地方
      import Vue from 'vue';
      import VueRouter from 'vue-router';
      // 使用插件
      Vue.use(VueRouter);
      
      // 引入路由组件
      import ShopCart from '../pages/ShopCart'
      
      // 先把VueRouter原型对象的push,先保存一份
      const originalPush = VueRouter.prototype.push
      const originalReplace = VueRouter.prototype.replace
      
      // 重写push | replace
      // 参数:告诉原来的push方法,你往哪里跳转(传递哪些参数)
      VueRouter.prototype.push = function push(location) {
           
          return originalPush.call(this, location).catch(err => err)
      }
      VueRouter.prototype.replace = function replace(location) {
           
          return originalReplace.call(this, location).catch(err => err)
      }
      
      // 配置路由
      export default new VueRouter({
           
          // 配置路由
          routes: [
              {
           
                  name: 'shopcart',
                  path: '/shopcart',
                  component: ShopCart,
                  meta: {
            showFooter: true },
              },
              // 重定向:在项目跑起来的时候,访问/,立马让他定向到首页!!!
              {
           
                  path: '*',
                  redirect: '/home',
              }
          ],
          // 控制滚动条的滚动行为
          scrollBehavior(to, from, savedPosition) {
           
              // return 期望滚动到哪个的位置
              return {
            y: 0 }; // 始终滚动到顶部
          }
      })
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47
      • 48
      • 49
      • 50
      • 51
      • 52
    2. 路由跳转

        <div class="right-gocart">
                <router-link :to="`/detail/${skuInfo.id}`" class="sui-btn btn-xlarge">查看商品详情router-link>
                <router-link to="/shopcart">去购物车结算 > router-link>
        div>
      
      • 1
      • 2
      • 3
      • 4

    向服务器发起请求,获取购物车数据

    向服务器发请求

    /api/cart/cartList GET 无参数

    //    src/api/index.js
    
    // 获取购物车列表数据   /api/cart/cartList  GET 无参数
    export const reqCartList = ()=>{
       
        return requests({
       url:'/cart/cartList',method:'GET'})
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    操作vuex 将数据存储到仓库中

    1. 新建一个仓库,用来存储购物车的数据
    //      src/store/shopcart/index.js
    
    import {
        reqCartList } from '@/api/index'
    const state = {
       };
    const mutations = {
       };
    const actions = {
       };
    const getters = {
       };
    export default {
       
        namespaced: true,
        state,
        mutations,
        actions,
        getters
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    1. 在大仓库中引用小仓库
    //      src/store/index.js
    
    import Vue from 'vue';
    import Vuex from 'vuex';
    // 需要使用插件
    Vue.use(Vuex);
    
    // 引入小仓库
    import home from './home'
    import search from './search'
    import detail from './detail'
    import shopcart from './shopcart';
    // 对外暴露Store类的一个实例
    export default new Vuex.Store({
       
        // 实现vuex仓库模块式开发存储数据
        modules:{
       
            home,
            search,
            detail,
            shopcart
        }
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. vuex三连环

      const actions = {
           
          // 获取购物车列表的数据
          async getCartList({
             commit }) {
           
              let result = await reqCartList();
              console.log('购物车列表',result);
          },
      };
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
        export default {
           
          name: 'ShopCart',
          mounted(){
           
            // 获取服务器数据
            this.getData();
          },
          methods:{
           
            // 获取个人购物车数据
            getData(){
           
              this.$store.dispatch('shopcart/getCartList');
            }
          }
        }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17

      注意:发请求的时候,获取不到你购物车里的数据,因为这里不知道购物车获取谁的数据,需要给用户加一个身份!所以需要 👉 UUID临时游客身份

      在这里插入图片描述

      在这里插入图片描述

    2. 开始真正的vuex三连环!!

      👇这个是shopcart仓库里面的数据,有点复杂,所以我们要简化

      在这里插入图片描述

      在这里插入图片描述

      import {
            reqCartList } from '@/api/index'
      
      const state = {
           
          cartList:[],
      };
      
      const mutations = {
           
          GETCARTLIST(state, cartList) {
           
              state.cartList = cartList;
          }
      };
      
      const actions = {
           
          // 获取购物车列表的数据
          async getCartList({
             commit }) {
           
              let result = await reqCartList();
              if (result.code == 200) {
           
                  commit('GETCARTLIST', result.data); // result.data 是个数组
              }
          },
      };
      
      const getters = {
           
          cartList(state){
           
              // state.cartList[0] 如果没有返回,至少是个数组
              return state.cartList[0]|| [];
          },
      };
      
      export default {
           
          namespaced: true,
          state,
          mutations,
          actions,
          getters
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12
      • 13
      • 14
      • 15
      • 16
      • 17
      • 18
      • 19
      • 20
      • 21
      • 22
      • 23
      • 24
      • 25
      • 26
      • 27
      • 28
      • 29
      • 30
      • 31
      • 32
      • 33
      • 34
      • 35
      • 36
      • 37
      • 38
      • 39
      • 40
      • 41
      • 42
      • 43
      • 44
      • 45
      • 46
      • 47

      现在仓库里面有了数据

    组件获取数据展示数据

    ...mapGetters("shopcart", ["cartList"]), 组件开始获取数据

    遍历用every

    <script>
    import {
        mapGetters } from "vuex";
    export default {
       
      name: "ShopCart",
      mounted() {
       
        // 获取服务器数据
        this.getData();
      },
      methods: {
       
        // 获取个人购物车数据
        getData() {
       
          this.$store.dispatch("shopcart/getCartList");
        },
      },
      computed: {
       
        ...mapGetters("shopcart", ["cartList"]),// 并不是真正的购物车列表数据
        // 真正的购物车列表数据
        cartInfoList() {
       
          // 至少是个空数组
          return this.cartList.cartInfoList || [];
        },
        // 计算购买产品的总价
        totalPrice() {
       
          let sum = 0;
          this.cartInfoList.forEach((item) => {
       
            // item是购物车列表的每一行数据
            sum += item.skuNum * item.cartPrice;
          });
          return sum;
        },
        // 判断底部的复选框是否勾选
        isAllChecked(){
       
          // 遍历每一个产品的isChecked,只要全部元素isChecked属性都为1,返回为真
          return this.cartInfoList.every(item=>item.isChecked==1)
        },
      },
    };
    </script>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48

    开始渲染数据

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    UUID临时游客身份

    在点击 加入购物车 的时候,告诉服务器你是谁

    在这里插入图片描述

    utils :放一些常用的功能模块,比如正则,uuid

    1. 将游客身份用会话存储(sessionStorage)保存,放到detail仓库里

      uuid是一个随机的字符串,且每次执行不能发生变化,且持久存储,

      所以每次调用getUUID函数的时候,先从本地存储获取uuid,看会话存储是否有,

      如果有的话就返回会话存储里面的uuid,

      如果没有的话,就生成uuid

    //      src/utils/uuid_token.js
    
    import {
       v4 as uuidv4} from 'uuid'
    // 要生成一个随机的字符串,且每次执行不能发生变化,游客身份持久存储
    export const getUUID = ()=>{
       
        // 先从会话存储获取uuid,看一下本地存储是否有
        let uuid_token = sessionStorage.getItem('UUIDTOKEN');
        // 如果没有,我就生成UUID
        if(!uuid_token){
       
            uuid_token=uuidv4();
            // 会话存储 存储一次
            sessionStorage.setItem('UUIDTOKEN',uuid_token);
        }
        // 切记要有返回值!
        return uuid_token;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在detail仓库里面存储uuid

    //     src/store/detail/index.js
    
    // 封装游客身份模块uuid---生成一个随机的字符串(不能再变了)
    import {
       getUUID} from '@/utils/uuid_token'
    const state = {
       
        goodsInfo: {
       }, // 看api文档,result.data返回的是一个对象
        // 游客临时身份
        uuid_token:getUUID(),
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    现在游客身份在仓库里,我们要把数据带给服务器,可以利用请求头把数据带给服务器

    找到请求拦截器,在请求拦截器捞到仓库里的数据

    //   src/api/request.js
    
    // 在当前模块引入store仓库
    import store from '@/store'
    .....
    // 请求拦截器:在发请求之前,请求拦截器可以检测到,可以在请求发出去之前做一些事情
    requests.interceptors.request.use((config) => {
       
        // config:配置对象,对象里面有一个属性很重要:headers请求头
        if (store.state.detail.uuid_token) {
       
            // 给请求头添加一个字段(userTempId):和后台老师商量好!
            config.headers.userTempId = store.state.detail.uuid_token
        }
    
        // 进度条开始动
        nprogress.start();
        return config;
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    在这里插入图片描述

    动态展示购物车

    修改购物车产品的数量

    在这里插入图片描述

    点击 + 或 - 或 修改input框里的数字,input框里发生变化

    :这个时候向服务器发请求吗?

    发请求,如果不发请求的话,服务器里的数据还是原来的,那么该页面的关于数量的数据和原来一样,

    -----------所以我们每当修改的时候,就要发请求给服务器,然后再从服务器捞到数据,进行渲染页面

    在这里插入图片描述

    这个之前写过api(在将产品添加到购物车那里,detail详情页,也有仓库了)所以我们可以把数据存到detail仓库,就现在直接派发action就行了,然后再重新捞数据渲染

    这里的skuNum是 现在状态的数字 与 起始状态的数字 的差值。比如:现在商品数量是5,我们要买12,这个skuNum是12-5 = 7

    1. 找到产品数量的结构位置

       <li class="cart-list-con5">
                  <a href="javascript:void(0)" class="mins">-a>
                  
                  <input
                    autocomplete="off"
                    type="text"
                    minnum="1"
                    class="itxt"
                    :value="cart.skuNum"
                  />
                  <a href="javascript:void(0)" class="plus">+a>
       li>
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7
      • 8
      • 9
      • 10
      • 11
      • 12

      这三个节点 要派发同一个action,也就是说这三个节点调用同一个回调函数

      :但是如何判断这三个节点?

      通过传参。三个不同的参数,用形参接收,来区分这三个节点

    2. 要传三个参数

      第一个参数type 是用来区分它们三个节点

      第二个参数是disNum,他们的变化量,+号是1,-号是-1,input框暂定不是变化量,是修改后的值

      第三个参数是cart 当前他们点击的产品的信息cart,然后得知他们的id,因为要发请求需要skuID

        <li class="cart-list-con5">
                  <a href="javascript:void(0)" class="mins" @click="handler('mins',-1,cart)">-a>
                  
                  <input
                    autocomplete="off"
                    type="text"
           
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
  • 相关阅读:
    C++新经典 | C++ 查漏补缺(概述)
    4k壁纸爬100页 python
    Web3设计风格和APP设计风格
    《恋上数据结构与算法》第1季:链表原理实现(图文并茂)
    Java——聊聊JUC中的Future和FutureTask
    Web入门
    Linux内存管理(十四):buddy 系统分配器之快速分配(2)
    【区分vue2和vue3下的element UI MessageBox 弹框组件,分别详细介绍属性,事件,方法如何使用,并举例】
    [go学习笔记.第十六章.TCP编程] 1.基本介绍以及入门案例
    面向智慧文博的知识图谱构建综述
  • 原文地址:https://blog.csdn.net/muziqwyk/article/details/126686479