React est un framework génial conçu par une bande de développeurs géniaux chez Facebook. Il implémente un DOM virtuel, en utilisant une approche semblable au DOM pour ajouter instantanément les composants dont vous avez besoin et supprimer instantanément ceux dont vous n’avez pas besoin. React joue le rôle du V dans la structure MVC, mais si vous l’associez à Flux, vous obtenez un framework génial qui synchronise facilement M et V. Plus d’informations sur Flux plus tard~

Composants

Dans React, vous pouvez créer un composant avec des fonctionnalités spéciales que vous ne trouveriez pas dans les éléments HTML même en cherchant avec une lanterne, comme la navigation déroulante de ce tutoriel. Chaque composant possède son propre territoire (scope), donc une fois qu’on définit un composant, on peut le réutiliser encore et encore sans avoir besoin d’interagir avec d’autres composants !

Chaque composant possède une fonctionnalité appelée render, qui renvoie efficacement le HTML à projeter dans le navigateur. Nous pouvons aussi appeler d’autres composants React, ce qui signifie qu’une fois que vous entrez dans React, c’est profond comme la mer — oh, non, c’est « rien n’est impossible, seulement inimaginable ».

JSX

Si vous prêtez une attention particulière à React, vous remarquerez peut-être quelque chose appelé JSX. JSX nous permet d’écrire du HTML dans JavaScript au lieu d’utiliser HTML pour contenir JavaScript. Cela nous aide à développer rapidement parce que nous n’avons pas à nous soucier des chaînes de caractères, des retours à la ligne et autres. Vous pouvez exécuter JSX dans le navigateur, mais ce n’est pas recommandé car cela ralentira votre page. Gulp et Grunt fournissent un interpréteur JSX pour vos tâches de prétraitement, donc si vous voulez utiliser JSX, je recommande d’activer cette fonctionnalité.

Utilisation de JSX

Comme mentionné précédemment, en JSX chaque composant possède une méthode render qui produit un « ViewModel » – avant de renvoyer le HTML au composant, vous pouvez placer les informations de ce modèle de vue dans la vue, ce qui signifie que votre HTML changera dynamiquement en fonction de ce modèle (par exemple, une liste dynamique).

Une fois que vous avez terminé, vous pouvez renvoyer tout ce que vous voulez afficher. Utiliser JSX pour faire cela est si simple.

var ExampleComponent = React.createClass({
    render: function () {
        return (
            <div className="navigation">
                Hello World!
            </div>
            );
    }
});

Si vous exécutiez ce code dans votre navigateur, vous n’obtiendriez qu’une erreur de syntaxe, car en JavaScript les caractères < et > doivent être entourés de guillemets. Lorsque vous exécutez l’interpréteur JSX sur le code, il est transformé en ceci.

var ExampleComponent = React.createClass({
    render: function () {
        return (
            React.createElement('div', {className: 'navigation'}, 'Hello World!')
            );
    }
});

Vous pouvez cliquer ici pour tester l’exemple.- J’utilise l’interpréteur JSX du navigateur (non recommandé, mais pour JSFiddle).

Ça a fonctionné ! JSX interprète ce que vous avez généré à l’aide de React.createElementtousles nœuds DOM, en générant les types de nœuds, paramètres et contenu. Vous pouvez vous passer de JSX, mais cela signifie que vous devez écrire manuellement tous les nœuds DOM via React.createElement. D’innombrables exemples me disent d’utiliser JSX.

Vous devez vous demander pourquoi j’utilise className au lieu de class sur le DOM. C’est parce que class est un mot réservé en JavaScript. Quand JSXinterprètevotre code, il transforme tous les attributs du nœud en un objet, mais vous ne pouvez pas traiter l’objet comme un attribut !

Utilisation de variables dans les props

Si vous souhaitez modifier dynamiquement la classe de style d’un composant (ou toute autre valeur d’attribut), vous pouvez utiliser des variables. Cependant, vous ne pouvez pas simplement passer un nom de variable ; vous devez également l’entourer d’une paire d’accolades pour que JSX sache qu’il s’agit d’une variable externe.

var ExampleComponent = React.createClass({
render: function () {
    var navigationClass = 'navigation';
    return (
        <div className={ navigationClass }>
            Hello World!
        </div>
        );
}
});

Vous pouvez voir cette fonctionnalité ici.

Le moteur de rendu initial

Lorsque vous voulez effectuer le rendu d’un composant React pour la première fois, vous devez indiquer à React quel composant rendre et aussi spécifier un nœud DOM existant pour indiquer où effectuer le rendu de ce composant. Pour ce faire, vous utiliserez la fonction React.render.

var ExampleComponent = React.createClass({
render: function () {
    return (
        <div className="navigation">
            Hello World!
        </div>
        );
}
});
React.render(<ExampleContent />, document.body);

Il effectuera le rendu du composant sur le nœud body—simple, non ! À partir de là, vous pouvez appeler d’autres composants comme d’habitude, ou, si vous le souhaitez, vous pouvez utiliser la fonction render plusieurs fois, si vous ne voulez pas utiliser React pour effectuer le rendu de toute la page mais que vous voulez quand même utiliser plusieurs composants.

Les bases d’un composant

Les composants peuvent avoir leur propre « état ». Cela nous permet de réutiliser le même composant de nombreuses fois tout en les faisant paraître complètement différents, car l’état de chaque instance de composant est unique.

Lorsque vous passez des propriétés à un composant, celles-ci sont appelées props. Ne vous limitez pas aux attributs HTML ; vous pouvez passer tout ce que vous voulez et y accéder à l’intérieur du composant via this.props. Cela nous permet de réutiliser le même composant tout en lui passant un ensemble différent de props, comme la « configuration » du composant.

Props

D’après notre exemple précédent « Hello World! », nous avions l’attribut className sur le nœud HTML. À l’intérieur du composant, nous pouvons accéder à cette valeur via this.props.classname, mais comme mentionné précédemment, vous pouvez passer tout ce que vous voulez. Pour notre menu déroulant, nous devons configurer la navigation sous forme d’objet, que le composant utilisera comme configuration à rendre. Commençons—

var navigationConfig = [];

var Navigation = React.createClass({
    render: function () {
        return (
            <div className="navigation">

            </div>
            );
    }
});

React.render(<Navigation config={ navigationConfig } />, document.body);

Si nous accédons maintenant à this.props.config, nous obtiendrons un tableau vide (la valeur de navigationConfig). Avant d’entrer dans le code réel de navigation, expliquons le state.

State

Comme nous l’avons vu précédemment, chaque composant a son propre « state ». Lorsque vous utilisez le state, vous définissez d’abord l’état initial, et ce n’est qu’ensuite que vous pouvez utiliser this.setState pour le mettre à jour. Chaque fois que le state est mis à jour, le composant appelle à nouveau la fonction render, en utilisant les nouvelles valeurs pour remplacer ou modifier ce qui a été rendu précédemment. C’est l’essence du DOM virtuel : l’algorithme de diffing est exécuté à l’intérieur de React, donc nous n’avons pas à dépendre des mises à jour du DOM (car le DOM est lent). React calcule les différences et produit un ensemble d’instructions (par exemple, ajouter la classe « active » à « navigation__link », ou supprimer un nœud), puis les exécute sur le DOM.

Pour la navigation, nous conservons l’état ouvert du menu déroulant dans le state. Pour ce faire, ajoutez une fonction getInitialState à l’objet de configuration de la classe et retournez un objet avec l’état initial souhaité.

var navigationConfig = [];

var Navigation = React.createClass({
    getInitialState: function () {
        return {
            openDropdown: -1
        };
    },
    render: function () {
        return (
            <div className="navigation">

            </div>
            );
    }
});

React.render(<Navigation config={ navigationConfig } />, document.body);

Vous remarquerez que nous l’avons défini à -1. Lorsque nous sommes sur le point d’ouvrir un menu déroulant, nous utiliserons la position de l’élément de navigation dans le tableau de configuration stocké dans le state, et comme les index de tableau commencent à 0, nous devons utiliser -1 pour indiquer qu’aucun élément de navigation n’est actuellement ciblé.

Nous pouvons accéder à l’état en utilisant this.state, donc si nous regardons this.state.openDropdown, nous devrions obtenir -1 en retour.

Cycle de vie des composants

Chaque composant a son « cycle de vie » — une série de fonctions que vous pouvez définir dans la configuration du composant et qui seront appelées tout au long de la vie du composant. Nous avons déjà vu getinitialstate — elle n’est appelée qu’une seule fois, lorsque le composant est monté.

componentWillMount

Cette fonction est appelée lorsque le composant est sur le point d’être monté. Cela signifie que nous pouvons y exécuter du code nécessaire au fonctionnement du composant. Comme render est appelé plusieurs fois pendant le cycle de vie du composant, nous plaçons généralement ici le code qui ne doit s’exécuter qu’une seule fois, comme les requêtes XHR.

var ExampleComponent = React.createClass({
    componentWillMount: function () {
        // xhr request here to get data
    },
    render: function () {
        // this gets called many times in a components life
        return (
            <div>
                Hello World!
            </div>
            );
    }
});

componentDidMount

Une fois que votre composant a exécuté la fonction render et qu’il a réellement été rendu dans le DOM, componentDidMount sera appelé. Ici, nous pouvons effectuer toutes les opérations DOM dont nous avons besoin, ainsi que tout ce qui dépend du fait que le composant existe déjà dans le DOM, comme le rendu d’un graphique. Vous pouvez accéder au nœud DOM en interne en appelant this.getDOMNode.

var ExampleComponent = React.createClass({
    componentDidMount: function () {
        var node = this.getDOMNode();
        // render a chart on the DOM node
    },
    render: function () {
        return (
            <div>
                Hello World!
            </div>
            );
    }
});

componentWillUnmount

Cette fonction sera appelée lorsque vous êtes sur le point de retirer le composant du DOM. Cela nous permet de nettoyer derrière le composant, par exemple en supprimant les écouteurs d’événements que nous avons liés. Si nousnenettoyons pas derrière nous, alors lorsqu’un de ces événements est déclenché, il essaiera d’effectuer des calculs sur un composant qui n’a pas été monté, et React lèvera une erreur.

var ExampleComponent = React.createClass({
    componentWillUnmount: function () {
        // unbind any event listeners specific to this component
    },
    render: function () {
        return (
            <div>
                Hello World!
            </div>
            );
    }
});

Méthodes des composants

React fournit également des méthodes pour les composants afin de nous faciliter le travail. Elles sont appelées pendant le processus de création du composant. Par exemple, getInitialState nous permet de définir un état par défaut, afin que nous n’ayons pas à nous soucier de vérifier davantage dans le code si un élément d’état existe.

getDefaultProps

Lorsque nous créons un composant, nous pouvons définir des valeurs par défaut pour les props du composant comme bon nous semble. Cela signifie que lorsque nous appelons le composant, si vous ne définissez pas de valeurs pour ces props, le composant aura une « configuration » par défaut, et nous n’avons pas à nous soucier de vérifier les props à la ligne de code suivante.

Lorsque vous définissez un composant, ces props par défaut sont mises en cache, elles sont donc identiques pour chaque instance du composant et ne peuvent pas être modifiées. Pour le composant de navigation, nous définissons la configuration sur un tableau vide, donc même si aucune configuration n’est transmise, aucune erreur ne se produira dans la méthode render.

var Navigation = React.createClass({
    getInitialState: function () {
        return {
            openDropdown: -1
        };
    },
    getDefaultProps: function () {
        return {
            config: []
        }
    },
    render: function () {
        return (
            <div className="navigation">

            </div>
            );
    }
});

React.render(<Navigation config={ navigationConfig } />, document.body);

propTypes

Nous pouvons également spécifier un type pour chaque prop comme nous le souhaitons. C’est très utile pour vérifier et gérer les valeurs inattendues attribuées aux props. Comme dans la liste déroulante ci-dessous, nous spécifions que seuls des tableaux peuvent être placés dans la configuration.

var Navigation = React.createClass({
    getInitialState: function () {
        return {
            openDropdown: -1
        };
    },
    getDefaultProps: function () {
        return {
            config: []
        }
    },
    propTypes: {
        config: React.PropTypes.array
    },
    render: function () {
        return (
            <div className="navigation">

            </div>
            );
    }
});

React.render(<Navigation config={ navigationConfig } />, document.body);

mixins

Nous pouvons également ajouter des mixins aux composants. Il s’agit d’un composant de base indépendant de React (juste une configuration de type objet). Cela signifie que si nous avons deux composants avec des fonctionnalités similaires, nous pouvons partager une configuration (si l’état initial est le même). Nous pouvons créer de manière abstraite une méthode dans le mixin, afin de ne pas avoir à écrire deux fois le même code.

var ExampleMixin = {
    componentDidMount: function () {
        // bind some event listeners here
    },
    componentWillUnmount: function () {
        // unbind those events here!
    }
};

var ExampleComponent = React.createClass({
    mixins: [ExampleMixin],
    render: function () {
        return (
            <div>
                Hello World!
            </div>
            );
    }
});

var AnotherComponent = React.createClass({
    mixins: [ExampleMixin],
    render: function () {
        return (
            <div>
                Hello World!
            </div>
            );
    }
});

De cette façon, tous les composants ont les mêmes méthodes componentDidMount et componentWillUnmount, ce qui nous évite de réécrire du code. Quoi qu’il en soit, vous ne pouvez pas surcharger ces propriétés ; si une propriété est définie dans un mixin, elle ne peut pas être surchargée dans ce composant.

Boucles d’itération

Lorsque nous avons un tableau contenant des objets, comment parcourir ce tableau et rendre chaque objet sous forme d’éléments de liste ? JSX vous permet de l’utiliser dans n’importe quel fichier JavaScript. Vous pouvez utiliser map sur le tableau et retourner du JSX, puis utiliser React pour le rendre.

var navigationConfig = [
    {
        href: 'http://ryanclark.me',
        text: 'My Website'
    }
];
var Navigation = React.createClass({
    getInitialState: function () {
        return {
            openDropdown: -1
        };
    },
    getDefaultProps: function () {
        return {
            config: []
        }
    },
    propTypes: {
        config: React.PropTypes.array
    },
    render: function () {
        var config = this.props.config;
        var items = config.map(function (item) {
            return (
                <li className="navigation__item">
                    <a className="navigation__link" href={ item.href }>
                        { item.text }
                    </a>
                </li>
                );
        });
        return (
            <div className="navigation">
                { items }
            </div>
            );
    }
});
React.render(<Navigation config={ navigationConfig } />, document.body);

N’hésitez pas à utiliser navigationConfig dans JSFiddle.

La configuration de navigation se compose d'un tableau et d'objets, comprenant un attribut href pointant vers un lien hypertexte et un attribut text pour l'affichage. Lorsque nous faisons un map, cela parcourt le tableau un par un pour obtenir des objets. Nous pouvons accéder à href et text et les utiliser en HTML. Lors du retour de la liste, les éléments de liste de ce tableau seront tous remplacés, donc lorsque nous le mettons dans React pour traitement, il saura comment le rendre !

Mixins

Jusqu'à présent, nous avons réalisé l'expansion de toutes les listes déroulantes. Nous devons savoir quel élément est en cours de déroulement. Nous utiliserons la propriété .children pour parcourir notre tableau navigationConfig. Ensuite, nous pouvons boucler sur les sous-éléments de la liste déroulante.

var navigationConfig = [
    {
        href: 'http://ryanclark.me',
        text: 'My Website',
        children: [
            {
                href: 'http://ryanclark.me/how-angularjs-implements-dirty-checking/',
                text: 'Angular Dirty Checking'
            },
            {
                href: 'http://ryanclark.me/getting-started-with-react/',
                text: 'React'
            }
        ]
    }
];
var Navigation = React.createClass({
    getInitialState: function () {
        return {
            openDropdown: -1
        };
    },
    getDefaultProps: function () {
        return {
            config: []
        }
    },
    propTypes: {
        config: React.PropTypes.array
    },
    render: function () {
        var config = this.props.config;
        var items = config.map(function (item) {
            var children, dropdown;
            if (item.children) {
                children = item.children.map(function (child) {
                    return (
                        <li className="navigation__dropdown__item">
                            <a className="navigation__dropdown__link" href={ child.href }>
                                { child.text }
                            </a>
                        </li>
                    );
                });
                dropdown = (
                    <ul className="navigation__dropdown">
                        { children }
                    </ul>
                );
            }
            return (
                <li className="navigation__item">
                    <a className="navigation__link" href={ item.href }>
                        { item.text }
                    </a>
                    { dropdown }
                </li>
                );
        });
        return (
            <div className="navigation">
                { items }
            </div>
            );
    }
});
React.render(<Navigation config={ navigationConfig } />, document.body);

Exemple ici- Mais nous pouvons encore voir les éléments de la liste déroulante, même si nous définissonsopenDropdown le définir à-1 。

Nous pouvons accéder dans le composantthis.state, pour déterminer si la liste déroulante est ouverte, et nous pouvons y ajouter une nouvelle classe de style CSS pour afficher l'effet de survol.

var navigationConfig = [
    {
        href: 'http://ryanclark.me',
        text: 'My Website',
        children: [
            {
                href: 'http://ryanclark.me/how-angularjs-implements-dirty-checking/',
                text: 'Angular Dirty Checking'
            },
            {
                href: 'http://ryanclark.me/getting-started-with-react/',
                text: 'React'
            }
        ]
    }
];
var Navigation = React.createClass({
    getInitialState: function () {
        return {
            openDropdown: -1
        };
    },
    getDefaultProps: function () {
        return {
            config: []
        }
    },
    openDropdown: function (id) {
        this.setState({
            openDropdown: id
        });
    },
    closeDropdown: function () {
        this.setState({
            openDropdown: -1
        });
    },
    propTypes: {
        config: React.PropTypes.array
    },
    render: function () {
        var config = this.props.config;
        var items = config.map(function (item, index) {
            var children, dropdown;
            if (item.children) {
                children = item.children.map(function (child) {
                    return (
                        <li className="navigation__dropdown__item">
                            <a className="navigation__dropdown__link" href={ child.href }>
                                { child.text }
                            </a>
                        </li>
                    );
                });
                var dropdownClass = 'navigation__dropdown';
                if (this.state.openDropdown === index) {
                    dropdownClass += ' navigation__dropdown--open';
                }
                console.log(this.state.openDropdown, index);
                dropdown = (
                    <ul className={ dropdownClass }>
                        { children }
                    </ul>
                );
            }
            return (
                <li className="navigation__item" onMouseOut={ this.closeDropdown } onMouseOver={ this.openDropdown.bind(this, index) }>
                    <a className="navigation__link" href={ item.href }>
                        { item.text }
                    </a>
                    { dropdown }
                </li>
                );
        }, this);
        return (
            <div className="navigation">
                { items }
            </div>
            );
    }
});
React.render(<Navigation config={ navigationConfig } />, document.body);

Voir l'exemple ici– Lorsque vous survolez « My Website », la liste déroulante apparaîtra.

Plus tôt, j'ai ajouté des événements de souris à chaque élément de liste. Comme vous pouvez le voir, j'ai utilisé.bind(bind), plutôt que de l'appeler d'une autre manière – c'est parce que lorsque la souris de l'utilisateur quitte la zone de l'élément, nous n'avons pas besoin de nous soucier de l'endroit où se trouve le curseur ; tout ce que nous devons savoir, c'est fermer la liste déroulante, donc nous pouvons définir sa valeur à -1. Cependant, nous devons savoir quel élément est développé lorsque la souris de l'utilisateur entre, donc nous devons connaître ce paramètre (l'index de l'élément). Nous utilisons la méthode de liaison pour appeler plutôt que d'appeler simplement via une fonction parce que nous devons l'appeler via React. Si nous l'appelons directement, nous devrions l'appeler tout le temps, plutôt que de l'appeler dans l'événement.

Maintenant, nous pouvons ajouter de nombreux éléments ànavigationConfig parmi eux, et nous pouvons également ajouter des styles à la fonctionnalité de liste déroulante.Voir l'exemple。

Résumé

React est un framework simple, pratique, facile à utiliser et puissant. Son API concise permet de créer rapidement ses propres composants sans avoir à gérer un DOM complexe ni à effectuer des opérations particulièrement compliquées, en particulier lorsqu'il s'agit d'éléments de liste répétés et similaires.

Source : http://www.oschina.net/translate/getting-started-with-react