Heim  >  Artikel  >  Web-Frontend  >  Detaillierte Erläuterung der Schritte zur Verwendung von Schnittstellen in JS

Detaillierte Erläuterung der Schritte zur Verwendung von Schnittstellen in JS

php中世界最好的语言
php中世界最好的语言Original
2018-05-24 13:38:107933Durchsuche

Dieses Mal erkläre ich Ihnen ausführlich die Schritte zur Verwendung von Schnittstellen in JS. Was sind die Vorsichtsmaßnahmen für die Verwendung von Schnittstellen in JS?

Dies ist die README-Datei von js-interface. Obwohl es keine sehr komplizierte Sache ist, werde ich die Quellcode-Ideen ORZ aufschreiben

Einführung

Wenn ich an einem Projekt mit separater Vorder- und Rückseite arbeite, habe ich beim Lesen des Buches „JavaScript Design Patterns“, Kapitel 2, einige Kopfschmerzen erwähnte, dass in Das Konzept der Simulation von Schnittstellen (Schnittstelle) in JavaScript die Verwendung vieler Entwurfsmuster erleichtert, daher habe ich versucht, eine Schnittstelle zu simulieren. Da ich ein Backend-Java-Entwickler bin, hoffe ich, Schnittstellenstandardimplementierung, Schnittstellenvererbung, zu dieser Simulationsschichtmethode hinzuzufügen Überladen von und anderen Funktionen, obwohl das Hinzufügen dieser Dinge unweigerlich die Leistung beeinträchtigen wird, kann es für mich einige Entwicklungserfahrungen verbessern (ich kenne TypeScript, wollte mir nur ein Rad zulegen und es ausprobieren: P).

Verwenden Sie

Da die ursprüngliche Absicht darin besteht, die Verwaltung von API zu erleichtern, erstellen Sie eine Demo über API.

Erstellen Sie eine Schnittstelle

const config = {
    // 接口的名字
    name: 'IApi', 
    // 是否打开此接口的 debug 开关
    // 开发时必须打开,否则不会启动 (方法声明、方法实现等)入参的类型检查。
    // 打开这个的情况下,还会获得一些调试用的信息。
    debug: true,          
}
let IApi = new Interface(config)

Deklarieren Sie eine Methode

Der einfachste Weg zum Deklarieren:

IApi.method({name: 'getName'})
// 等价于
IApi.method({name: 'getName', args: undefined})

Dies deklariert, dass die IApi-Schnittstelle eine Methode, sie hat keine Parameter und keine Standardimplementierung, was erfordert, dass jede nachfolgende getName-Subschnittstelle oder Implementierungsklasse diese Methode implementieren muss, andernfalls wird eine Ausnahme ausgelöst. IApi


Wenn Sie die Parameterliste einer Methode angeben möchten:

IApi.method({ name: 'getName', args: null })

Achtung!

Wenn es args ist, bedeutet dies, dass die Methode eine beliebige Anzahl von Parametern akzeptieren kann. Wenn eine Methode überladen ist (Einzelheiten finden Sie in der Beschreibung der Überladung später): null

// 声明一个空参方法
IApi.method({ id: 0, name: 'getName', args: null })
// 重载上面的方法,使其有且只有一个 'string' 类型,名为 name 的参数
IApi.method({ id: 1, name: 'getName', args: [
    {name: 'name', type: 'string', support: val => typeof val === 'string'}
] })

Achtung!

In der Parameterbeschreibung ist das

-Attribut type nur ein String-Wert, der nicht wirklich den tatsächlichen Typ des Parameters darstellt. Wie das Attribut stellt es nur Informationen zum Debuggen bereit, sodass Sie jeden Zeichenfolgenwert eingeben können, der Ihrer Meinung nach angemessen genug ist, um den Parameter mit einigen Informationen zu kennzeichnen. name

Was wirklich bestimmt, ob die Methode den Parameter akzeptiert, ist das

-Attribut. Wenn es support zurückgibt, wird der nächste Parameter überprüft, bis alle Parameter überprüft wurden oder ein Parameter an einer bestimmten Position nicht akzeptiert wird . true

Bei Bedarf können Sie eine spezielle Verarbeitung der tatsächlichen Eingabeparameter in

durchführen, z. B. das Konvertieren von Objekten, das Überprüfen bestimmter Attribute usw. support


Wenn Sie eine Standardimplementierung für eine Methode bereitstellen möchten:

IApi.method({ 
    name: 'getName', 
    // 默认实现,不能为箭头函数!
    implement: function() {
        return "IApi"   
    }
})

Gehen Sie zurück zu unserer Demo und nutzen Sie sie umfassend:

// 声明两个方法,它们都没有参数,也不需要重载因此这样就可以了
IApi
  .method({ name: 'getName'  })
  // 项目中使用 Axios,因此这里需要一个方法来获取 axios 实例
  .method({ name: 'getAxios' })
// 声明四个请求方式对应的方法
const methods = ['get', 'post', 'put', 'delete']
methods.forEach(method => {
  IApi.method({
    name: method,
    args: null,
    implement: function() {
      // 处理了 this 指向问题,放心用吧
      return this.getAxios()[method].apply(this, arguments)
        .then(responseHandler)
        .catch(errorHandler)
    }
  })
})
Geerbte Schnittstelle

Angenommen, wir möchten Schnittstelle A erstellen und die Schnittstellen B, C, D, E usw. erben, verwenden Sie die folgende Anweisung:

const A = new Interface({
    name: 'A',
    debug: true
}).extends([B, C, D, E])

Die Methode deklariert alle von gehaltenen Methoden Die eingehende Schnittstelle (d. h. die durch extends deklarierten Methoden) wird auf die Schnittstelle A kopiert, einschließlich der Standardimplementierung dieser Methodendeklarationen. Interface.method(config)

Achtung!

Im Allgemeinen wird dieselbe Methodensignatur nicht in mehreren Schnittstellen überschrieben, aber wenn Sie wirklich einen solchen Bedarf haben, können Sie Ihre eigenen

Regeln festlegen, wie zum Beispiel: id

const B = new Interface(...)
  .method({ id: 'B00', name: 'getName', args = [...] })
  .method({ id: 'B01', name: 'getName', args = [...] })
                
const C = new Interface(...)
  .method({ id: 'C00', name: 'getName', args = [...] })
Geben Sie dann an, welche Anweisung bei der Implementierung der Methode implementiert werden soll:

// 注意!如果一个方法被重载,则不能在 class 中声明该方法。
class AImpl { ... } 
const AInstance = new AImpl(...)
B.implement({
    object: AInstance,
    id: 'B00', // 指定要实现的方法声明
    name: 'getName'
})

Gehen Sie noch einmal zu unserer Demo zurück und nutzen Sie sie umfassend:

const IAuthenticationApi = new Interface({
  name: 'IAuthentication',
  debug: true
})
   // 指明 IAuthenticationApi 继承自 IApi 接口
   .extends(IApi)
IAuthenticationApi
  // 重载方法 login
  // loin (username :string, password :string)
  .method({
    id: 0,
    name: 'login',
    args: [
      {name: 'username', type: 'string', support: val => typeof val === 'string'},
      {name: 'password', type: 'string', support: val => typeof val === 'string'}
    ]
  })
  // login()
  .method({
    id: 1,
    name: 'login'
  })
Implementieren Sie die Schnittstelle

// 编写一个实现类
class AuthenticationApi {
  constructor(axios) { this.axios = axios }
  // 直接实现 getName 方法  
  getName() { return "AuthenticationApi" }
  // 直接实现 getAxios 方法
  getAxios() { return this.axios }
}
// 实现重载方法
IAuthenticationApi
  .implement({
    // 指定挂载实现到 AuthenticationApi 上
    object: AuthenticationApi,
    // 指定此实现是对应 id 为 0 的方法声明
    id: 0,
    name: 'login',
    implement: function(username, password) {
      console.log('带参数的 login')
      // 还记得我们在 IApi 接口中定义了 get 方法(包括默认实现)吗?
      this.get('https://www.baidu.com')
      return Promise.resolve('hello')
    }
  })
  .implement({
    object: AuthenticationApi,
    id: 1,
    name: 'login',
    implement: function () {
      console.log('无参数的 login')
    },
  })
IAuthenticationApi.ensureImplements(AuthenticationApi)

Verwenden Sie die Schnittstelle, um die Klasse zu implementieren

    let authenticationService = new AuthenticationApi(axios)
    // 挂载代理函数到实例上,否则会提示
    // Uncaught TypeError: authenticationService.login is not a function
    IAuthenticationApi.ensureImplements(authenticationService)
    authenticationService
        .login('sitdownload', '1498696873')
        // login(string, string) 会返回一个 Promise 还记得吗 :P
        .then(str => alert(`${str} world!`))
    authenticationService.login()

Über das Protokoll

Stellen Sie zunächst sicher, dass der Debug-Schalter beim Erstellen der Schnittstelle aktiviert ist (

). { debug: true }

Wenn die obige Demo normal läuft, erhalten Sie das folgende Protokoll:

// 注册方法
Interface 注册方法: IApi.getName()
Interface 注册方法: IApi.getAxios()
Interface 注册方法: IApi.get(any)
Interface 注册方法: IApi.post(any)
Interface 注册方法: IApi.put(any)
Interface 注册方法: IApi.delete(any)
Interface 注册方法: IAuthentication extends IApi.getName()
Interface 注册方法: IAuthentication extends IApi.getAxios()
Interface 注册方法: IAuthentication extends IApi.get(any)
Interface 注册方法: IAuthentication extends IApi.post(any)
Interface 注册方法: IAuthentication extends IApi.put(any)
Interface 注册方法: IAuthentication extends IApi.delete(any)
Interface 注册方法: [0]IAuthentication.login(username :string, password :string)
Interface 注册方法: [1]IAuthentication.login()
// 实现方法
Interface 实现方法: 保存 [0]IAuthentication.login(...) 实现:
ƒ implement(username, password)
Interface 实现方法: 保存 [1]IAuthentication.login(...) 实现:
ƒ implement()
// 匹配方法
Interface 方法匹配: 精准匹配
IAuthentication.login({ username: "sitdownload" } :string, { password: "1498696873" } :string).
// 在控制台这行是可以打开实现的具体位置的
ƒ implement(username, password)
// 方法输出
AuthenticationApi.js?7b55:25 带参数的 login
// 匹配方法
Interface 方法匹配: 无法精准匹配 IAuthentication.get("https://www.baidu.com"),使用 any 实现匹配:
ƒ implement()
Interface 方法匹配: 精准匹配 IAuthentication.login().
ƒ implement()
// 方法输出
AuthenticationApi.js?7b55:35 无参数的 login
// AuthenticationApi.login(username, password) 中请求了 'https://www.baidu.com'
Failed to load https://www.baidu.com/: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://127.0.0.1' is therefore not allowed access.
// IApi.get(any) 中将异常直接向下抛了
Uncaught (in promise) {type: "network", payload: Error: Network Error
    at createError (webpack-internal:///./node_modules/_axios@0.18.0@axios/lib/…}
Nachverfolgung

Wenn Sie die Version veröffentlichen möchten, nachdem Sie alle Schnittstellenmethoden bestätigt haben korrekt implementiert sind, können Sie das Debuggen deaktivieren, sodass in

keine Überprüfung der Eingabeparameter und keine Debugging-Ausgabe erfolgt. Interface

Ich glaube, dass Sie die Methode beherrschen, nachdem Sie den Fall in diesem Artikel gelesen haben. Weitere spannende Informationen finden Sie in anderen verwandten Artikeln auf der chinesischen PHP-Website!

Empfohlene Lektüre:

Analyse echter Front-End-Interviewfragen

Detaillierte Erläuterung der Schritte zur Kombination von React mit TypeScript und Mobx

Das obige ist der detaillierte Inhalt vonDetaillierte Erläuterung der Schritte zur Verwendung von Schnittstellen in JS. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Der Inhalt dieses Artikels wird freiwillig von Internetnutzern beigesteuert und das Urheberrecht liegt beim ursprünglichen Autor. Diese Website übernimmt keine entsprechende rechtliche Verantwortung. Wenn Sie Inhalte finden, bei denen der Verdacht eines Plagiats oder einer Rechtsverletzung besteht, wenden Sie sich bitte an admin@php.cn