Clean up exported apis and doc visibility (#977)

* Clean up exported apis and doc visibility

* Remove unused ScopeHolder

* Change ComponentLink to alias of Scope

* cargo fmt
This commit is contained in:
Justin Starry 2020-02-29 19:58:07 +08:00 committed by GitHub
parent d80e2f3e8a
commit b4d5227e62
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 138 additions and 156 deletions

View File

@ -312,7 +312,7 @@ cloned is when a wrapper component re-renders nested children components.
```rust
use stdweb::web::html_element::InputElement;
use stdweb::web::IHtmlElement;
use yew::*;
use yew::prelude::*;
pub struct Input {
node_ref: NodeRef,

View File

@ -124,7 +124,7 @@ impl ToTokens for HtmlComponent {
Props::List(list_props) => {
let set_props = list_props.props.iter().map(|HtmlProp { label, value }| {
quote_spanned! { value.span()=> .#label(
<::yew::virtual_dom::vcomp::VComp as ::yew::virtual_dom::Transformer<_, _>>::transform(
<::yew::virtual_dom::VComp as ::yew::virtual_dom::Transformer<_, _>>::transform(
#value
)
)}

View File

@ -52,7 +52,7 @@ impl ToTokens for HtmlList {
let children = &self.0;
tokens.extend(quote! {
::yew::virtual_dom::VNode::VList(
::yew::virtual_dom::vlist::VList::new_with_children({
::yew::virtual_dom::VList::new_with_children({
let mut v = ::std::vec::Vec::new();
#(v.extend(::yew::utils::NodeSeq::from(#children));)*
v

View File

@ -147,7 +147,7 @@ impl ToTokens for HtmlTag {
quote_spanned! {name.span()=> {
::yew::html::#name::Wrapper::new(
<::yew::virtual_dom::vtag::VTag as ::yew::virtual_dom::Transformer<_, _>>::transform(
<::yew::virtual_dom::VTag as ::yew::virtual_dom::Transformer<_, _>>::transform(
#callback
)
)
@ -155,7 +155,7 @@ impl ToTokens for HtmlTag {
});
tokens.extend(quote! {{
let mut #vtag = ::yew::virtual_dom::vtag::VTag::new(#name);
let mut #vtag = ::yew::virtual_dom::VTag::new(#name);
#(#set_kind)*
#(#set_value)*
#(#add_href)*

View File

@ -1,11 +1,11 @@
#![recursion_limit = "128"]
mod event_bus;
mod subscriber;
mod producer;
mod subscriber;
use subscriber::Subsciber;
use producer::Producer;
use subscriber::Subsciber;
use yew::{html, Component, ComponentLink, Html, ShouldRender};
pub struct Model {}

View File

@ -1,18 +1,16 @@
#![recursion_limit = "256"]
use yew::html::Scope;
/// This example demonstrates low-level usage of scopes.
use yew::{html, Component, ComponentLink, Html, ShouldRender};
pub struct Model {
link: ComponentLink<Self>,
scope: Option<Scope<Model>>,
opposite: Option<ComponentLink<Model>>,
selector: &'static str,
title: String,
}
pub enum Msg {
SetScope(Scope<Model>),
SetOpposite(ComponentLink<Model>),
SendToOpposite(String),
SetTitle(String),
}
@ -24,7 +22,7 @@ impl Component for Model {
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
Model {
link,
scope: None,
opposite: None,
selector: "",
title: "Nothing".into(),
}
@ -32,37 +30,27 @@ impl Component for Model {
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::SetScope(scope) => {
self.scope = Some(scope);
Msg::SetOpposite(opposite) => {
self.opposite = Some(opposite);
}
Msg::SendToOpposite(title) => {
self.scope
self.opposite
.as_mut()
.unwrap()
.send_message(Msg::SetTitle(title));
}
Msg::SetTitle(title) => {
match title.as_ref() {
"Ping" => {
self.scope
.as_mut()
.unwrap()
.send_message(Msg::SetTitle("Pong".into()));
}
"Pong" => {
self.scope
.as_mut()
.unwrap()
.send_message(Msg::SetTitle("Pong Done".into()));
}
"Pong Done" => {
self.scope
.as_mut()
.unwrap()
.send_message(Msg::SetTitle("Ping Done".into()));
}
_ => {}
let send_msg = match title.as_ref() {
"Ping" => Some(Msg::SetTitle("Pong".into())),
"Pong" => Some(Msg::SetTitle("Pong Done".into())),
"Pong Done" => Some(Msg::SetTitle("Ping Done".into())),
_ => None,
};
if let Some(send_msg) = send_msg {
self.opposite.as_mut().unwrap().send_message(send_msg);
}
self.title = title;
}
}

View File

@ -1,18 +1,16 @@
#![recursion_limit = "256"]
use yew::html::Scope;
/// This example demonstrates low-level usage of scopes.
use yew::{html, Component, ComponentLink, Html, ShouldRender};
pub struct Model {
link: ComponentLink<Self>,
scope: Option<Scope<Model>>,
opposite: Option<ComponentLink<Model>>,
selector: &'static str,
title: String,
}
pub enum Msg {
SetScope(Scope<Model>),
SetOpposite(ComponentLink<Model>),
SendToOpposite(String),
SetTitle(String),
}
@ -24,7 +22,7 @@ impl Component for Model {
fn create(_: Self::Properties, link: ComponentLink<Self>) -> Self {
Model {
link,
scope: None,
opposite: None,
selector: "",
title: "Nothing".into(),
}
@ -32,37 +30,27 @@ impl Component for Model {
fn update(&mut self, msg: Self::Message) -> ShouldRender {
match msg {
Msg::SetScope(scope) => {
self.scope = Some(scope);
Msg::SetOpposite(opposite) => {
self.opposite = Some(opposite);
}
Msg::SendToOpposite(title) => {
self.scope
self.opposite
.as_mut()
.unwrap()
.send_message(Msg::SetTitle(title));
}
Msg::SetTitle(title) => {
match title.as_ref() {
"Ping" => {
self.scope
.as_mut()
.unwrap()
.send_message(Msg::SetTitle("Pong".into()));
}
"Pong" => {
self.scope
.as_mut()
.unwrap()
.send_message(Msg::SetTitle("Pong Done".into()));
}
"Pong Done" => {
self.scope
.as_mut()
.unwrap()
.send_message(Msg::SetTitle("Ping Done".into()));
}
_ => {}
let send_msg = match title.as_ref() {
"Ping" => Some(Msg::SetTitle("Pong".into())),
"Pong" => Some(Msg::SetTitle("Pong Done".into())),
"Pong Done" => Some(Msg::SetTitle("Ping Done".into())),
_ => None,
};
if let Some(send_msg) = send_msg {
self.opposite.as_mut().unwrap().send_message(send_msg);
}
self.title = title;
}
}

View File

@ -31,7 +31,7 @@ cfg_if! {
/// Serializable messages to worker
#[derive(Serialize, Deserialize, Debug)]
pub enum ToWorker<T> {
enum ToWorker<T> {
/// Client is connected
Connected(HandlerId),
/// Incoming message to Worker
@ -44,7 +44,7 @@ pub enum ToWorker<T> {
/// Serializable messages sent by worker to consumer
#[derive(Serialize, Deserialize, Debug)]
pub enum FromWorker<T> {
enum FromWorker<T> {
/// Worker sends this message when `wasm` bundle has loaded.
WorkerLoaded,
/// Outgoing message to consumer

View File

@ -1,7 +1,7 @@
//! This module contains the `App` struct, which is used to bootstrap
//! a component in an isolated scope.
use crate::html::{Component, NodeRef, Scope};
use crate::html::{Component, ComponentLink, NodeRef, Scope};
use crate::utils::document;
use cfg_if::cfg_if;
cfg_if! {
@ -38,7 +38,7 @@ where
/// which will update the state of the model and a `view` function which
/// will render the model to a virtual DOM tree. If you would like to pass props,
/// use the `mount_with_props` method.
pub fn mount(self, element: Element) -> Scope<COMP> {
pub fn mount(self, element: Element) -> ComponentLink<COMP> {
clear_element(&element);
self.scope.mount_in_place(
element,
@ -49,7 +49,7 @@ where
}
/// Alias to `mount("body", ...)`.
pub fn mount_to_body(self) -> Scope<COMP> {
pub fn mount_to_body(self) -> ComponentLink<COMP> {
// Bootstrap the component for `Window` environment only (not for `Worker`)
let element = document()
.query_selector("body")
@ -62,7 +62,7 @@ where
/// element at the root of the HTML generated by its `view` method. Use this method when you
/// need to manipulate the body element. For example, adding/removing app-wide
/// CSS classes of the body element.
pub fn mount_as_body(self) -> Scope<COMP> {
pub fn mount_as_body(self) -> ComponentLink<COMP> {
let html_element = document()
.query_selector("html")
.expect("can't get html node for rendering")
@ -97,14 +97,18 @@ where
/// similarly to the `program` function in Elm. You should provide an initial model, `update`
/// function which will update the state of the model and a `view` function which
/// will render the model to a virtual DOM tree.
pub fn mount_with_props(self, element: Element, props: COMP::Properties) -> Scope<COMP> {
pub fn mount_with_props(
self,
element: Element,
props: COMP::Properties,
) -> ComponentLink<COMP> {
clear_element(&element);
self.scope
.mount_in_place(element, None, NodeRef::default(), props)
}
/// Alias to `mount_with_props("body", ...)`.
pub fn mount_to_body_with_props(self, props: COMP::Properties) -> Scope<COMP> {
pub fn mount_to_body_with_props(self, props: COMP::Properties) -> ComponentLink<COMP> {
// Bootstrap the component for `Window` environment only (not for `Worker`)
let element = document()
.query_selector("body")
@ -117,7 +121,7 @@ where
/// has a body element at the root of the HTML generated by its `view` method. Use this method
/// when you need to manipulate the body element. For example, adding/removing app-wide
/// CSS classes of the body element.
pub fn mount_as_body_with_props(self, props: COMP::Properties) -> Scope<COMP> {
pub fn mount_as_body_with_props(self, props: COMP::Properties) -> ComponentLink<COMP> {
let html_element = document()
.query_selector("html")
.expect("can't get html node for rendering")

View File

@ -1,6 +1,8 @@
//! This module contains useful components.
//! At this moment it includes typed `Select` only.
#[doc(hidden)]
pub mod select;
#[doc(inline)]
pub use self::select::Select;

View File

@ -8,32 +8,58 @@ use anyhow::Error;
use thiserror::Error as ThisError;
#[macro_use]
pub mod macros;
mod macros;
#[cfg(feature = "bincode")]
#[doc(hidden)]
pub mod bincode;
#[cfg(feature = "cbor")]
#[doc(hidden)]
pub mod cbor;
#[doc(hidden)]
pub mod json;
#[doc(hidden)]
#[cfg(feature = "msgpack")]
pub mod msgpack;
#[doc(hidden)]
pub mod nothing;
#[cfg(feature = "toml")]
#[doc(hidden)]
pub mod toml;
#[cfg(feature = "yaml")]
#[doc(hidden)]
pub mod yaml;
#[cfg(feature = "bincode")]
#[doc(inline)]
pub use self::bincode::Bincode;
#[cfg(feature = "cbor")]
#[doc(inline)]
pub use self::cbor::Cbor;
#[doc(inline)]
pub use self::json::Json;
#[cfg(feature = "msgpack")]
#[doc(inline)]
pub use self::msgpack::MsgPack;
#[doc(inline)]
pub use self::nothing::Nothing;
#[cfg(feature = "toml")]
#[doc(inline)]
pub use self::toml::Toml;
#[cfg(feature = "yaml")]
#[doc(inline)]
pub use self::yaml::Yaml;
/// A representation of a value which can be stored and restored as a text.

View File

@ -5,6 +5,7 @@ macro_rules! impl_action {
)*};
($($action:ident(name: $name:literal, event: $type:ident) -> $ret:ty => $convert:expr)*) => {$(
/// An abstract implementation of a listener.
#[doc(hidden)]
pub mod $action {
use cfg_if::cfg_if;
use cfg_match::cfg_match;

View File

@ -7,8 +7,8 @@ mod listener;
mod scope;
pub use listener::*;
pub use scope::Scope;
pub(crate) use scope::{ComponentUpdate, HiddenScope};
pub use scope::{Scope, ScopeHolder};
use crate::callback::Callback;
use crate::virtual_dom::{VChild, VList, VNode};
@ -287,7 +287,7 @@ where
/// use stdweb::web::{html_element::InputElement, IHtmlElement};
/// #[cfg(feature = "web_sys")]
/// use web_sys::HtmlInputElement as InputElement;
///# use yew::*;
///# use yew::prelude::*;
///
/// pub struct Input {
/// node_ref: NodeRef,
@ -384,6 +384,7 @@ pub trait Properties: Clone {
/// Builder for when a component has no properties
#[derive(Debug)]
#[doc(hidden)]
pub struct EmptyBuilder;
impl Properties for () {
@ -400,78 +401,7 @@ impl EmptyBuilder {
}
/// Link to component's scope for creating callbacks.
pub struct ComponentLink<COMP: Component> {
scope: Scope<COMP>,
}
impl<COMP> ComponentLink<COMP>
where
COMP: Component,
{
/// Create link for a scope.
fn connect(scope: &Scope<COMP>) -> Self {
ComponentLink {
scope: scope.clone(),
}
}
/// This method creates a `Callback` which will send a batch of messages back to the linked
/// component's update method when called.
pub fn batch_callback<F, IN>(&self, function: F) -> Callback<IN>
where
F: Fn(IN) -> Vec<COMP::Message> + 'static,
{
let scope = self.scope.clone();
let closure = move |input| {
let messages = function(input);
scope.send_message_batch(messages);
};
closure.into()
}
/// This method creates a `Callback` which will send a message to the linked component's
/// update method when invoked.
pub fn callback<F, IN>(&self, function: F) -> Callback<IN>
where
F: Fn(IN) -> COMP::Message + 'static,
{
let scope = self.scope.clone();
let closure = move |input| {
let output = function(input);
scope.send_message(output);
};
closure.into()
}
/// This method sends a message to this component to be processed immediately after the
/// component has been updated and/or rendered.
pub fn send_message(&self, msg: COMP::Message) {
self.scope.send_message(msg);
}
/// Sends a batch of messages to the component to be processed immediately after
/// the component has been updated and/or rendered..
///
/// All messages will first be processed by `update`, and if _any_ of them return `true`,
/// then re-render will occur.
pub fn send_message_batch(&self, msgs: Vec<COMP::Message>) {
self.scope.send_message_batch(msgs)
}
}
impl<COMP: Component> fmt::Debug for ComponentLink<COMP> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.write_str("ComponentLink<_>")
}
}
impl<COMP: Component> Clone for ComponentLink<COMP> {
fn clone(&self) -> Self {
ComponentLink {
scope: self.scope.clone(),
}
}
}
pub type ComponentLink<COMP> = Scope<COMP>;
/// A bridging type for checking `href` attribute value.
#[derive(Debug)]

View File

@ -23,9 +23,6 @@ pub(crate) enum ComponentUpdate<COMP: Component> {
Properties(COMP::Properties),
}
/// A reference to the parent's scope which will be used later to send messages.
pub type ScopeHolder<PARENT> = Rc<RefCell<Option<Scope<PARENT>>>>;
/// A context which allows sending messages to a component.
pub struct Scope<COMP: Component> {
shared_state: Shared<ComponentState<COMP>>,
@ -67,11 +64,10 @@ impl<COMP: Component> Scope<COMP> {
props: COMP::Properties,
) -> Scope<COMP> {
let mut scope = self;
let link = ComponentLink::connect(&scope);
let ready_state = ReadyState {
element,
node_ref,
link,
scope: scope.clone(),
props,
ancestor,
};
@ -120,6 +116,34 @@ impl<COMP: Component> Scope<COMP> {
pub fn send_message_batch(&self, messages: Vec<COMP::Message>) {
self.update(ComponentUpdate::MessageBatch(messages));
}
/// This method creates a `Callback` which will send a message to the linked component's
/// update method when invoked.
pub fn callback<F, IN>(&self, function: F) -> Callback<IN>
where
F: Fn(IN) -> COMP::Message + 'static,
{
let scope = self.clone();
let closure = move |input| {
let output = function(input);
scope.send_message(output);
};
closure.into()
}
/// This method creates a `Callback` which will send a batch of messages back to the linked
/// component's update method when called.
pub fn batch_callback<F, IN>(&self, function: F) -> Callback<IN>
where
F: Fn(IN) -> Vec<COMP::Message> + 'static,
{
let scope = self.clone();
let closure = move |input| {
let messages = function(input);
scope.send_message_batch(messages);
};
closure.into()
}
}
enum ComponentState<COMP: Component> {
@ -147,14 +171,14 @@ struct ReadyState<COMP: Component> {
element: Element,
node_ref: NodeRef,
props: COMP::Properties,
link: ComponentLink<COMP>,
scope: Scope<COMP>,
ancestor: Option<VNode>,
}
impl<COMP: Component> ReadyState<COMP> {
fn create(self) -> CreatedState<COMP> {
CreatedState {
component: COMP::create(self.props, self.link),
component: COMP::create(self.props, self.scope),
element: self.element,
last_frame: self.ancestor,
node_ref: self.node_ref,

View File

@ -88,7 +88,7 @@ pub mod callback;
pub mod components;
pub mod format;
pub mod html;
pub mod scheduler;
mod scheduler;
pub mod utils;
pub mod virtual_dom;

View File

@ -15,15 +15,24 @@ pub mod storage;
pub mod timeout;
pub mod websocket;
#[doc(inline)]
pub use self::console::ConsoleService;
#[doc(inline)]
pub use self::dialog::DialogService;
pub use self::fetch::FetchService;
#[doc(inline)]
pub use self::interval::IntervalService;
#[doc(inline)]
pub use self::reader::ReaderService;
#[doc(inline)]
pub use self::render::RenderService;
#[doc(inline)]
pub use self::resize::ResizeService;
#[doc(inline)]
pub use self::storage::StorageService;
#[doc(inline)]
pub use self::timeout::TimeoutService;
#[doc(inline)]
pub use self::websocket::WebSocketService;
use std::time::Duration;

View File

@ -1,9 +1,14 @@
//! This module contains the implementation of reactive virtual dom concept.
#[doc(hidden)]
pub mod vcomp;
#[doc(hidden)]
pub mod vlist;
#[doc(hidden)]
pub mod vnode;
#[doc(hidden)]
pub mod vtag;
#[doc(hidden)]
pub mod vtext;
use cfg_if::cfg_if;
@ -21,10 +26,15 @@ cfg_if! {
}
}
#[doc(inline)]
pub use self::vcomp::{VChild, VComp};
#[doc(inline)]
pub use self::vlist::VList;
#[doc(inline)]
pub use self::vnode::VNode;
#[doc(inline)]
pub use self::vtag::VTag;
#[doc(inline)]
pub use self::vtext::VText;
/// `Listener` trait is an universal implementation of an event listener
@ -180,7 +190,7 @@ enum Reform {
// `Ace` editor embedding for example?
/// This trait provides features to update a tree by calculating a difference against another tree.
pub trait VDiff {
pub(crate) trait VDiff {
/// Remove itself from parent and return the next sibling.
fn detach(&mut self, parent: &Element) -> Option<Node>;