JavaScript’te Dekoratörler – JSManifest

JavaScript'te Dekoratörler – JSManifest

Web geliştirmede JavaScript, özellikle iş gereksinimlerinden kaynaklanan çeşitli ihtiyaçlardan kaynaklanabilecek oldukça karmaşık kullanıcı arayüzleri oluşturmak için en çok önerilen dil olarak kabul edilir. Ve bu makalede, JavaScript’te denilen yararlı bir kalıbın üzerinden geçeceğiz. dekoratörler.

Dekoratörler, kullanabileceğiniz nesnelerdir. dinamik olarak başka bir nesneye ek işlevsellik eklemek, o nesnenin uygulamasını değiştirmek zorunda kalmadan. Sadece bu tanımı anlayarak, büyük olasılıkla uygulama kodumuz için yararlı olabilecekleri konusunda bir anlaşmaya varabiliriz.

Benim gibiyseniz, özellikle TypeScript’te sözdizimi olağandışı olduğu için başta biraz kafa karıştırıcı olabilir. pek değil hissetmek JavaScript’in sınıflara dekoratörleri modern sözdizimini kullanarak uygularken uygulaması gibi (Şu anda TypeScript ve babel eklentilerinde desteklenmektedir).

İşte kullanımda olan bir örnek:

@filterMales 
class MyClass {
  constructor(children) {
    this.children = children
  }
}

Bu tür bir kodu hiç görmemiş olanlarınız (özellikle @filterMales sözdizimi), bunun bir dekoratör uyguladığını fark ettiğinde dekoratörlerden biraz korkmuş hissedebilir. Bu şekilde dekoratörler sadece sözdizimi şekeridir. Bir dekoratörü anlamak ve uygulamak, düşündüğünden daha kolay. JavaScript’te bir süredir geliştirme yapıyorsanız, muhtemelen farkına bile varmadan bir dekoratör uygulamışsınızdır. Basit ama güçlüler.

JavaScript’teki bazı dekoratör örneklerine göz atacağız ve kodumuz için nasıl yararlı olabileceğini görmek için kendi dekoratörümüzü oluşturacağız.

Bir Dekoratör kullanmak için iyi bir zaman ne zaman?

Neyse ki, bir dekoratörün bizim için yararlı olabileceği birçok yol var.

Mevcut Nesnelere Dinamik Davranış Ekleme

Daha önce de belirtildiği gibi, çok yararlı olabilecek bir senaryo, dinamik olarak bazı alternatiflerle (alt sınıflama veya kalıtım gibi) uğraşmak zorunda kalmadan nesnelere ek mantık ekleyin.

Bunu unutmayın: dekoratörler malzeme enjekte etmek dış dünya bile bilmeden nesnelere nasıl yapacaklar.

Örneğin, diyelim ki bir Frog adlı bir yöntemi uygulayacak sınıf lick. Kurbağaların dişleri vardır, bu yüzden biz de rastgele bir getTeeths sahip oldukları diş miktarını iade etme yöntemi.

İşte böyle görünebilir:

function Frog(name) {
  this.name = name
}

Frog.prototype.getTeeths = function() {
  return 2
}

Frog.prototype.lick = function(target) {
  console.log(`I'm going lick you, ${target.name}. You better taste delicious`)
}



class Frog {
  constructor(name) {
    this.name = name
  }

  getTeeths() {
    return 2
  }

  lick(target) {
    console.log(
      `I'm going lick you, ${target.name}. You better taste delicious`,
    )
  }
}

Gerçekte farklı kurbağalar vardır, tıpkı bir karakurbağası örneğin. Bir kurbağa hala bir kurbağa ancak bir kurbağa olumsuzluk orada olduğu anlamına gelen bir kurbağa zorunlu aralarında bazı ayırt edici özellikler olmak zorunlu karıştırılmamalıdır.

Kurbağa bir kurbağa olduğundan, bir withToad Kurbağaları temsil edebilmesi için istenirse bir kurbağa örneğini süsleyecek dekoratör.

Unutmayın, bir dekoratör yalnızca bir şeyi genişletmeli veya ek davranış eklemelidir, ancak olumsuzluk uygulamasını değiştir.

Bunu bilerek, withToad dekoratör aslında oldukça basittir:

function withToad(frog) {
  frog.getTeeths = function() {
    return 0
  }
}

const mikeTheFrog = new Frog('mike')
withToad(mikeTheFrog)

console.log(mikeTheFrog.getTeeths())

dekoratörümüz withToad yeniden uygular getTeeths böylece geri döner 0 çünkü kurbağalar diş yok. Bu dekoratörü kullandığımızda, aslında bir kurbağayı, kurbağa olan bir kurbağayı temsil etmek için sessizce dekore ediyoruz (bu durumda dönüştürüyoruz).

Sen Yapabilmek aşağıda gösterildiği gibi kalıtımla alt sınıflamayı kullanarak aynı hedefe ulaşın:

function Toad(name) {
  Frog.call(this, name)

  this.getTeeths = function() {
    return 0
  }
}

const kellyTheToad = new Toad('kelly')



class Toad extends Frog {
  getTeeths() {
    return 0
  }
}

const kellyTheToad = new Toad('kelly')

İki yaklaşım arasındaki fark, dekoratörleri kullanarak kurbağalar için sınıflar oluşturmanıza gerek kalmamasıdır.

Örneklerimiz, bir kurbağanın özellikleriyle daha uyumlu olması için bir kurbağayı manipüle etmek için dekoratörlerin nasıl kullanıldığını gösterdi.

Şimdi, işlevselliği genişletmek için dekoratörleri nasıl kullanabileceğimize dair daha iyi bir örneğe bakalım. İşlerin biraz ilginçleşmeye başladığı yer burasıdır.

Kullanıcıların kontrol panellerini şekillendirmeleri için önceden tanımlanmış çeşitli özel temaları destekleyen bir uygulama oluşturduğumuzu düşünelim. bir uygulayacağız Theme yöntem ile createStylesheet çalışmak üzere uyumlu bir stil sayfası oluşturmak için applyStyles bu stil sayfasını ayrıştırma ve DOM’a uygulama yöntemi, kendisinin arama yapmasına izin verir. applyStyle bunları DOM’a uygulamak için:

function Theme() {}

Theme.prototype.createStylesheet = function() {
  return {
    header: {
      color: '#333',
      fontStyle: 'italic',
      fontFamily: 'Roboto, sans-serif',
    },
    background: {
      backgroundColor: '#fff',
    },
    button: {
      backgroundColor: '#fff',
      color: '#333',
    },
    color: '#fff',
  }
}

Theme.prototype.applyStylesheet = function(stylesheet) {
  const bodyElem = document.querySelector('body')
  const headerElem = document.getElementById('header')
  const buttonElems = document.querySelectorAll('button')
  this.applyStyles(bodyElem, stylesheet.background)
  this.applyStyles(headerElem, stylesheet.header)
  buttonElems.forEach((buttonElem) => {
    this.applyStyles(buttonElem, stylesheet.button)
  })
}

Theme.prototype.applyStyles = function(elem, styles) {
  for (let key in styles) {
    if (styles.hasOwnProperty(key)) {
      elem.style[key] = styles[key]
    }
  }
}

İşler harika görünüyor. Şimdi tanımladık Theme API ve şimdi şöyle bir stil sayfası oluşturabiliriz:

const theme = new Theme()
const stylesheet = theme.createStylesheet()

İşte ne stylesheet şu anda benziyor:

{
  "header": {
    "color": "#333",
    "fontStyle": "italic",
    "fontFamily": "Roboto, sans-serif"
  },
  "background": { "backgroundColor": "#fff" },
  "button": { "backgroundColor": "#fff", "color": "#333" },
  "color": "#fff"
}

Ve şimdi böyle kullanabiliriz, bu da web sayfamızı buna göre süsleyecektir:

theme.applyStylesheet(stylesheet)

Bunu akılda tutarak devam edin: Eklenti Geliştirmeyi Desteklemek için Açık Fırsatlar Sağlama

nasıl yaparız theme ararken bize özel bir tema gönderin createStylesheet varsayılan ile çalışmak yerine genişletmek için birlikte çalışabileceğimiz?

Burası, dekoratörlerin işe yarayabilecekleri yer, çünkü bize çalışmak için önceden tanımlanmış farklı bir varsayılan temayı geri getirmemize izin verecek.

uygulamamıza yardımcı olacak bir dekoratör yaratacağız. blood süsleyecek tema Theme böylece bize aşağıdakileri temsil edecek varsayılan bir stil sayfası oluşturur. blood orijinal yerine tema.

Bu dekoratörü arayacağız bloodTheme:

function bloodTheme(originalTheme) {
  const originalStylesheet = originalTheme.createStylesheet()
  originalTheme.createStylesheet = function() {
    return {
      name: 'blood',
      ...originalStylesheet,
      header: {
        ...originalStylesheet.header,
        color: '#fff',
        fontStyle: 'italic',
      },
      background: {
        ...originalStylesheet.background,
        color: '#fff',
        backgroundColor: '#C53719',
      },
      button: {
        ...originalStylesheet.button,
        backgroundColor: 'maroon',
        color: '#fff',
      },
      primary: '#C53719',
      secondary: 'maroon',
      textColor: '#fff',
    }
  }
}

Şimdi tek yapmamız gereken bir theme sadece bir satırla:

const theme = new Theme()
bloodTheme(theme) 
const stylesheet = theme.createStylesheet()
console.log(stylesheet)

Tema şimdi bize bir varsayılan veriyor blood çalışmak için stil sayfası:

{
  "name": "blood",
  "header": {
    "color": "#fff",
    "fontStyle": "italic",
    "fontFamily": "Roboto, sans-serif"
  },
  "background": { "backgroundColor": "#C53719", "color": "#fff" },
  "button": { "backgroundColor": "maroon", "color": "#fff" },
  "color": "#fff",
  "primary": "#C53719",
  "secondary": "maroon",
  "textColor": "#fff"
}

Gördüğünüz gibi kod/uygulama theme değişmedi. Özel stil sayfasını uygulamak da değişmedi:

theme.applyStylesheet(stylesheet)

Artık web sayfamız blood uygulanan tema stilleri:

tema-dekoratör-javascript-uygula-kan-teması

İstediğimiz kadar tema oluşturabilir ve istediğimiz zaman uygulayabiliriz. Bu, örneğin özel temalar gibi eklentiler için kodumuzu açık bıraktığımız anlamına gelir.

Geçici Davranış Uygulamak

Dekoratörleri kullanmanın bir başka iyi zamanı, geçici davranışları nesnelere uygulamak, çünkü gelecekte onu kaldırmayı planlıyoruz.

Örneğin, Noel mevsimi yaklaşıyorsa, kolayca bir Noel stil sayfası ve bir dekoratör olarak uygulayın. Bu harika çünkü Noel sezonu bittiğinde koddan kolayca çıkarabiliyoruz. Önceki örneğimizde, orijinal stil sayfasına geri dönmek için tek yapmamız gereken, sadece bloodTheme(theme) astar.

Alt Sınıflandırma/Kalıtım

Dekoratörleri kullanmanın bir başka iyi kullanım durumu, kodumuz büyüdüğünde alt sınıflar oluşturmanın yönetilemez hale gelmesidir. Ancak, JavaScript’te sınıf devralma uygulamalarını yoğun olarak kullanmıyorsanız, Java gibi statik dillerin aksine JavaScript’te bu sorun o kadar büyük bir sorun değildir.

Hata Ayıklama Modları

Başka bir yararlı kullanım örneği, bir hata ayıklama modu dekoratör, uygulandığında konsola olan her şeyi günlüğe kaydeder. Örneğin burada bir debugTheme geliştirme modunda işimize yarayacak dekoratör:

function debugTheme(originalTheme) {
  const stylesheet = originalTheme.createStylesheet()
  console.log(
    '%cStylesheet created:',
    'color:green;font-weight:bold;',
    stylesheet,
  )
  if (!stylesheet.primary) {
    console.warn(
      'A stylesheet was created without a primary theme color. There may be layout glitches.',
    )
  }
}

const theme = new Theme()
bloodTheme(theme)
if (process.env.NODE_ENV === 'development') debugTheme(theme)

Konsolumuz artık uygulamamızı şurada çalıştırırken faydalı bilgiler veriyor: development mod:

hata ayıklama modu tema dekoratörü javascript konsolu günlük mesajları

Bir cevap yazın

E-posta hesabınız yayımlanmayacak.