Skip to content

Latest commit

 

History

History
511 lines (375 loc) · 41.1 KB

README.md

File metadata and controls

511 lines (375 loc) · 41.1 KB

언어: English | Português | Chinese | Japanese | Korean

mobx.dart



pub package pub package pub package

Build Status Publish Coverage Status Netlify Status Mutable.ai Auto Wiki

Join the chat at https://discord.gg/dNHY52k

Dart 언어를 위한 MobX.

투명한 함수형 반응형 프로그래밍(TFRP, Transparent Functional Reactive Programming)을 사용하여 Dart 앱의 상태 관리를 강화합니다.

저희는 관리자를 찾고 있습니다. Discord 또는 GitHub 이슈에 문의하세요!

소개

MobX는 애플리케이션의 반응형 데이터를 UI와 간편하게 연결할 수 있는 상태 관리 라이브러리입니다. 이 연결은 완전히 자동으로 이루어지며 매우 자연스럽게 느껴집니다. 애플리케이션 개발자는 두 데이터를 동기화할 걱정 없이 UI(및 다른 곳)에서 어떤 리액티브 데이터를 사용해야 하는지에만 집중할 수 있습니다.

이것은 정말 마법은 아니지만, 무엇이(observables) 어디에서(reactions) 소비되고 있는지를 파악하고 자동으로 추적하는 스마트한 기능을 갖추고 있습니다. observables 이 변경되면 모든 reactions 이 다시 실행됩니다. 흥미로운 점은 이러한 반응이 단순한 콘솔 로그, 네트워크 호출, UI 재렌더링 등 무엇이든 될 수 있다는 것 입니다.

MobX는 자바스크립트 앱에 매우 효과적인 라이브러리였으며, 이번 Dart 언어 포팅은 동일한 수준의 생산성을 제공하는 것을 목표로 합니다.

후원자

우리는 후원자들에게 매우 감사하게 생각합니다. 덕분에 우리는 오픈소스 소프트웨어(OSS) 프로그램의 일부가 될 수 있었습니다. [후원하기]

과거 후원자

시작하기

MobX.dart 웹사이트의 시작하기 가이드를 따르세요.

더 깊이 알아보기

MobX에 대한 자세한 내용은 MobX 빠른 시작 가이드를 참조하세요. 이 책에서는 자바스크립트 버전의 MobX를 사용하지만, 개념은 Dart와 Flutter에 100% 적용할 수 있습니다.

핵심 개념

MobX Triad

MobX의 핵심에는 세 가지 중요한 개념이 있습니다: Observables, Actions, Reactions.

Observables

observables은 애플리케이션의 반응 상태를 나타냅니다. 단순한 스칼라부터 복잡한 객체 트리까지 다양합니다. 애플리케이션의 상태를 observables 트리로 정의하면 UI(또는 앱의 다른 observer)가 소비하는 reactive-state-tree 를 노출할 수 있습니다.

간단한 리액티브 카운터는 다음과 같은 observables로 표현됩니다:

import 'package:mobx/mobx.dart';

final counter = Observable(0);

클래스와 같은 더 복잡한 observables도 만들 수 있습니다.

class Counter {
  Counter() {
    increment = Action(_increment);
  }

  final _value = Observable(0);
  int get value => _value.value;

  set value(int newValue) => _value.value = newValue;
  Action increment;

  void _increment() {
    _value.value++;
  }
}

언뜻 보기에 이 코드는 상용구 코드처럼 보이지만 금방 지겨워질 수 있습니다! 그래서 위의 코드를 다음과 같이 대체할 수 있는 mobx_codegen 를 추가했습니다:

import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void increment() {
    value++;
  }
}

어노테이션을 사용하여 클래스의 observables 속성을 표시하는 것에 주목하세요. 예, 여기에는 헤더 상용구가 있지만 모든 클래스에 대해 고정되어 있습니다. 더 복잡한 클래스를 만들면 이 상용구는 사라지고 대부분 중괄호 안의 코드에 집중하게 될 것입니다.

참고: 어노테이션은 mobx_codegen 패키지를 통해 사용할 수 있습니다.

readonly

코드를 줄이려면 @observable@readonly로 바꿀 수 있습니다.

모든 비공개 변수에 대해 스토어 클라이언트에서 값을 변경할 수 없도록 공개 getter를 생성합니다. 자세한 내용은 여기를 참조하세요.

Computed Observables

도출할 수 있는 것은 반드시 도출해야 합니다. 자동으로.

애플리케이션의 상태는 핵심 상태(core-state)파생 상태(derived-state) 로 구성됩니다. 핵심 상태(core-state) 는 현재 다루고 있는 도메인에 고유한 상태입니다. 예를 들어, Contact 엔티티가 있는 경우 firstNamelastNameContactcore-state 를 구성합니다. 그러나 fullNamefirstNamelastName 을 결합하여 얻은 파생 상태(derived-state) 입니다.

core-state 또는 other derived-state 에 의존하는 이러한 derived stateComputed Observable 이라고 합니다. observables이 변경되면 자동으로 동기화 상태를 유지합니다.

MobX의 상태 = 핵심 상태 + 파생 상태

import 'package:mobx/mobx.dart';

part 'contact.g.dart';

class Contact = ContactBase with _$Contact;

abstract class ContactBase with Store {
  @observable
  String firstName;

  @observable
  String lastName;

  @computed
  String get fullName => '$firstName, $lastName';

}

위의 예에서 firstName 및/또는 lastName이 변경되면 fullName이 자동으로 동기화됩니다.

Actions

action은 observables을 변경하는 방법입니다. 액션은 직접 변경하는 대신 변화에 의미론적 의미를 추가합니다. 예를 들어, 단순히 value+ 를 실행하는 대신 increment() action을 실행하면 더 많은 의미를 전달할 수 있습니다. 또한, action은 모든 알림을 일괄 처리하여 변경이 완료된 후에만 알림을 받도록 합니다. 따라서 observer들은 action이 원자적으로 완료될 때만 알림을 받습니다.

action은 중첩될 수도 있으며, 이 경우 최상위 action이 완료되면 알림이 발송됩니다.

final counter = Observable(0);

final increment = Action((){
  counter.value++;
});

클래스 내에서 action을 만들 때 어노테이션을 활용할 수 있습니다!

import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void increment() {
    value++;
  }
}

Asynchronous Actions

MobX.dart는 비동기 동작을 자동으로 처리하며 runInAction로 코드를 래핑할 필요가 없습니다.

@observable
String stuff = '';

@observable
bool loading = false;

@action
Future<void> loadStuff() async {
  loading = true; //This notifies observers
  stuff = await fetchStuff();
  loading = false; //This also notifies observers
}

Reactions

reaction은 observables, actions, reactionsMobX triad 를 완성합니다. 이들은 반응형 시스템의 observer이며, 추적하는 observable이 변경될 때마다 알림을 받습니다. 변경될 때마다 알림을 받습니다. reaction은 아래와 같이 몇 가지 종류가 있습니다. 이들 모두는 reaction을 삭제(dispose)기 위해 호출할 수 있는 함수인 ReactionDisposer를 반환합니다.

reaction의 눈에 띄는 특징 중 하나는 명시적인 연결 없이 모든 observable을 자동으로 추적 한다는 것입니다. reaction 내에서 observable을 읽는 행위만으로도 충분히 추적할 수 있습니다!

MobX로 작성하는 코드는 말 그대로 의식이 없는 것처럼 보입니다!

ReactionDisposer autorun(Function(Reaction) fn)

Runs the reaction immediately and also on any change in the observables used inside fn.

import 'package:mobx/mobx.dart';

final greeting = Observable('Hello World');

final dispose = autorun((_){
  print(greeting.value);
});

greeting.value = 'Hello MobX';

// Done with the autorun()
dispose();


// Prints:
// Hello World
// Hello MobX

ReactionDisposer reaction<T>(T Function(Reaction) predicate, void Function(T) effect)

predicate() 함수 내에서 사용되는 observables를 모니터링하고, predicate() 가 다른 값을 반환하면 effect()를 실행합니다. predicate() 내부의 observables만 추적됩니다.

import 'package:mobx/mobx.dart';

final greeting = Observable('Hello World');

final dispose = reaction((_) => greeting.value, (msg) => print(msg));

greeting.value = 'Hello MobX'; // Cause a change

// Done with the reaction()
dispose();


// Prints:
// Hello MobX

ReactionDisposer when(bool Function(Reaction) predicate, void Function() effect)

whenpredicate() 내부에 사용된 observables를 관찰하고 true를 반환할 때 effect()를 실행합니다. effect()가 실행된 후에는 when가 자동으로 폐기됩니다. 따라서 when일회성 reaction으로 생각할 수 있습니다. 또한 when()을 미리 폐기할 수도 있습니다.

import 'package:mobx/mobx.dart';

final greeting = Observable('Hello World');

final dispose = when((_) => greeting.value == 'Hello MobX', () => print('Someone greeted MobX'));

greeting.value = 'Hello MobX'; // Causes a change, runs effect and disposes


// Prints:
// Someone greeted MobX

Future<void> asyncWhen(bool Function(Reaction) predicate)

when과 비슷하지만 Future를 반환합니다. 이는 predicate()true 를 반환할 때 완료됩니다. 이는 predicate()true가 될 때까지 기다릴 수 있는 편리한 방법입니다.

final completed = Observable(false);

void waitForCompletion() async {
  await asyncWhen(() => _completed.value == true);

  print('Completed');
}

Observer

앱에서 가장 시각적으로 반응하는 부분 중 하나는 UI입니다. Observer 위젯([flutter_mobx]https://github.com/mobxjs/mobx.dart/tree/master/flutter_mobx) 패키지의 일부인)은 builder 함수에서 사용되는 observables에 대한 세분화된 observer를 제공합니다. 이러한 observables가 변경될 때마다 Observer는 다시 빌드하고 렌더링합니다.

아래는 Counter 예제 전체입니다.

import 'package:flutter/material.dart';
import 'package:flutter_mobx/flutter_mobx.dart';
import 'package:mobx/mobx.dart';

part 'counter.g.dart';

class Counter = CounterBase with _$Counter;

abstract class CounterBase with Store {
  @observable
  int value = 0;

  @action
  void increment() {
    value++;
  }
}

class CounterExample extends StatefulWidget {
  const CounterExample({Key key}) : super(key: key);

  @override
  _CounterExampleState createState() => _CounterExampleState();
}

class _CounterExampleState extends State<CounterExample> {
  final _counter = Counter();

  @override
  Widget build(BuildContext context) => Scaffold(
        appBar: AppBar(
          title: const Text('Counter'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              const Text(
                'You have pushed the button this many times:',
              ),
              Observer(
                  builder: (_) => Text(
                        '${_counter.value}',
                        style: const TextStyle(fontSize: 20),
                      )),
            ],
          ),
        ),
        floatingActionButton: FloatingActionButton(
          onPressed: _counter.increment,
          tooltip: 'Increment',
          child: const Icon(Icons.add),
        ),
      );
}

기여하기

여기까지 읽으셨다면 🎉🎉🎉. MobX.dart의 성장하는 커뮤니티에 기여할 수 있는 몇 가지 방법이 있습니다.

  • "good first issue"로 표시된 issue를 선택합니다
  • 기능, 개선 사항 제안하기
  • 버그 신고하기
  • 버그 수정하기
  • 토론에 참여하여 의사 결정에 도움 주기
  • 문서를 작성하고 개선하세요. 문서화는 매우 중요하며 그 중요성은 아무리 강조해도 지나치지 않습니다!
  • 풀 리퀘스트 보내기 :-)
  • Join the chat at https://discord.gg/dNHY52k에서 채팅에 참여하세요

기여자 ✨

All Contributors

Thanks goes to these wonderful people (emoji key):

Pavan Podila
Pavan Podila

💻 📖 👀
katis
katis

💻 🤔 👀 ⚠️
Scott Hyndman
Scott Hyndman

💻 🤔 👀 ⚠️
Michael Bui
Michael Bui

💻 📖 👀 💡
Remi Rousselet
Remi Rousselet

💻 📖 👀
adiaKhaitan
adiaKhaitan

📖
Jacob Moura
Jacob Moura

💻 📖 🌍
Daniel Albuquerque
Daniel Albuquerque

🌍
Marco Scannadinari
Marco Scannadinari

📖
lsaudon
lsaudon

💻 📖
Efthymis Sarmpanis
Efthymis Sarmpanis

💻
Giri Jeedigunta
Giri Jeedigunta

📖 💡
Hebri Ramnath Nayak
Hebri Ramnath Nayak

📖
Robert Brunhage
Robert Brunhage

📖
Brady Trainor
Brady Trainor

📖
Kushagra Saxena
Kushagra Saxena

📖 💡
Pedro Massango
Pedro Massango

🌍
Peter Czibik
Peter Czibik

💻
Luan Nico
Luan Nico

📖
Kobi
Kobi

💻
Ryan
Ryan

📖
Ivan Terekhin
Ivan Terekhin

💻
Yoav Rofé
Yoav Rofé

📖
Mateusz Wojtczak
Mateusz Wojtczak

📖
Timur Artikov
Timur Artikov

💻
Saurabh Sohoni
Saurabh Sohoni

📖
renanzdm
renanzdm

📖
Rachman Chavik
Rachman Chavik

💻
Nathan Cabasso
Nathan Cabasso

🐛 💻
geisterfurz007
geisterfurz007

📖 🖋
Romuald Barbe
Romuald Barbe

💻
Alexander Mazuruk
Alexander Mazuruk

💡
Alberto Bonacina
Alberto Bonacina

📖
Roland Ibragimov
Roland Ibragimov

📖
zyzhao
zyzhao

📖
Xinhai Wang
Xinhai Wang

📖
Henry Mayer
Henry Mayer

💻 ⚠️
Sergey
Sergey

💻 ⚠️
Jason Rai
Jason Rai

📖
Joshua de Guzman
Joshua de Guzman

💡
Jan Hertlein
Jan Hertlein

📖
Evo Stamatov
Evo Stamatov

💻
Davi Eduardo
Davi Eduardo

📖
Leonardo Custodio
Leonardo Custodio

💻 📖
Prince Srivastava
Prince Srivastava

💡 💻
Muhammad Muhajir
Muhammad Muhajir

📖
D
D

📖
David Martos
David Martos

💻
Issa Nimaga
Issa Nimaga

📖
Ascênio
Ascênio

💻 📖
Alex Isaienko
Alex Isaienko

💻
Moritz Weber
Moritz Weber

💻
Carter Snook
Carter Snook

📖
Brian Robles
Brian Robles

💻 ⚠️
harrypunk
harrypunk

📖
Ikko Ashimine
Ikko Ashimine

📖
amond
amond

💻 ⚠️ 👀 📖
fzyzcjy
fzyzcjy

💻 📖 👀
Vandad Nahavandipoor
Vandad Nahavandipoor

📖
Sergey Molchanovsky
Sergey Molchanovsky

💻
ko16a46
ko16a46

💻
Yatharth Chauhan
Yatharth Chauhan

📖
Parth Baraiya
Parth Baraiya

💻 🐛
Altynbek Aidarbekov
Altynbek Aidarbekov

💻
CpedniyNikon
CpedniyNikon

📖

이 프로젝트는 all-contributors 규정을 따릅니다. 모든 종류의 기여를 환영합니다!