Mengetik naskah dan bereaksi

Perkembangan Javascript terkadang menjadi seperti seorang detektif. Bagaimana cara memahami kode orang lain? Ada baiknya jika pengembang memiliki keterampilan halus dalam penamaan variabel sehingga orang lain mengerti maksudnya. Tetapi bagaimana jika anggota tim masih tidak selalu dapat memahami maksud rekan mereka? Bagaimana memahami apa yang menjadi argumen dari suatu fungsi?


Misalkan argumen fungsi disebut kesalahan. Mungkin kesalahan adalah array. Garis yang paling mungkin? Nah, array itu bisa dimengerti. Lagi pula, panjangnya diperiksa lebih lanjut. Tetapi properti panjang juga memiliki string. Tampaknya untuk mengetahui dengan tepat, Anda harus meletakkan breakpoint dan menjalankan skrip. Lalu, lewati skrip di UI sepenuhnya (misalnya, kita perlu langkah terakhir dari formulir). Sekarang di devtools dapat dilihat bahwa kesalahan adalah objek dengan seperangkat bidang tertentu, termasuk bidang panjang.


Ketidakjelasan dalam penguraian kode javascript menyebabkan pemborosan waktu pengembang. Solusi yang baik dalam hal ini bisa berupa naskah (selanjutnya disebut ts). Anda dapat menggunakannya di proyek berikutnya, atau bahkan lebih baik, membuat dukungan di yang sudah ada. Setelah itu, waktu untuk memahami kode orang lain akan berkurang secara signifikan. Memang, untuk memahami struktur data apa pun, cukup satu klik saja sudah cukup. Anda dapat berkonsentrasi pada logika bekerja dengan data dan kapan saja tahu bahwa Anda memahami kode dengan jelas.


Beberapa keunggulan ts harus diperhatikan. Ini banyak digunakan dalam berbagai kerangka kerja dan terkait erat dengan javascript. Pengembangan ts ditentukan oleh kebutuhan pengembang frontend.


Artikel ini menyajikan pengembangan aplikasi todo, tetapi hanya uraian singkat tentang poin-poin menarik. Kode lengkap dapat ditemukan di sini .


Saya menggunakan reaksi, naskah dan mobx. Mobx adalah alat yang fleksibel untuk mengelola keadaan aplikasi. Mobx ringkas. Ini memungkinkan Anda untuk bekerja dengan keadaan komponen reaksi dalam gaya sinkron. Tidak masalah seperti:


this.setState({name: 'another string'}); alert(this.state.name); 

Dalam hal ini, state.name lama ditampilkan.


Selain itu, mobx nyaman dan tidak mengganggu bekerja dengan tipe ts. Anda dapat menggambarkan status sebagai kelas terpisah atau langsung di dalam komponen reaksi.


Untuk mempermudah, semua komponen ditempatkan di folder komponen. Kelas didefinisikan dalam folder komponen dengan deskripsi keadaan yang secara logis dikaitkan dengan tampilan dan operasi komponen.


Folder TodoItem berisi file dengan komponen reaksi TodoItem.tsx, file dengan gaya TodoItem.module.scss, dan file status TodoItemState.ts.


TodoItemState.ts menjelaskan bidang untuk menyimpan data, cara mengaksesnya, dan aturan untuk mengubahnya. Berbagai kemungkinan sangat besar berkat OOP dan ts. Sebagian dari data dapat bersifat pribadi, sebagian hanya-baca dan sebagainya. Menggunakan @o dekorator, bidang yang dapat diamati ditentukan. Bereaksi komponen bereaksi terhadap perubahannya. Dekorator @a ( aksi ) digunakan dalam metode untuk mengubah status.


 // TodoItemState.ts import { action as a, observable as o } from 'mobx'; export interface ITodoItem { id: string; name: string; completed: boolean; } export class TodoItemState { @o public readonly value: ITodoItem; @o public isEditMode: boolean = false; constructor(value: ITodoItem) { this.value = value; } @a public setIsEditMode = (value: boolean = true) => { this.isEditMode = value; }; @a public editName = (name: string) => { this.value.name = name; }; @a public editCompleted = (completed: boolean) => { this.value.completed = completed; }; } 

Di TodoItem.tsx, hanya dua properti yang diteruskan ke properti. Dalam mobx, optimal untuk kinerja keseluruhan aplikasi untuk mentransfer struktur data yang kompleks ke komponen reaksi alat peraga. Karena kita menggunakan ts, kita dapat secara tepat menunjukkan jenis objek yang diterima oleh komponen.


 // TodoItem.tsx import React, { ChangeEventHandler } from 'react'; import { observer } from 'mobx-react'; import { TodoItemState } from './TodoItemState'; import { EditModal } from 'components/EditModal'; import classNames from 'classnames'; import classes from './TodoItem.module.scss'; export interface ITodoItemProps { todo: TodoItemState; onDelete: (id: string) => void; } @observer export class TodoItem extends React.Component<ITodoItemProps> { private handleCompletedChange: ChangeEventHandler<HTMLInputElement> = e => { const { todo: { editCompleted }, } = this.props; editCompleted(e.target.checked); }; private handleDelete = () => { const { onDelete, todo } = this.props; onDelete(todo.value.id); }; private get editModal() { const { todo } = this.props; if (!todo.isEditMode) return null; return ( <EditModal name={todo.value.name} onSubmit={this.handleSubmitEditName} onClose={this.closeEditModal} /> ); } private handleSubmitEditName = (name: string) => { const { todo } = this.props; todo.editName(name); this.closeEditModal(); }; private closeEditModal = () => { const { todo } = this.props; todo.setIsEditMode(false); }; private openEditModal = () => { const { todo } = this.props; todo.setIsEditMode(); }; render() { const { todo } = this.props; const { name, completed } = todo.value; return ( <div className={classes.root}> <input className={classes.chackbox} type="checkbox" checked={completed} onChange={this.handleCompletedChange} /> <div onClick={this.openEditModal} className={classNames( classes.name, completed && classes.completedName )}> {name} </div> <button onClick={this.handleDelete}>del</button> {this.editModal} </div> ); } } 

Antarmuka ITodoItemProps menjelaskan properti todo tipe TodoItemState. Jadi, di dalam komponen reaksi, kami diberikan data untuk tampilan dan metode untuk mengubahnya. Selain itu, pembatasan mengubah data dapat dijelaskan baik di kelas negara dan dalam metode komponen reaksi, tergantung pada tugas.


Komponen TodoList mirip dengan TodoItem. Di TodoListState.ts, Anda dapat melihat getter dengan dekorator @c (@computed). Ini adalah getter kelas biasa, hanya nilainya yang di-memo dan diceritakan kembali ketika dependensinya berubah. Dihitung dengan desain mirip dengan penyeleksi redux. Mudahnya, tidak perlu, seperti React.memo atau pilih kembali, untuk secara eksplisit melewati daftar dependensi. Bereaksi komponen menanggapi perubahan yang dihitung serta perubahan yang dapat diamati. Fitur yang menarik adalah bahwa penghitungan ulang nilai tidak terjadi jika dihitung saat ini tidak terlibat dalam rendering (yang menghemat sumber daya). Oleh karena itu, meskipun mempertahankan nilai ketergantungan konstan, dihitung dapat dihitung ulang (ada cara untuk secara eksplisit memberitahu mobx untuk menyimpan nilai yang dihitung).


 // TodoListState.ts import { action as a, observable as o, computed as c } from 'mobx'; import { ITodoItem, TodoItemState } from 'components/TodoItem'; export enum TCurrentView { completed, active, all, } export class TodoListState { @o public currentView: TCurrentView = TCurrentView.all; @o private _todos: TodoItemState[] = []; @c public get todos(): TodoItemState[] { switch (this.currentView) { case TCurrentView.active: return this.activeTodos; case TCurrentView.completed: return this.completedTodos; default: return this._todos; } } @c public get completedTodos() { return this._todos.filter(t => t.value.completed); } @c public get activeTodos() { return this._todos.filter(t => !t.value.completed); } @a public setTodos(todos: ITodoItem[]) { this._todos = todos.map(t => new TodoItemState(t)); } @a public addTodo = (todo: ITodoItem) => { this._todos.push(new TodoItemState(todo)); }; @a public removeTodo = (id: string): boolean => { const index = this._todos.findIndex(todo => todo.value.id === id); if (index === -1) return false; this._todos.splice(index, 1); return true; }; } 

Daftar todo akses terbuka hanya melalui bidang yang dihitung, di mana, tergantung pada mode tampilan, set data yang diperlukan yang disaring dikembalikan (selesai, aktif atau semua todo). Dependensi todo menentukan bidang completeTodos yang dihitung, activeTodos yang dihitung, dan private _todos yang dapat diamati.


Pertimbangkan komponen utama Aplikasi. Itu membuat formulir untuk menambahkan todo baru dan daftar todo. Sebuah instance dari negara AppSate utama dibuat secara instan.


 // App.tsx import React from 'react'; import { observer } from 'mobx-react'; import { TodoList, initialTodos } from 'components/TodoList'; import { AddTodo } from 'components/AddTodo'; import { AppState } from './AppState'; import classes from './App.module.scss'; export interface IAppProps {} @observer export class App extends React.Component<IAppProps> { private appState = new AppState(); constructor(props: IAppProps) { super(props); this.appState.todoList.setTodos(initialTodos); } render() { const { addTodo, todoList } = this.appState; return ( <div className={classes.root}> <div className={classes.container}> <AddTodo onAdd={addTodo} /> <TodoList todoListState={todoList} /> </div> </div> ); } } 

Bidang appState berisi turunan dari kelas TodoListState untuk menampilkan komponen TodoList dan metode untuk menambahkan todo baru, yang diteruskan ke komponen AddTodo.


 // AppState.ts import { action as a } from 'mobx'; import { TodoListState } from 'components/TodoList'; import { ITodoItem } from 'components/TodoItem'; export class AppState { public todoList = new TodoListState(); @a public addTodo = (value: string) => { const newTodo: ITodoItem = { id: Date.now().toString(), name: value, completed: false, }; this.todoList.addTodo(newTodo); }; } 

Komponen AddTodo memiliki status terisolasi. Tidak ada akses ke sana dari keadaan umum. Satu-satunya koneksi ke appState adalah melalui metode appState.addTodo saat mengirimkan formulir.
Untuk status komponen AddTodo, pustaka formstate digunakan, yang merupakan teman baik dengan ts dan mobx. Formstate memungkinkan Anda bekerja dengan nyaman dengan formulir, memvalidasi formulir, dan banyak lagi. Formulir hanya memiliki satu nama bidang yang diperlukan.


 // AddTodoState.ts import { FormState, FieldState } from 'formstate'; export class AddTodoState { // Create a field public name = new FieldState('').validators( val => !val && 'name is required' ); // Compose fields into a form public form = new FormState({ name: this.name, }); public onSubmit = async () => { // Validate all fields const res = await this.form.validate(); // If any errors you would know if (res.hasError) { console.error(this.form.error); return; } const name = this.name.$; this.form.reset(); return name; }; } 

Secara umum, tidak masuk akal untuk sepenuhnya menggambarkan perilaku semua komponen. Kode lengkapnya diberikan di sini .


Artikel ini menjelaskan upaya penulis untuk menulis kode sederhana, fleksibel, dan terstruktur yang mudah dipelihara. Bereaksi membagi UI menjadi komponen. Komponen menggambarkan kelas negara (masing-masing kelas dapat diuji secara terpisah). Contoh status dibuat baik di komponen itu sendiri atau di tingkat yang lebih tinggi, tergantung pada tugas. Cukup mudah, Anda bisa menentukan tipe bidang kelas dan tipe properti komponen berkat naskah. Berkat mobx, kita dapat, hampir tanpa terasa bagi pengembang, membuat komponen bereaksi bereaksi terhadap perubahan data.

Source: https://habr.com/ru/post/id462597/


All Articles