Material-UI yönetilen stilleri material-ui, reat olmayan öğelere nasıl uygulayabilirim?


9

Material UI ve tema sağlayıcısını (JSS kullanarak) kullandığım bir uygulama var.

Şimdi tam teşekküllü bir React kütüphanesi olmayan fullcalendar-reakt'ı kullanıyorum - sadece orijinal fullcalendar kodunun etrafında ince bir React bileşeni sarıcısı.

Yani, unsurlarını nasıl şekillendirdiğini kontrol etmek için render sahne gibi şeylere erişimim yok.

Ancak, bunları oluştururken çağrılan bir geri çağrı aracılığıyla DOM öğelerine doğrudan erişmenizi sağlar (ör. EventRender yöntemi ).

İşte temel bir demo sanal alanı.

resim açıklamasını buraya girin

Şimdi yapmak istediğim, Tam Takvim bileşenlerinin (örn. Düğmeler) uygulamamın geri kalanıyla aynı görünümü ve hissi paylaşmasını sağlamak.

Bunu yapmanın bir yolu, kullandığı sınıf adlarına bakarak ve stili buna göre uygulayarak tüm stilleri el ile geçersiz kılabilmemdir.

Veya - Belgelerinde önerildiği gibi bir Bootstrap teması uygulayabilirim.

Ancak bu çözümlerden herhangi biriyle ilgili sorun şudur:

  1. Çok iş olurdu
  2. Senkronizasyon sorunları yaşardım, MUI temamda değişiklik yaptıysam ve takvim temasını güncellemeyi unuttuysam, farklı görüneceklerdi.

Ne yapmak istiyorum ya:

  • MUI temasını sihirli bir şekilde bir Bootstrap temasına dönüştürün.
  • Veya MUI sınıfı adları ile takvim sınıfı adları arasında aşağıdakiler gibi bir eşleme oluşturun:
.fc-button = .MuiButtonBase-root.MuiButton-root.MuiButton-contained
.fc-button-primary= .MuiButton-containedPrimary

Çalıştırmak için seçicilere vb. Masaj yapmak zorunda kalmam. Çoğunlukla temayı değiştirdiğim zaman - iki yerde değiştirmek istemiyorum.

@extendSözdizimi ile Sass gibi bir şey kullanmak aklımdaki şey. Sass ile tam takvim CSS'yi yeterince kolayca oluşturabilirim - ama Sass MuiTheme'e nasıl erişebilir?

Belki de karşıt yaklaşımı benimseyebilirim - MUI'ye 'Buradaki bu sınıf isimleri bu MUI sınıfları gibi biçimlendirilmelidir' deyin.

Bunu nasıl çözeceğime dair somut öneriler var mı?

Yanıtlar:


4

İşte benim önerim (açıkçası, ileri doğru değil). MUI temasından stilleri alın ve kullanarak styleetiketi oluşturun react-helmet. Olay güzel yapmak için, harita yapmak bir "sarıcı" bileşen oluşturdum. Yalnızca birincil kuralı uyguladım, ancak tüm diğer kurallara genişletilebilir.

Bu şekilde, temada yapacağınız herhangi bir değişiklik eşlenen seçicileri de etkileyecektir.

import React from "react";
import { Helmet } from "react-helmet";

export function MuiAdapter({ theme }) {
  if (!theme.palette) {
    return <></>;
  }
  return (
    <Helmet>
      <style type="text/css">{`
          .fc-button-primary {
            background: ${theme.palette.primary.main}
          }
          /* more styles go here */
      `}</style>
    </Helmet>
  );
}

Ve adaptörün kullanımı

<MuiAdapter theme={theme} />

Çalışma demosu: https://codesandbox.io/s/reverent-mccarthy-3o856

ekran görüntüsü


Bu düşünceyi seviyorum. Bu çözümle ilgili sorun, temel olarak tüm stilleri kendiniz (yani fareyle üzerine gelme rengi, dolgu, sınır yarıçapı vb.) Uygulamanızdır. Örneğin, düğme metninin altı çizili olması gerektiğine karar verdiyseniz, text-decorationözelliği kaska eklemeyi hatırlamanız gerekir .
dwjohnston

Ne istediğini anlıyorum. Farklı bir yaklaşım benimsemeye ve MUI styleetiketlerini manipüle etmeye ve bunları .fc-seçicilere haritaya göre eklemeye çalıştım, ancak temel seviyelerde (örneğin display, paddingvb.) Çatışmalar var , böylece sahip olsanız bile nasıl çalışacağını görmüyorum scss içinde taşıma seçeneği. Örneğin: codesandbox.io/s/charming-sound-3xmj9
Mosh Feu

Haha - şimdi bunu seviyorum. Daha sonra daha iyi bakacağım.
dwjohnston

3

ref' Den geçerek MUI sınıf adları ile takvim sınıfı adları arasında bir eşleme oluşturabilirsiniz . Bazılarının "en iyi uygulama" dediği şey bu olmayabilir ... ama bu bir çözüm :). Bileşeninizi işlevsel bir bileşenden sınıf bileşenine güncellediğimi, ancak bunu işlevsel bir bileşendeki kancalarla başarabileceğinizi unutmayın.

Referans ekle

Bir ekleme refsenin durumda, bir referans olarak ayarlamak istediğiniz MUI elemana Button.

<Button
  color="primary"
  variant="contained"
  ref={x => {
    this.primaryBtn = x;
  }}
>

Ve a refile diveşlemek istediğiniz bileşenin etrafına sarın . Bize erişime izin vermeyeceği için doğrudan bileşene ekleyemezsiniz children.

<div
  ref={x => {
    this.fullCal = x;
  }}
>
  <FullCalendar
    ...
  />
</div>

Harita sınıfları

Gönderen componentDidMount()doğru DOM düğümünü hedef ne gerekiyorsa mantık eklenti (dava için, ben mantığını eklendi typeve matchingClass). Ardından bu mantığı tüm FullCalendar DOM düğümlerinde çalıştırın ve classListeşleşen herhangi biriyle değiştirin .

componentDidMount() {
  this.updatePrimaryBtns();
}

updatePrimaryBtns = () => {
  const children = Array.from(this.fullCal.children);
  // Options
  const type = "BUTTON";
  const matchingClass = "fc-button-primary";

  this.mapClassToElem(children, type, matchingClass);
};

mapClassToElem = (arr, type, matchingClass) => {
  arr.forEach(elem => {
    const { tagName, classList } = elem;
    // Check for match
    if (tagName === type && Array.from(classList).includes(matchingClass)) {
      elem.classList = this.primaryBtn.classList.value;
    }

    // Run on any children
    const next = elem.children;
    if (next.length > 0) {
      this.mapClassToElem(Array.from(next), type, matchingClass);
    }
  });
};

Bu belki biraz ağırdır, ancak Güncelleme Malzeme Arayüzünü güncellediğinizde gelecekteki kanıt gereksiniminizi karşılar. Ayrıca classList, belirgin faydaları olan bir öğeye geçerken değiştirmenize de izin verir .

Uyarılar

'Mapped-to' bileşeni ( FullCalendar) hedeflediğiniz öğelerdeki sınıfları güncellediyse ( .is-selectedgeçerli bir düğmeye eklenmiş gibi ) veya montajdan sonra yeni düğmeler eklerse, ilgili değişiklikleri izlemenin ve yeniden çalıştırmanın bir yolunu bulmanız gerekir mantık.

Ayrıca (açık bir şekilde) değişen sınıfların, bir kullanıcı arayüzü gibi istenmeyen sonuçlara yol açabileceğini ve bunları nasıl düzelteceğinizi anlamanız gerektiğini de belirtmeliyim.

İşte çalışma sanal alanı: https://codesandbox.io/s/determined-frog-3loyf


1
Bu çalışıyor. Bir sınıf bileşenine dönüştürmeniz gerekmediğini unutmayın - bunu yapmak için kancaları kullanabilirsiniz.
dwjohnston

Haklısın, bu fonksiyonel bir bileşendeki kancalarla yapılabilir. Cevabı yansıtacak şekilde güncelledim.
sallf

Güzel, oldukça pragmatik bir yaklaşım. Ama her zaman bir ref'ye ihtiyaç duyacağınız için gerçekten uygun değil.
Aniket Chowdhury
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.