method_missingのjavascriptのメタプログラミング
入門
この技術を書くために、今日のヒントでも多くを言うためにRubyのメタプログラミングは、ルビーのインスピレーションから来ています。
Rubyでこのメソッドを呼び出すために転送されない場合はmethod_missingオブジェクトは、このメソッドを呼び出します。
JavaScriptでこの機能を達成するためにどのように、今のプロキシが、この考え方があります。
実現
class Base {
constructor () {
return new Proxy(this, {
get (target, property) {
if (Reflect.has(target, property)) {
return Reflect.get(target, property)
} else {
return function () {
if (target.method_missing) {
return target.method_missing(property, ...arguments)
} else {
throw new ReferenceError('Property "' + property + '" does not exist.')
}
}
}
}
})
}
}
クラス、プロキシ機能を、説明するためのコード。
どのようにそれを使用するには?
あなたがそれを行うだろう通常の環境で使用したい場合、私はどのように、単一のページのフロントエンドで、AJAXインターフェースがたくさんあり、シナリオの話を?
する最初のネットワークライブラリ(jqueryの、axios)シール層、HTTP、及び要求に、サブ層のリクエストには、各界面層のための最終的な閉鎖は、この方法は、メソッド呼び出しとなり、にフォルダ管理APIは、その後、別の場所で参照します。
もちろん、これは動作することができます。問題は、あまりにも冗長インターフェイス情報は、3ヶ所、URL、パラメータ、メソッド名、変更をすることがあれば、それは3ヶ所かもしれにおけるインタフェース情報を変更しなければならないということです。
そして、各ジョブ機能のために再びそれをしなければならないします。
例としては、以下のとおりです。
// http 方法
import $ from 'jquery'
window.jQuery = $
$.ajaxSetup({
cache: false,
dataType: 'json'
})
// request 方法
export function request (url, setting) {
return new Promise((resolve, reject) => {
$.ajax(url, setting)
.then(resolve)
.fail(reject)
})
}
export function get (url, params) {
return request(url, {
method: 'GET',
data: params
})
}
export function post (url, params) {
return request(url, {
method: 'POST',
data: params
})
}
// 具体的方法
import { post } from '@/lib/http'
export function getPermission (params = {}) {
return post('/passport/permission', params)
}
私たちは、意味を表現し、実際に具体的な方法は、関数名とURLを参照してください、私はそれをしなければならない場合は、再度のインタフェースすることができます。
重複したコードです20の以上のインタフェース、場合、それを行うべきではありません。
実現
方法は?
再生するにはmethod_missingメソッドの上に書かれた、と私たちは、直接書き込み機能を方法を封印して、統一されたメソッド呼び出しをmethod_missing委託し、私たちは、シール方法、他のドライ何かから解放繰り返すことはできません。
import Base from './base'
import { request } from './http'
import * as _ from 'lodash'
let METHOD = {
GET: ['get', 'show'],
POST: ['post', 'update', 'change', 'create', 'delete', 'remove']
}
class ApiService extends Base {
constructor () {
super()
this.baseURL = '/api/web'
}
method_missing (property, ...args) {
let [url, setting] = args
if (_.isObject(url)) {
setting = {
data: url
}
// 这里通过方法名生成 url
const url_parts = property.split('_')
const method = url_parts[0].toLowerCase()
if (METHOD.GET.includes(method)) {
setting.method = 'GET'
url_parts.shift()
} else if (METHOD.POST.includes(method)) {
setting.method = 'POST'
url_parts.shift()
} else {
setting.method = 'GET'
}
url = '/' + url_parts.join('/')
}
return request(this.baseURL + url, setting)
}
}
export default new ApiService()
// 执行代码
import apiService from './api-service'
// 调用,神奇的代码
apiService.get_passport_permission({
})
ビューのコード実行の点から、私はmethod_missingの回でapiserverを落ちるこのメソッドを、定義されていません。
その後、パラメータを追加し、あなたがリクエストを送信することができ、生成されたURLに記載の方法の名前で、私は物事が可能であった、メソッド名とパラメータリストを取得します。
結論
コードのインターフェイス上のこのメソッドは、あなたがしている場合は特に、あなたは定型コードを大幅に節約することができますが、method_missingクラスを達成するために追加することができ、コードの特殊なケースがある場合は、より良い、より一般的なコードです。
このような共通のコードとアカウントに特殊なケースを取るためのコードは、もちろん、互換性が考慮されることはまだあります。