Maison  >  Article  >  interface Web  >  Explication détaillée des étapes d'utilisation des interfaces en JS

Explication détaillée des étapes d'utilisation des interfaces en JS

php中世界最好的语言
php中世界最好的语言original
2018-05-24 13:38:107932parcourir

Cette fois je vais vous donner une explication détaillée des étapes d'utilisation des interfaces en JS Quelles sont les précautions pour utiliser les interfaces en JS Voici des cas pratiques, jetons un coup d'œil.

Voici le README de js-interface Bien que ce ne soit pas une chose très compliquée, si quelqu'un peut le lire, j'écrirai les idées du code source ORZ

Introduction

<.>Dans Lorsque je travaille sur un projet avec un recto et un verso séparés, j'ai des maux de tête sur la façon de gérer des choses comme les API En lisant le livre "

JavaScript Design Patterns", chapitre 2. mentionné que dans Le concept de simulation d'interfaces (interface) en JavaScript facilite l'utilisation de nombreux modèles de conception, j'ai donc essayé de simuler une interface. Puisque je suis un développeur back-end Java, j'espère ajouter Implémentation par défaut de l'interface, Héritage de l'interface, à cette couche de simulation Méthode la surcharge et d'autres fonctionnalités, bien que l'ajout de ces éléments sacrifiera inévitablement les performances, pour moi, cela peut améliorer une certaine expérience de développement (je connais TypeScript, je voulais juste me procurer une roue et l'essayer : P).

Utiliser

Puisque l'intention initiale est de faciliter la gestion d'Api, alors faites une démo sur Api.

Créer une interface

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

La manière la plus simple de déclarer :

IApi.method({name: 'getName'})
// 等价于
IApi.method({name: 'getName', args: undefined})
De cette façon, l'

interface contient Une méthode IApi n'a aucun paramètre ni aucune implémentation par défaut, ce qui nécessite que toute sous-interface getName ou classe d'implémentation ultérieure implémente cette méthode, sinon une exception sera levée. IApi


Si vous souhaitez préciser la liste des paramètres d'une méthode :

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

Attention !

Lorsqu'il est args, cela signifie que la méthode peut accepter n'importe quel nombre de paramètres si une méthode est surchargée (pour plus de détails, veuillez vous référer à la description de la surcharge plus tard) : 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'}
] })

Attention !

Dans la description du paramètre, l'attribut

type est juste une valeur chaîne, qui ne représente pas vraiment le type réel du paramètre. Comme l'attribut , il fournit uniquement des informations pour le débogage, vous pouvez donc remplir n'importe quelle valeur de chaîne que vous jugez suffisamment appropriée pour marquer le paramètre avec des informations. name

Ce qui détermine réellement si la méthode accepte le paramètre est l'attribut

. Lorsqu'il renvoie support, le paramètre suivant sera vérifié jusqu'à ce que tous les paramètres soient vérifiés ou qu'un paramètre à une certaine position ne soit pas accepté. . true

Si nécessaire, vous pouvez effectuer un traitement spécial sur les paramètres d'entrée réels dans

, comme la conversion d'objets, la vérification d'attributs spécifiques, etc. support


Si vous souhaitez fournir une implémentation par défaut pour une méthode :

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

Retournez à notre démo et utilisez-la de manière exhaustive :

// 声明两个方法,它们都没有参数,也不需要重载因此这样就可以了
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)
    }
  })
})
Hériter de l'interface

Supposons que nous voulions créer l'interface A et hériter des interfaces B, C, D, E, etc., utilisez l'instruction suivante :

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

Le La méthode passera dans l'interface détenue par Toutes les déclarations de méthode (c'est-à-dire celles déclarées via extends) sont copiées dans l'interface A, y compris l'implémentation par défaut de ces déclarations de méthode. Interface.method(config)

Attention !

De manière générale, la même signature de méthode ne sera pas remplacée dans plusieurs interfaces, mais si vous en avez vraiment besoin, vous pouvez définir vos propres

règles, telles que : 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 = [...] })
Spécifiez ensuite quelle instruction implémenter lors de l'implémentation de la méthode :

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

Retournez à notre démo et utilisez-la de manière exhaustive :

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'
  })
Implémentez la interface

// 编写一个实现类
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)
Utilisez l'interface pour implémenter la classe

    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()
À propos du journal

Assurez-vous d'abord que le commutateur de débogage (

) est activé lorsque création de l'interface. { debug: true }

Si la démo ci-dessus fonctionne normalement, vous obtiendrez le journal suivant :

// 注册方法
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/…}
Suivi

Si vous souhaitez publier la version, confirmez que toutes les interfaces les méthodes sont implémentées correctement. Après cela, vous pouvez désactiver le débogage, de sorte qu'il n'y ait pas de vérification des paramètres d'entrée ni de sortie de débogage à l'intérieur de

. Interface

Je pense que vous maîtrisez la méthode après avoir lu le cas dans cet article. Pour des informations plus intéressantes, veuillez prêter attention aux autres articles connexes sur le site Web chinois de php !

Lecture recommandée :

Analyse de véritables questions d'entretien front-end

Explication détaillée des étapes de combinaison de React avec TypeScript et Mobx

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn