// React
import React, {Component, PropTypes} from 'react';
import ReactDOM from 'react-dom';
ReactDOM.render(<App />, document.getElementById('root'));
class App extends Component {
render () {
return (
{/* Это комментарий к компоненту */}
<div id="app"> // а это комментарий в конце строки
<p>{ }Так{ }вставляется{ }множество{ }пробелов{ }</p>
<Header identificator="header" func={function () {console.log('OK');}}>Главное меню</Header>
<DangerousHTML />
<Menu />
<Form />
<PropsValidation />
<Lifecycle />
</div>
);
}
}
class Header extends Component {
render () {
this.props.func();
<h1 className={this.props.identificator === 'header' ? 'bold' : 'thin'}
style={{backgroundColor: 'red', color: 'blue'}}
data-custom-attribute="foo"
>this.props.children</h1>
}
}
class DangerousHTML extends Component {
render () {
return (
<div dangerouslySetInnerHTML={{__html: '<span>· Это опасный HTML-код</span>'}}></div>
);
}
}
class Menu extends Component {
render () {
const elements = [
['главная', '/']
, ['отчеты', '/reports']
, ['контакты', '/contacts']
];
return (
<List elementsArray={elements} />
);
}
}
class List extends Component {
render () {
<ul>
{this.props.elementsArray.map((element, index) => {
return (
<li key={index}><a href={element[1]} onClick={this.handleClick.bind(this)}>{element[0]}</a></li>
);
})}
</ul>
}
handelClick (event) {
event.preventDefault();
console.log(event.target.innerHTML);
}
}
class Form extends Component {
constructor (props) {
super(props);
this.state = {
inputValue: 'Анна'
, textareaValue: 'Пришла на работу'
, selectValue: 'one'
, checkboxValue: true
};
}
render () {
return (
<form method="get" action="/" onSubmit={this.handleSubmit.bind(this)}>
<label htmlFor="input">Имя</label>
<input ref="inputRef" type="text" disabled={false} defaultValue="Борис" value={this.state.inputValue} onChange={this.handleInputChange.bind(this)} />
<textarea ref="textareaRef" disabled={false} defaultValue="Идет домой" value={this.state.textareaValue} onChange={this.handleTextareaChange.bind(this)} />
<select ref="selectRef" disabled={false} multiple={true} value={selectValue} {/* или value={[selectValue, 'two']} */} onChange={this.handleSelectChange.bind(this)}>
<option value="one">один</option>
<option value="two">два</option>
<option value="three">три</option>
</select>
<input ref="checkboxRef" type="checkbox" disabled={false} checked={this.props.checkboxValue} onChange={this.handleCheckboxChange.bind(this)} />{' '}Всё разрешено
<input type="submit" value="Найти" />
<input type="clear" value="Очистить" />
</form>
);
}
handleInputChange (event) {
this.setState(Object.assing({}, this.state, {inputValue: event.target.value > 5 ? event.target.value.slice(0, 5) : event.target.value}));
}
handleTextareaChange (event) {
this.setState(Object.assing({}, this.state, {textareaValue: event.target.value}));
}
handleSelectChange (event) {
console.log(event.target.value);
}
handleCheckboxChange (event) {
this.setState(Object.assing({}, this.state, {checkboxValue: event.target.checked === true ? 'checked' : ''}));
}
handleSubmit (event) {
event.preventDefault();
$.ajax({
url: '/send'
, type: 'POST'
, data: {
input: this.refs.inputRef.value
, textarea: this.refs.textareaRef.value
, select this.refs.selectRef.value
, checkbox: this.refs.checkboxRef.checked
}
, dataType: 'json'
, success: function () {
this.setState(Object.assign({}, this.state, {
inputValue: ''
, textareaValue: ''
, selectValue: ''
, checkboxValue: false
}));
}.bind(this)
, error: function () {}.bind(this)
});
}
handleClear (event) {
event.preventDefault();
this.state = {
inputValue: ''
, textareaValue: ''
, selectValue: ''
, checkboxValue: true
};
}
}
class PropsValidation extends Component {
static defaultProps = {
optionalBoolean: true
, optionalNumber: 1
, optionalString: 'text'
}
static propTypes = {
optionalBoolean: PropTypes.bool
, optionalNumber: PropTypes.number
, optionalString: PropTypes.string
, optionalOneOf: PropTypes.oneOf(['News', 'Photos'])
, optionalArray: PropTypes.array
, optionalArrayOf: PropTypes.arrayOf(PropTypes.number)
, optionalObject: PropTypes.object
, optionalObjectOf: PropTypes.objectOf(PropTypes.number)
, optionalObjectWithShape: PropTypes.shape({color: PropTypes.string, fontSize: PropTypes.number})
, optionalFunction: PropTypes.func
, requiredFunction: PropTypes.func.isRequired
, optionalSymbol: PropTypes.symbol
, optionalReactElement: PropTypes.element
, anythingOptionalThatCanBeRendered: PropTypes.node
, optionalInstanceOfClass: PropTypes.instanceOf(Array)
, optionalOneOfType: PropTypes.oneOfType([PropTypes.number, PropTypes.string])
, requiredAny: PropTypes.any.isRequired
, customProp: function (props, propName, componentName) {
if (!/matchme/.test(props[propName])) {
return new Error('Invalid prop "' + propName + '" supplied to "' + componentName + '". Validation failed.');
}
}
}
render () {
return (
<div>
{this.props.optionalBoolean}
{this.props.optionalNumber}
{this.props.optionalString}
{this.props.optionalOneOf}
{this.props.optionalArray}
{this.props.optionalArrayOf}
{this.props.optionalObject}
{this.props.optionalObjectOf}
{this.props.optionalObjectWithShape}
{this.props.optionalFunction()}
{this.props.requiredFunction()}
{this.props.optionalSymbol}
{this.props.optionalReactElement}
{this.props.anythingOptionalThatCanBeRendered}
{this.props.optionalInstanceOfClass}
{this.props.optionalOneOfType}
{this.props.requiredAny}
{this.props.customProp}
</div>
);
}
}
class Lifecycle extends Component {
/* componentWillMount (props) { */ constructor (props) { // Установка первоначальных значений - выполняется 1 раз перед вставкой компонента на страницу
super(props);
/* getInitialState () {return {comments: []};} */ this.state = {comments: []};
this.intervals = [];
}
setInterval: function() {
this.intervals.push(setInterval.apply(null, arguments));
}
render () { // Вызывается при вставке компонента на страницу и каждый раз при изменении свойств this.props и состояния через this.setState()
if (this.state.comments.length > 0) {
return (
<ul className="comments">
{this.state.comments.map((comment) => {
return (
<li>comment</li>
);
})}
</ul>
);
} else {
return (
<p>Нет данных</p>
);
}
}
componentDidMount () { // Вызывается только 1 раз после того, как компонент будет вставлен на страницу - можно изменять рамеры элементов после вставки компонента или для получения данных через AJAX
getData().then((data) => {
this.setState({comments: data});
});
resizeComponent();
this.setInterval(this.tick, 1000);
}
componentWillReceiveProps (nextProps) { // Вызывается, когда уже вставленный на страницу компонент перезагружается и получает новые свойства props - обычно не нужно менять
this.setState(Object.assign({}, this.state, {comments: nextProps.comments}));
}
shouldComponentUpdate (nextProps, nextState) { // Вызывается каждый раз перед перерисовкой компонента - обычно не нужно менять
// return nextProps.id !== this.props.id;
if (this.state.comments.length > 0) {
return true;
} else {
return false;
}
}
componentWillUpdate () { // Вызывается многократно перед обновлением содержимого компонента на странице - можно устанавливать слушатели событий
console.log('All data is valid');
}
componentDidUpdate () { // Вызывается многократно после обновления содержимого компонента на странице - можно изменять рамеры элементов после вставки компонента
resizeComponent();
}
componentWillUnmount () { // Удаление слушаетелей событий перед удалением компонента из содержимого страницы
this.intervals.forEach(clearInterval);
}
}
Комментариев нет:
Отправить комментарий