Использование материалов-компонентов-паутины в коде реакции-шаблона

После некоторого исследования существующего шаблонного кода на GitHub я решил использовать react-boilerplate, чтобы получить началось с моего приложения React. Я планировал добавить стили Материала на свой веб-сайт, и поскольку react-mdl сейчас устарела, я планировал использовать зависимость material-components-web на моем проекте.

Это мое первое приложение React, и я хотел бы знать простой способ удалить стили по умолчанию и добавить зависимость к material-components-web в моем проекте.

Любая помощь высоко ценится. Спасибо.


person Shankar Raju    schedule 04.03.2017    source источник


Ответы (2)


EDIT: обновленный ответ (v0.22.0)

Для настройки CSS вы все равно можете использовать обычный CSS:

<link rel="stylesheet" href="LINK_TO/material-components-web.css">

Но я бы порекомендовал использовать scss, таким образом вы можете переопределить различные значения, такие как цвета темы, и настроить все так, как вы хотите. Пример:

$mdc-theme-primary: #404040;
$mdc-theme-accent: #a349a3;
$mdc-theme-background: #fff;  

@import "@material/ripple/mdc-ripple";
@import "@material/typography/mdc-typography";
@import "@material/theme/mdc-theme";
@import "@material/button/mdc-button";

Для использования компонентов, которым нужна логика в терминах javascript, я обычно пишу обертку react.js для этого компонента. Вот пример компонента диалога принятия/отклонения:

import React from 'react';
import { MDCDialog } from '@material/dialog/dist/mdc.dialog';

class AcceptDialog extends React.Component {
    constructor(props) {
        super(props);

        this.passThroughInfo;
    }

    componentDidMount() {
        this.dialog = new MDCDialog(this.refs.dialog);
        // provide control to parent component to open the dialog from there
        this.props.provideCtrl({
            show: (passThroughInfo) => {
                this.passThroughInfo = passThroughInfo;
                this.dialog.show();
            },
            close: () => {
                this.passThroughInfo = undefined;
                this.dialog.close();
            }
        });

        this.dialog.listen('MDCDialog:accept', () => {
            this.props.acceptCb(this.passThroughInfo);
        })

        this.dialog.listen('MDCDialog:cancel', () => {
            this.props.declineCb(this.passThroughInfo);
        })
    }

    componentWillUnmount() {
        this.props.provideCtrl(null);
    }

    defaultProps = {
        className: "",
        id: "",
        header: "",
        text: "",
        acceptCb: function () { },
        declineCb: function () { }
    }

    render() {
        let className = "mdc-dialog accept_dialog" + this.props.className;
        return (
            <aside className={className} role="alertdialog" ref="dialog" id={this.props.id}>
                <div className="mdc-dialog__surface">
                    {this.props.header !== "" &&
                        <header className="mdc-dialog__header">
                            <h2 className="mdc-dialog__header__title">
                                {this.props.header}
                            </h2>
                        </header>
                    }
                    <section className="mdc-dialog__body">
                        {this.props.section}
                    </section>
                    <footer className="mdc-dialog__footer">
                        <button type="button" className="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--cancel">Decline</button>
                        <button type="button" className="mdc-button mdc-dialog__footer__button mdc-dialog__footer__button--accept">Accept</button>
                    </footer>
                </div>
                <div className="mdc-dialog__backdrop"></div>
            </aside>
        );
    }
}

export default AcceptDialog

Затем используйте это в других компонентах:

// How to open the accept dialog
this.accept_dialog.show(data);

// The callback called on accept
callback(data){...}

<AcceptDialog 
    acceptCb={this.callback}
    provideCtrl={ctrl => this.accept_dialog = ctrl}>
</AcceptDialog>

____________СТАРЫЙ ОТВЕТ_______________

1) Добавление CSS

Это очень легко. Вы можете просто добавить его в свой файл index.html:

<link rel="stylesheet" href="LINK_TO/material-components-web.css">

Если вы используете SASS, вы также можете получить доступ к файлам sass (вам необходимо установить модуль npm @material: npm install --save @material). Затем вам понадобится node-sass и укажите путь к папке @material в конфигурации вашего веб-пакета. Я не пробовал это, но в теории это должно работать.


2) Добавление Javascript

Опять же, у вас больше возможностей. Вот что я сделал. Вы можете импортировать mdc следующим образом

class Foo extends Component(){
componentDidMount(){
    // either this like that
    mdc.textfield.MDCTextfield.attachTo(this.refs.textfield);
    // or like that
    const MDCTextfield = mdc.textfield.MDCTextfield;
    const textfield = new MDCTextfield(this.refs.textfield);
}
render() {
    return(
        <form className="form-group" onSubmit={this.submitForm}>
            <div className="mdc-textfield" ref="textfield">
                <input type="text" id="my-textfield" className="mdc-textfield__input"/>
                <label className="mdc-textfield__label" htmlFor="my-textfield">Hint text</label>
            </div>
        </form>
    );
}

}

теперь вы можете создать компонент (оболочку) для поля ввода. Если вы не хотите этого делать, вы также можете автоматически инициализировать все свои компоненты, добавив:

// app.component.js    
import * as mdc from 'material-components-web/dist/material-components-web';

    class App extends React.Component {
        componentDidMount(){        
            mdc.autoInit();
        }
        render(){
            return(
                <div className="my-app">
                    {this.props.children}
                </div>
            ); 
        }
    }

и добавьте это в свои текстовые поля:

<div className="mdc-textfield" data-mdc-auto-init="MDCTextfield">

Теперь другая возможность - импортировать так:

import {MDCCheckbox} from '@material/checkbox';

Здесь вам нужно сообщить загрузчику bable в файле конфигурации вашего веб-пакета, чтобы он также включал папку node_modules/@material. Все остальное остается в основном таким же.

person Jodo    schedule 09.05.2017
comment
Ответ здесь очень хороший, однако React внесла изменения в использование текстовых ссылок, и этот метод должен быть объявлен устаревшим. См. документы: https://reactjs.org/docs/refs-and-the-dom.html Решение состоит в том, чтобы использовать функцию для установки значения свойства в классе, в этом случае this.refs.dialog станет this.dialog, который устанавливается в соответствии с приведенным ниже примером: code ‹aside ref={(dialog) =› { this.dialog = dialog; }} /› code Проголосовал за меня. Должен быть отмечен как правильный ответ!!! - person Aiky30; 15.12.2017

Немного изменив ответ @Jodo, это сработало для меня:

import React from 'react'
import {observer} from 'mobx-react'

import * as mdc from 'material-components-web/dist/material-components-web'

@observer
export class RegisterForm extends React.Component{
    /**
     * Notice I'm calling mdc.autoInit() on the "RegisterForm" component NOT on any parent component
     * Actually, when I call mdc.autoInit() on any parent component, it won't work
     */
    componentDidMount=()=>{mdc.autoInit()}
    setMeta=(e)=>{
        this.props.store.storeReg.setMeta(e.target.name,e.target.value)
    }
    preview=()=>{
        this.props.store.storeReg.preview()
    }
    render=()=>{
        return(
            <form onChange={this.setMeta.bind(this)}>
                <div class="mdc-form-field">
                    <div class="mdc-textfield" data-mdc-auto-init="MDCTextfield">
                        <input class="mdc-textfield__input" type="text" required name="email" value={this.props.store.storeReg.meta.get('email')}/>
                        <label class="mdc-textfield__label" for="email">Email</label>
                    </div>
                </div>
                <div class="mdc-form-field">
                    <div class="mdc-textfield" data-mdc-auto-init="MDCTextfield">
                        <input class="mdc-textfield__input" type="text" required name="first_name" value={this.props.store.storeReg.meta.get('first_name')}/
                        <label class="mdc-textfield__label" for="first_name">First Name</label>
                    </div>
                </div>
                <div class="mdc-form-field">
                    <div class="mdc-textfield" data-mdc-auto-init="MDCTextfield">
                        <input class="mdc-textfield__input" type="text" required name="last_name" value={this.props.store.storeReg.meta.get('last_name')}/>
                        <label class="mdc-textfield__label" for="last_name">Last Name</label>
                    </div>
                </div>
                <div class="group">
                    <button class="mdc-button mdc-button--raised mdc-button--primary mdc-ripple-surface" data-mdc-auto-init="MDCRipple" type="button" onClic
                </div>
            </form>
        )
    }
}
person user3405291    schedule 01.08.2017