在对 GitHub 上现有的样板代码进行了一些研究之后,我决定使用react-boilerplate来开始我的 React 应用程序。我计划在我的网站上添加 Material 样式,并且由于react-mdl现在已弃用,我计划在我的项目中使用material-components-web依赖项。
这是我的第一个 React 应用程序,我想知道一种干净的方法来删除默认样式并在我的项目中添加对 material-components-web 的依赖关系。
非常感谢任何帮助。谢谢。
在对 GitHub 上现有的样板代码进行了一些研究之后,我决定使用react-boilerplate来开始我的 React 应用程序。我计划在我的网站上添加 Material 样式,并且由于react-mdl现在已弃用,我计划在我的项目中使用material-components-web依赖项。
这是我的第一个 React 应用程序,我想知道一种干净的方法来删除默认样式并在我的项目中添加对 material-components-web 的依赖关系。
非常感谢任何帮助。谢谢。
编辑:更新答案(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>
);
}
}
并将其添加到您的文本字段中:
<div className="mdc-textfield" data-mdc-auto-init="MDCTextfield">
现在另一种可能性是像这样导入:
import {MDCCheckbox} from '@material/checkbox';
在这里,您需要告诉 webpack 配置文件中的 bable-loader 也包含 node_modules/@material 文件夹。其他一切基本保持不变。
稍微修改@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>
)
}
}