0
use wasm_bindgen::prelude::*;
use yew::prelude::*;

#[wasm_bindgen]
extern "C" {
    #[wasm_bindgen(js_namespace = ["window", "__TAURI__", "tauri"])]
    async fn invoke(cmd: &str, args: JsValue) -> JsValue;

    #[wasm_bindgen(js_namespace = console)]
    fn log(s: &str);
}

#[function_component]
pub fn App() -> Html {
    let body = vec![
        "BodyCell1".to_owned(),
        "BodyCell2".to_owned(),
        "BodyCell3".to_owned(),
        "BodyCell4".to_owned(),
        "BodyCell5".to_owned(),
    ];

    let mut data = vec![];
    for _ in 0..2000 {
        data.push(body.clone());
    }
    html! {
        <TestTable {data}/>
    }
}

#[derive(PartialEq, Properties)]
pub struct TableProps {
    onwheel: Callback<TableMsg>,
    children: Children,
}

pub struct Table;

pub enum TableMsg {
    LoadNextPage,
}

impl Component for Table {
    type Message = ();
    type Properties = TableProps;

    fn create(ctx: &Context<Self>) -> Self {
        Self {}
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let onwheel = ctx.props().onwheel.reform(move |_| TableMsg::LoadNextPage);
        html! {
            <table {onwheel}>
            <thead>
                <tr>
                    <th>{""}</th>
                    <th>{"HeadCell1"}</th>
                    <th>{"HeadCell2"}</th>
                    <th>{"HeadCell3"}</th>
                    <th>{"HeadCell4"}</th>
                    <th>{"HeadCell5"}</th>
                </tr>
            </thead>
            <tbody>
                {for ctx.props().children.iter()}
            </tbody>
            </table>
        }
    }
}

pub struct TestTable {
    page: usize,
    per_page: usize,
    total: usize,
}

#[derive(PartialEq, Properties)]
pub struct TestTableProps {
    data: Vec<Vec<String>>,
}

impl Component for TestTable {
    type Message = TableMsg;
    type Properties = TestTableProps;

    fn create(ctx: &Context<Self>) -> Self {
        Self {
            page: 0,
            per_page: 16,
            total: ctx.props().data.len(),
        }
    }

    fn update(&mut self, ctx: &Context<Self>, msg: Self::Message) -> bool {
        match msg {
            TableMsg::LoadNextPage => {
                self.page += 1;
                if self.page > self.total / self.per_page {
                    self.page = 0;
                }
            }
        }
        true
    }

    fn view(&self, ctx: &Context<Self>) -> Html {
        let mut rows = vec![];
        for i in 0..self.per_page {
            let index = i + self.page * self.per_page;
            if index >= self.total {
                break;
            }
            rows.push(html! {
                <tr>
                    <td>{index}</td>
                    <td>{format!("{}--{}", ctx.props().data[index][0].to_owned(), index)}</td>
                    <td>{format!("{}--{}", ctx.props().data[index][1].to_owned(), index)}</td>
                    <td>{format!("{}--{}", ctx.props().data[index][2].to_owned(), index)}</td>
                    <td>{format!("{}--{}", ctx.props().data[index][3].to_owned(), index)}</td>
                    <td>{format!("{}--{}", ctx.props().data[index][4].to_owned(), index)}</td>
                </tr>
            });
        }

        html! {
            <Table onwheel={ctx.link().callback(|_|TableMsg::LoadNextPage)}>
            {for rows}
            </Table>
        }
    }
}

This code is a Rust implementation of a scrollable table component. The App function returns a TestTable component that takes a Vec<Vec> as its data. The TestTable component uses the Table component to render a table with a header and body. The Table component updates its state when the user scrolls the table using the mouse wheel. The table is updated by increasing the current page index, which is used to slice the data and render the current portion of the data in the table body.

Memory leak when scrolling with the mouse wheel.

cafce25
  • 15,907
  • 4
  • 25
  • 31
Chaos
  • 33
  • 5

0 Answers0