es6學習筆記-proxy對象

来源:https://www.cnblogs.com/sqh17/archive/2019/04/27/10755165.html
-Advertisement-
Play Games

前提摘要 尤大大的vue3.0即將到來,雖然學不動了,但是還要學的啊,據說vue3.0是基於proxy來進行對值進行攔截並操作,所以es6的proxy也是要學習一下的。 一 什麼是proxy Proxy 對象用於定義基本操作的自定義行為(如屬性查找,賦值,枚舉,函數調用等) 摘自MDN Proxy ...


前提摘要

尤大大的vue3.0即將到來,雖然學不動了,但是還要學的啊,據說vue3.0是基於proxy來進行對值進行攔截並操作,所以es6的proxy也是要學習一下的。

一 什麼是proxy

Proxy 對象用於定義基本操作的自定義行為(如屬性查找,賦值,枚舉,函數調用等) --摘自MDN
Proxy 用於修改某些操作的預設行為,等同於在語言層面做出修改,所以屬於一種“元編程”(meta programming),即對編程語言進行編程。 --摘自阮一峰的ES6入門
Proxy 這個詞的原意是代理,用在這裡表示由它來“代理”某些操作,可以譯為“代理器”。
Proxy 也可以理解成,在目標對象之前架設一層“攔截”,外界對該對象的訪問,都必須先通過這層攔截,因此提供了一種機制,可以對外界的訪問進行過濾和改寫。
總結來說:Proxy對象就是要在目標對象上設置自定義的規則和方法,讓它按照自己定義的規則去實行某些操作。

二 Proxy聲明

ES6 原生提供 Proxy 構造函數,用來生成 Proxy 實例,所以可以按照構造函數創建對象的形式去實例化一個Proxy對象。

var proxy = new Proxy({},{})
console.log(proxy) // Proxy{}

註意點:
1 實例化一個Proxy對象時,必須要傳兩個參數對象,否則會報錯:Uncaught TypeError: Cannot create proxy with a non-object as target or handler,不能創建沒有對象的proxy對象。
2 傳兩個空對象時,預設的是簡單聲明瞭一個Proxy實例,(好像沒啥卵用……)

參數對象解釋:

  • 第一個參數:target,目標對象,是你要代理的對象.它可以是JavaScript中的任何合法對象.如: (數組, 對象, 函數等等)
    tip:

    var arr = []
    var obj = {}
    var Person = class{}
    var foo = function (){}
    console.log(Person instanceof Object) // true
    console.log(foo instanceof Object)  // true
    console.log(arr instanceof Object)  // true
    console.log(obj instanceof Object)  // true
  • 第二個參數:handler,配置對象,用來定製攔截行為,對於每一個被代理的操作,需要提供一個對應的處理函數,該函數將攔截對應的操作。
    Proxy支持的攔截操作,有13種,使用方法可以參考 阮一峰的ES6入門

三 常見情況

3.1 當目標對象為空時

var proxy = new Proxy({},handler)
這樣直接代表著,攔截的對象是空的,所以直接對proxy對象進行操控。

var target = {};
var handler = {
  get(target,propKey,receiver){
    return 'peter'
  }
};
var proxy = new Proxy(target, handler);
proxy.name = 'tom';
console.log(proxy.name) // tom
console.log(target.name) // undefined

上面的代碼說明瞭:target是個空對象,但是操作了proxy,也影響不了target
ps:要使得Proxy起作用,必須針對Proxy實例進行操作,而不是針對目標對象進行操作

3.2 當攔截對象為空時

var proxy = new Proxy(target,{})
handler沒有設置任何攔截,那就等同於直接通向原對象。

var target = {};
var handler = {};
var proxy = new Proxy(target, handler);
proxy.name = 'peter';
console.log(proxy.name) // peter
console.log(target.name) // peter

上面的代碼說明瞭:handler是一個空對象,沒有任何攔截效果,訪問proxy就等同於訪問target

四 方法解析

Proxy實例化的對象預設帶有get和set方法。也可以在這些基礎上進行攔截操作,其他的13種方法也是如此。

  1. get() 用於攔截某個屬性的讀取(read)操作,換句話講,就是在讀取目標對象的屬性之前,操作該屬性。
    參數解釋:
    • target:目標對象
    • property:屬性名
    • receiver:proxy實例
      例子:

      var person = {
        name: "張三"
      };
      
      var proxy = new Proxy(person, {
        get: function(target, property) {
          if (property in target) {
            return target[property];
          } else {
            throw new ReferenceError("Property \"" + property + "\" does not exist.");
          }
        }
      });
      
      proxy.name // "張三"
      proxy.age // Property "age" does not exist.

      參考阮一峰的例子,上述說明瞭,如果輸入目標函數不存在的屬性,就直接報錯。

  2. set() 用來攔截目標對象的賦值(write)操作
    參數解釋:
    • target:目標對象
    • propertyName:屬性名
    • propertyValue:屬性值
    • receiver:Proxy實例本身
      例子:

      var target = {}
      var handler = {
        set(target, propKey, value, receiver) {
          if (typeof value !== 'string') {
            target[propKey] = String(value);
          }else{
            target[propKey] = value;
          }
        }
      }
      var proxy = new Proxy(target, handler)
      proxy.name = 'peter'
      proxy.age = 25
      console.log(typeof proxy.name) // string
      console.log(typeof proxy.age) // string

      上面例子就是攔截對象是不是字元串,不是字元串的話會強制轉化為字元串。

  3. apply() 用來攔截函數的調用、call和apply操作
    參數解釋:
    • target:目標對象
    • context:目標對象的上下文對象(this)
    • arguments:目標對象的參數數組
      例子:

      var target = function(a,b){
        return 10 + a + b
      }
      var handler = {
        apply(target,context,arguments){
          arguments[0] = 10
          arguments[1] = 20
          return arguments.reduce(function(prev, curr, idx, arr){
              return prev + curr;
          });
        }
      }
      var proxy = new Proxy(target,handler)
      console.log(proxy(1,2)) // 30

      上面的例子,就是目標函數是要傳兩個參數,並且返回之和,攔截目標做的就是改變目標對象的參數,並且求和,所以這樣寫觸發了apply方法,返回30,而不是13

  4. has() 用來攔截hasProperty操作,即判斷對象是否具有某個屬性時,這個方法會生效。典型的操作就是in運算符。
    參數解釋:
    • target:目標對象
    • key: 需查詢的屬性名,是一個字元串!!!!!
      例子:

      var target = {
        name: 'peter',
        age:25
      }
      var handler = {
        has(target,key){
          return key in target;
        }
      
      }
      var proxy = new Proxy(target,handler)
      console.log('age' in proxy) // true
      console.log('colors' in proxy) // false

      上面的例子是典型的has的方法,判斷所要查詢的屬性名是不是在目標對象上的屬性名,返回布爾值。
      ps:has攔截對for...in迴圈不生效。

  5. construct() 用於攔截new命令,要返回是一個對象,否則會報錯
    參數解釋:
    • target:目標對象
    • args:構造函數的參數對象
    • newTarget:創造實例對象時,new命令作用的構造函數
      例子:

      var p = new Proxy(function () {}, {
        construct: function(target, args) {
          console.log('called: ' + args.join(', '));
          return { value: args[0] * 10 };
        }
      });
      
      (new p(1)).value
      // "called: 1"
      // 10

      由此可見,是針對構造函數而言的,對目標對象的構造函數進行攔截。

  6. defineProperty() 攔截了Object.defineProperty操作,在聲明時進行攔截,設置的是一個布爾值
    • 參數解釋:
      • target:目標對象
      • key:要定義或修改的屬性的名稱
      • descriptor: 將被定義或修改的屬性描述符,是一個對象
    • 拓展:
      Object.defineProperty(),聲明對象的屬性,參數說明和上述一樣
      例子:

      var obj = {}
      Object.defineProperty(obj, "key", {
        enumerable: false,
        configurable: false,
        writable: false,
        value: "static"
      });
    • 例子:

      var target = {
        name: 'peter',
        age:25
      }
      var handler = {
        defineProperty(target,key,descriptor){
          if(key === 'color'){
            throw new Error('不能定義顏色')
          }
          Object.defineProperty(target, key, descriptor)
          // return true
        }
      }
      var proxy = new Proxy(target,handler)
      var descriptor = {
        writable : true,
        enumerable : true,
        configurable : true
      }
      descriptor.value = 'sport'
      Object.defineProperty(proxy, 'favor', descriptor)
      console.log(proxy.favor) // sport
      descriptor.value = 'red'
      Object.defineProperty(proxy, 'color', descriptor)  // 不能定義顏色
      console.log(proxy.color)

      如果目標對象不可擴展(non-extensible),則defineProperty不能增加目標對象上不存在的屬性,否則會報錯。另外,如果目標對象的某個屬性不可寫(writable)或不可配置(configurable),則defineProperty方法不得改變這兩個設置。

  7. deleteProperty() 用於攔截delete操作,如果這個方法拋出錯誤或者返回false,當前屬性就無法被delete命令刪除。
    • 參數解釋:
      • target:目標對象
      • key:要刪除的屬性名
        (delete是關鍵字,目前用到的就是刪除對象的某個屬性)
    • 例子:

      var target = { _prop: 'foo' };
      var handler = {
        deleteProperty (target, key) {
          if (key[0] === '_') {
            throw new Error(`Invalid attempt to ${target} private "${key}" property`);
          }
          delete target[key];
          return true;
        }
      };
      var proxy = new Proxy(target, handler);
      delete proxy._prop // Error: Invalid attempt to delete private "_prop" property

      上面代碼中,deleteProperty方法攔截了delete操作符,刪除第一個字元為下劃線的屬性會報錯。
      註意,目標對象自身的不可配置(configurable)的屬性,不能被deleteProperty方法刪除,否則報錯。

  8. getOwnPropertyDescriptor() 攔截Object.getOwnPropertyDescriptor(),返回一個屬性描述對象或者undefined。
    • 參數解釋:
      • target:目標對象
      • key: 屬性名
    • 拓展:
      Object.getOwnPropertyDescriptor(obj,prop) 返回指定對象上一個自有屬性對應的屬性描述符
      • 參數解釋:
        • obj:需要查找的目標對象
        • prop: 目標對象內屬性名稱
      • 返回值:
        如果指定的屬性存在於對象上,則返回其屬性描述符對象(property descriptor),否則返回 undefined。
      • 例子:

        o = { bar: 42 };
        d = Object.getOwnPropertyDescriptor(o, "bar");
        console.log(d)
        // d {
        //   configurable: true,
        //   enumerable: true,
        //   value: 42,
        //   writable: true
        // }
    • 例子:

      var target = { _foo: 'bar', baz: 'tar' };
      var handler = {
        getOwnPropertyDescriptor (target, key) {
          if (key[0] === '_') {
            return;
          }
          return Object.getOwnPropertyDescriptor(target, key);
        }
      };
      var proxy = new Proxy(target, handler);
      Object.getOwnPropertyDescriptor(proxy, 'wat')
      // undefined
      Object.getOwnPropertyDescriptor(proxy, '_foo')
      // undefined
      Object.getOwnPropertyDescriptor(proxy, 'baz')
      // { value: 'tar', writable: true, enumerable: true, configurable: true }

      上述說明:對於第一個字元為下劃線的屬性名會返回undefined。

  9. getPrototypeOf() 用來攔截獲取對象原型,主要攔截以下操作:
    • 如下:
      • Object.prototype.__proto__
        -- 該特性已經從 Web 標準中刪除
      • Object.prototype.isPrototypeOf()
        用於測試一個對象是否存在於另一個對象的原型鏈上。
        • 參數:
          • object 在該對象的原型鏈上搜尋
        • 返回值:
          • 返回值 表示調用對象是否在另一個對象的原型鏈上。布爾值
        • 例子:

          function Baz() {}
          var baz = new Baz();
          console.log(Baz.prototype.isPrototypeOf(baz)); // true
      • Object.getPrototypeOf(obj) 返回指定對象的原型(內部[[Prototype]]屬性的值)
        • 參數:
          • obj 返回其原型的對象
        • 返回值:
          給定對象的原型。如果沒有繼承屬性,則返回 null 。
        • 例子:

          var proto = {};
          var obj = Object.create(proto);
          Object.getPrototypeOf(obj) === proto; // true
      • Reflect.getPrototypeOf()
      • instanceof
    • 例子:

      var proto = {};
      var p = new Proxy({}, {
        getPrototypeOf(target) {
          return proto;
        }
      });
      Object.getPrototypeOf(p) === proto // true
      上面代碼中,getPrototypeOf方法攔截Object.getPrototypeOf(),返回proto對象。
      ps:
      1. getPrototypeOf方法的返回值必須是對象或者null,否則報錯
      2. 如果目標對象不可擴展(non-extensible), getPrototypeOf方法必須返回目標對象的原型對象。
  10. isExtensible() 攔截Object.isExtensible()操作
    • Object.isExtensible() 判斷是否可以為對象添加新的屬性
      參數:
      • object 要進行判斷的對象
        返回值:
      • 是個布爾值,true是可以添加,false不可以添加
        例子:

        let obj = { 
          name: 'peter',
          age:25
        }
        console.log(Object.isExtensible(obj)) // true
      對象預設情況下是可以添加新的屬性的。
    • 例子:

      var p = new Proxy({}, {
        isExtensible: function(target) {
          console.log("called");
          return true;
        }
      });
      Object.isExtensible(p) // called

      這個方法有一個強限制,它的返回值必須與目標對象的isExtensible屬性保持一致,否則就會拋出錯誤。
      即:Object.isExtensible(proxy) === Object.isExtensible(target)

  11. preventExtensions() 攔截Object.preventExtensions()操作
    • Object.preventExtensions(object) 不能再為此對象添加新的屬性或者方法
      • 參數:object,要成為不可擴展的對象的對象
      • 無返回值
      • 例子

        let obj = { 
          name: 'peter',
          age:25
        } 
        Object.preventExtensions(obj)
        obj.color = 'red' // object is not extensible
    • 例子
      ————————————
  12. setPrototypeOf() 攔截Object.setPrototypeOf方法
    • Object.setPrototypeOf(obj,proto) 設置對象的原型
      此方法修改的是對象實例的內部屬性[[Prototype]],也就是__proto__屬性所指向的對象,它只是修改了特定對象上的原型對象,對於構造函數的prototype指向的原型對象沒有影響
      • 參數:
        • obj 對其設置原型的對象
        • proto 新的原型對象
      • 例子:

        let proto = {
        color: red
        };
        let obj = {
        name: 'peter'
        age: 26
        };
        Object.setPrototypeOf(obj, proto);
        console.log(obj.color); // red
    • 例子

      var handler = {
        setPrototypeOf (target, proto) {
          throw new Error('Changing the prototype is forbidden');
        }
      };
      var proto = {};
      var target = function () {};
      var proxy = new Proxy(target, handler);
      Object.setPrototypeOf(proxy, proto);
      // Error: Changing the prototype is forbidden
      上面代碼中,只要修改target的原型對象,就會報錯。
    • ps
      1. 該方法只能返回布爾值,否則會被自動轉為布爾值
      2. 如果目標對象不可擴展(non-extensible),setPrototypeOf方法不得改變目標對象的原型
  13. ownKeys() 用來攔截對象自身屬性的讀取操作
    • 如下:
      • Object.getOwnPropertyNames(obj) 獲取對象的屬性名稱,並存儲在數組中。
        • 參數解釋: obj 要獲取屬性名稱的對象
        • 返回值:存放屬性名稱的數組
        • 只能拿到對象的自有屬性,拿不到原型上的屬性,另外,defineProperty的值也可以拿到
        • 例子:

          function Person(){
            this.name = 'peter'
            this.age = 26
          }
          Person.prototype={
            address:"北京"
          }
          let peter=new Person();
          console.log(Object.getOwnPropertyNames(peter)); // ['name','age']
      • Object.getOwnPropertySymbols(obj) 返回一個給定對象自身的所有 Symbol 屬性的數組
        • 參數解釋: obj 要返回 Symbol 屬性的對象
        • 返回值: 在給定對象自身上找到的所有 Symbol 屬性的數組。
        • 例子:

          var obj = {};
          var a = Symbol("a");
          var b = Symbol.for("b");
          
          obj[a] = "localSymbol";
          obj[b] = "globalSymbol";
          
          var objectSymbols = Object.getOwnPropertySymbols(obj);
          
          console.log(objectSymbols.length); // 2
          console.log(objectSymbols)         // [Symbol(a), Symbol(b)]
          console.log(objectSymbols[0])      // Symbol(a)
      • Object.keys() 返回一個由一個給定對象的自身可枚舉屬性組成的數組,數組中屬性名的排列順序和使用 for...in 迴圈遍歷該對象時返回的順序一致
        • 參數:obj 要返回其枚舉自身屬性的對象
        • 返回值: 一個表示給定對象的所有可枚舉屬性的字元串數組
        • 例子:

          var obj = { 0: 'a', 1: 'b', 2: 'c' };
          console.log(Object.keys(obj)); // ['0', '1', '2']
      • for...in迴圈
        ————————————
    • 例子之一:

      var p = new Proxy({}, {
        ownKeys: function(target) {
          return ['a', 'b', 'c'];
        }
      });
      
      Object.getOwnPropertyNames(p)
      // [ 'a', 'b', 'c' ]

五 Proxy.revocable(target, handler)

返回一個可取消的 Proxy 實例

  • 參數解釋:
    • target 用Proxy包裝的目標對象(可以是任何類型的對象,包括原生數組,函數,甚至另一個代理)。
    • handler 攔截對象,其屬性是當執行一個操作時定義代理的行為的函數。
  • 返回值
    返回一個包含了所生成的代理對象本身以及該代理對象的撤銷方法的對象
    其結構為: {"proxy": proxy, "revoke": revoke},其中:
    • proxy
      表示新生成的代理對象本身,和用一般方式 new Proxy(target, handler) 創建的代理對象沒什麼不同,只是它可以被撤銷掉
    • revoke
      撤銷方法,調用的時候不需要加任何參數,就可以撤銷掉和它一起生成的那個代理對象
  • 例子:

    var revocable = Proxy.revocable({}, {
      get(target, propKey) {
        return propKey + '啦啦啦';
      }
    });
    var proxy = revocable.proxy;
    console.log(proxy.foo) // foo啦啦啦
    revocable.revoke(); // 執行撤銷方法
    console.log(proxy.foo); // Uncaught TypeError: Cannot perform 'get' on a proxy that has been revoked

總結

剛開始學proxy時,都是懵逼的狀態,阮一峰ES6入門一開始看代碼有點難度,所以我一邊看一邊查資料,裡面關於Object對象的方法居多,也順便學習了一下,知識很多,需要日常回顧加深理解,經過查閱,對於代理模式 Proxy 的作用主要體現在三個方面:1攔截和監視外部對對象的訪問,2降低函數或類的複雜度,3在複雜操作前對操作進行校驗或對所需資源進行管理,目前還沒有大量運用,最常見的應該是攔截和監聽對象的變化吧。
我把筆記放到GitHub里了,如需要可以去看看,有什麼不對的地方,歡迎指正,大家一起進步加油。

參考文獻

阮一峰ES6入門
詳解ES6中的代理模式——Proxy
MDN
[譯] 實例解析 ES6 Proxy 使用場景


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 原理: MySQL主從複製涉及到三個線程,一個運行在主節點(log dump thread),其餘兩個(I/O thread, SQL thread)運行在從節點,如下圖所示: l 主節點 binary log dump 線程 當從節點連接主節點時,主節點會創建一個log dump 線程,用於發送b ...
  • 首先百度搜索阿裡雲 如果是學生可以學生認證 然後註冊賬號->個人認證->學生認證 然後你會發現 伺服器一年只要114,114你買不了上當,買不了吃虧,買下麵的ECS伺服器,系統可以選擇window也可以選擇linux,編者用的centos7。 當然輕量級的應用伺服器也是可以的,這些輕量級伺服器會預裝 ...
  • Mysql子查詢 概念分析: 根據相關性分: (1)不相關子查詢:一條Sql語句中含有多條SELECT語句,先執行子查詢,再執行外查詢,子查詢可對立運行 關鍵字:(1)先子查詢,再外查詢 (2)可以對立運行,即可以單獨運行子查詢,對外查詢不幹擾 (2)相關子查詢:子查詢不能獨立運行,並且先運行外查詢 ...
  • 初學者都會接觸到三種表:emp、dept、salgrade表,進行練習各種語句操作再合適不過 但是,網上大多數的操作語句都是用oracle進行操作的,小編在學習mysql的時候,參考網上的書寫遇到了不少問題 都是由於oracle語句和mysql語句的不相容的引起的。 寫多行sql語句的時候或者嵌套查 ...
  • 第一題 代碼生成表格如: 根據以上代碼生成的表寫出一條查詢語句,查詢結果如下: 第二題 第三題 第四題(這道題難度相對較高) ...
  • 版權聲明:本文為HaiyuKing原創文章,轉載請註明出處! 前言 使用Poi實現android中根據模板文件生成Word文檔的功能。這裡的模板文件是doc文件。如果模板文件是docx文件的話,請閱讀下一篇文章《PoiDocxDemo【Android將表單數據生成Word文檔的方案之二(基於Poi4 ...
  • 前言 最近利用業餘時間閱讀了鬍子大哈寫的《React小書》,從基本的原理講解了React,Redux等等受益頗豐。眼過千遍不如手寫一遍,跟著作者的思路以及參考代碼可以實現基本的Demo,下麵根據自己的理解和參考一些資料,用原生JS從零開始實現一個Redux架構。 一.Redux基本概念 經常用Rea ...
  • 概述:本文描述TypeScript環境搭建,以及基於VSCode的自動編譯設置和調試設置。網路上很多相應文章的方式過時了或者無法試驗成功。 TypeScript簡介:由微軟開發的開源免費的編程語言,是JavaScript語言的一個超集,本質上為JavaScript語言添加了可選的靜態類型和基於類的面 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...