【问题标题】:Using "material-components-web" within "react-boilerplate" code在“react-boilerplate”代码中使用“material-components-web”
【发布时间】:2017-03-04 04:37:19
【问题描述】:

在对 GitHub 上现有的样板代码进行了一些研究之后,我决定使用 react-boilerplate 来开始我的 React 应用程序。我正计划在我的网站上添加 Material 样式,由于 react-mdl 现在已弃用,我正计划在我的项目中使用 material-components-web 依赖项。

这是我的第一个 React 应用程序,我想知道一种干净的方法来删除默认样式并在我的项目中添加对 material-components-web 的依赖项。

非常感谢任何帮助。谢谢。

【问题讨论】:

    标签: javascript reactjs material-design single-page-application react-boilerplate


    【解决方案1】:

    编辑:更新答案 (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 文件(您必须安装 @material npm 模块:npm install --save @material)。然后你需要 node-sass 并在你的 webpack 配置中包含 @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>
                ); 
            }
        }
    

    并将其添加到您的文本字段中:

    &lt;div className="mdc-textfield" data-mdc-auto-init="MDCTextfield"&gt;

    现在另一种可能性是像这样导入:

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

    这里你需要告诉你的 webpack 配置文件中的 bable-loader 也包含 node_modules/@material 文件夹。其他一切基本保持不变。

    【讨论】:

    • 这里的答案非常好,但是 React 已经对使用文本引用进行了更改,并且这里的方法将被弃用。请参阅文档:https://reactjs.org/docs/refs-and-the-dom.html 解决方案是使用函数将值设置为类的属性,在这种情况下,this.refs.dialog 将变为 this.dialog,根据以下示例设置:@987654331 @
    【解决方案2】:

    稍微修改@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>
            )
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-25
      • 2017-12-21
      • 2016-01-27
      • 1970-01-01
      • 2020-08-23
      • 2021-10-09
      • 2017-08-28
      • 1970-01-01
      • 2018-06-20
      相关资源
      最近更新 更多