首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用Rust和Yew实现一个重要的应用程序导航?

如何使用Rust和Yew实现一个重要的应用程序导航?
EN

Stack Overflow用户
提问于 2019-09-06 06:02:06
回答 1查看 1.2K关注 0票数 2

我正在尝试构建一个带有导航选项卡的应用程序,并试图使用最好的方式给整个应用程序提供状态。目前,标签是功能性的,但我正在努力实现一种方法,以实现地图和恢复标签导航通过生锈状态使用Yew前端单页应用程序框架。如何将这些选项卡及其各自的上下文部分链接到状态?

github上的源文件:

我的目标是:

使用Rust和Yew机箱.实现有状态的选项卡导航

我已经设置了一个toggle_tab函数,它使用STDweb库通过tabcontentset attribute ("style", "display: none;")类迭代现有的HTML。然后,我根据唯一的类名进行匹配(通过函数输入,并从退出的onclick调用)。

Yew关于Github的例子中,我知道我可能需要将存储实现为状态,将状态实现为模型。用Yew & Rust实现应用导航的好方法是什么?

HTML和Toggle函数:

代码语言:javascript
复制
impl Renderable<Model> for Model {
    fn view(&self) -> Html<Self> {
        html! {
    <>
        <nav class="tab grey lighten-2">
            <div class="nav-wrapper">
                // BUTTONS
                <ul class="row">
                    <div class="col s1" >
                    <button class="tablinks brand-logo welcome " onclick=|e| toggle_tab(e, ".welcome")>{"Welcome"}</button>
                    </div>
                    <div class="col s1 push-s1" >
                    <button class="tablinks brand-logo home active" onclick=|e| toggle_tab(e, ".home")>{"Home"}</button>
                    </div>
                </ul>
            </div>
        </nav>
        //SNIPPETS
        <div class="tabcontent white welcome content" >
                <Welcome/>
        </div>
        <div class="tabcontent white home content" style="display: block;">
//        <HomeTabs/>
        </div>
    </>
                        }
    }
}


fn toggle_tab(event: ClickEvent, tab_unique_class_name: &str) {
    use crate::stdweb::web::{IElement, IParentNode, INonElementParentNode};

    // Get all elements with class="tabcontent" and hide them
    for tab in document().query_selector_all(".tabcontent").unwrap() {
        let tab: Element = tab.try_into().unwrap();
        tab.set_attribute("style", "display: none;").unwrap();
    }

    // Get all elements with class="tablinks" and remove the class "active"
    for tab in document().query_selector_all(".tablinks").unwrap() {
        let tab: Element = tab.try_into().unwrap();
        tab.class_list().remove("active");
    }

    let matching_tabs = document().query_selector_all(tab_unique_class_name).unwrap();

    match tab_unique_class_name {
        ".welcome" => {
            for elem in matching_tabs.iter() {
                let elem: Element = elem.try_into().unwrap();
                elem.class_list().add("active");
                elem.set_attribute("style", "display: block");
            }
        }
        ".home" => {
            for elem in matching_tabs.iter() {
                let elem: Element = elem.try_into().unwrap();
                elem.class_list().add("active");
                elem.set_attribute("style", "display: block");
                document().get_element_by_id("dashboard").unwrap().set_attribute("style", "display: block;");
            }
        }
        ".campaign" => {
            for elem in matching_tabs.iter() {
                let elem: Element = elem.try_into().unwrap();
                elem.class_list().add("active");
                elem.set_attribute("style", "display: block");
            }
        }
        ".comming_soon" => {
            for elem in matching_tabs.iter() {
                let elem: Element = elem.try_into().unwrap();
                elem.class_list().add("active");
                elem.set_attribute("style", "display: block");
            }
        }
        _ => alert("Catchall WHoahw!"),
    }
}

源代码

如果看到更多的代码有帮助,我在这里上传了当前的源代码,1.rs

这是非常重要的,你的任何指导都是非常感谢的。

app外观

切换选项卡功能

Html代码

模型,状态,Msg,过滤器

我意识到这是一个相当抽象和冗长的问题,因此如果取得任何进展,我将在此更新。

EN

回答 1

Stack Overflow用户

发布于 2019-09-09 04:27:19

Yew Gitter的回答;

@健壮--系统(不看提供的其他源代码,只查看在SO帖子中可见的代码)我的建议是发出一条消息,其中包含一个枚举,表示您想要选择的选项卡,而不是运行toggle_tab。您可以在update中处理此消息,并将枚举存储为模型的一部分,指示哪个是活动的。从这里来看,在模型中利用这个状态的一种方法是创建一个很小的html片段,您可以将它们缝合在一起。例如:

代码语言:javascript
复制
let welcome_button = if let Tab::Welcome = self.active_tab {
    html!{
        <button class="tablinks brand-logo welcome active " onclick=self.link.callback(|_| Message::ChangeTab(Tab::Welcome))>{"Welcome"}</button>
    }
} else {
    html!{
        <button class="tablinks brand-logo welcome " onclick=self.link.callback(|_| Message::ChangeTab(Tab::Welcome))>{"Welcome"}</button>
    }
};

然后在你的大html!块,插入“欢迎”按钮,如

代码语言:javascript
复制
<ul class="row">
    <div class="col s1" >
    {welcome_button}
   ...

思考

现在如何发出msg和发送到哪里,我将在yew页面上破解自定义组件示例。*将在应用程序完全有状态时编辑此答案。

更新

我终于完全有状态了!以下是为任何碰巧发现它有用的人生成的代码。

我必须匹配一个ChangeTab(Tab)消息,并将模型中的active_tab字段保存到本地存储,然后使用一个if来恢复active_tab。

代码语言:javascript
复制
use crate::button_welcome::WelcomeButton;
use crate::button_home::HomeButton;
use crate::button_comming_soon::CommingSoon;
use crate::button_debug_panel::DebugButton;

use serde_derive::{Deserialize, Serialize};

use yew::prelude::*;
use yew::services::storage::{StorageService, Area};
use yew::format::Json;
use crate::tab_navigation::Tab::Home;
use std::sync::atomic::Ordering::AcqRel;

const RESTORE_KEY: &'static str = "tab_navigation";

pub struct TabNavigation {
    active_tab: Tab,
    storage: StorageService,
}

pub enum Msg {
    ChangeTab(Tab),
}

#[derive(Serialize, Deserialize)]
pub enum Tab {
    Welcome,
    Home,
    CommingSoon,
    Debug,
}

impl Default for Tab {
    fn default() -> Self {
        Tab::Home
    }
}

impl Component for TabNavigation {
    type Message = Msg;
    type Properties = ();

    fn create(props: Self::Properties, _: ComponentLink<Self>) -> Self {
        let storage = StorageService::new(Area::Local);
        let active_tab: Tab = {
            if let Json(Ok(active_tab)) = storage.restore(RESTORE_KEY) {
                active_tab
            } else {
                Tab::Home
            }
        };

        TabNavigation {
            storage: storage,
            active_tab: active_tab,
        }
    }

    fn update(&mut self, msg: Self::Message) -> ShouldRender {
        match msg {
            // active tab enum
            Msg::ChangeTab(tab_to_activate) => {
                match tab_to_activate {
                    Tab::Welcome => {
                        self.active_tab = Tab::Welcome
                    },
                    Tab::Home => {
                        self.active_tab = Tab::Home
                    },
                    Tab::CommingSoon => {
                        self.active_tab = Tab::CommingSoon
                    },
                    Tab::Debug => {
                        self.active_tab = Tab::Debug
                    }
                }
            }
        }
        self.storage.store(RESTORE_KEY, Json(&self.active_tab));
        true
    }

    fn change(&mut self, props: Self::Properties) -> ShouldRender {
//        if self.active_tab == Tab::Home
        true
    }
}

impl Renderable<TabNavigation> for TabNavigation {
    fn view(&self) -> Html<Self> {
        html! {
            // WELCOME
            let welcome_button = if let Tab::Welcome = self.active_tab {
                html! {
                    <WelcomeButton onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::Welcome)) title="Welcome" class="active" />
                    // INSERT SECTION HERE
                }
            } else {
                html! {
                    <WelcomeButton onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::Welcome)) title="Welcome" class="not-active" />
                }
            };
            // HOME
            let home_button = if let Tab::Home = self.active_tab {
                html! {
                    <HomeButton onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::Home)) title="Home" class="active" />
                }
            } else {
                html! {
                    <HomeButton onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::Home)) title="Home" class="not-active" />
                }
            };
            // COMMING SOON
            let comming_soon_button = if let Tab::CommingSoon = self.active_tab {
                html! {
                    <CommingSoon onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::CommingSoon)) title="Comming Soon" class="active" />
                }
            } else {
                html! {
                    <CommingSoon onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::CommingSoon)) title="Comming Soon" class="not-active" />
                }
            };
            // DEBUG
            let debug_button = if let Tab::Debug = self.active_tab {
                html! {
                    <DebugButton onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::Debug)) title="Debug" class="active" />
                }
            } else {
                html! {
                    <DebugButton onsignal=self.link.callback(|_| Msg::ChangeTab(Tab::Debug)) title="Debug" class="not-active" />
                }
            };

            html! {
            <>
                {welcome_button}
                {home_button}
                {comming_soon_button}
                {debug_button}
            </>
            }
        }
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/57816515

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档