我正在緩慢但肯定地將一個 jquery 專案遷移到 Svelte,但一些功能(如資料表)在 jquery 中稍微成熟一點。因此,參考Svelte html 示例,我通過使用 promise 更新來自服務器端呼叫的物件陣列來測驗 Svelte 的反應特性;然后重新繪制表格。目的是使實作更接近原生 Svelte。
但是,雖然我得到了要渲染的表,但是當我使用 Svelte 反應性宣告的變數插入 jquery 搜索功能時,我只能在收到錯誤之前更新表一次:Uncaught (in promise) TypeError: e.parentNode is null.
有人可以幫我理解為什么會發生這種情況嗎?
// Load.svelte
<script context="module">
import {env} from './EnvUtils.js';
import axios from "axios";
const wait = delay => new Promise(resolve => setTimeout(resolve, delay));
let perPage = 10;
console.log(env);
const BASE_URL = env.host 'blogged-posts';
const config = {
headers: {
"X-Requested-With": "XMLHttpRequest",
"Accept": "application/json",
'Content-Type': 'application/json',
"X-CSRF-Token": document.querySelector('meta[name="csrf-token"][content]').content
}
}
export async function fetchData(page, search = undefined) {
await wait(500);
console.log(page, search);
try {
const getUrl = (search!==undefined) ? `${BASE_URL}?page=${page}&per_page=${perPage}&search=${search}&delay=1` : `${BASE_URL}?page=${page}&per_page=${perPage}&delay=1`;
const response = await axios.get(getUrl, config);
const { data } = await response;
console.log("data:", data);
return data && data['data']!==null && data['data']!==undefined ? data.data : [];
} catch (error) {
console.error("Error: ", error);
}
}
</script>
以上是用于檢索遠程資料的Load.svelte模塊。axios
// Blog.svelte
<script>
import { onMount, tick } from "svelte";
import {env} from './utils/EnvUtils.js';
import {fetchData} from "./utils/Load.svelte";
import jQuery from "jquery/dist/jquery";
import initDt from 'datatables.net-dt';
console.log(env, jQuery, initDt);
let search;
let currentPage = 1;
let el // table element
let table // table object (API)
$: dataPromise = fetchData(currentPage, search);
onMount(() => {
dataPromise.then(tick).then(() => {
table = jQuery(el).DataTable();
// search input function
table.on('search.dt', function() {
var input = jQuery('.dataTables_filter input')[0];
dataPromise = fetchData(table.page.info().page, input.value);
dataPromise.then(tick).then(() => { // error occurs within this promise on searching more than one letter
console.log("redraw");
});
});
})
});
</script>
<table bind:this={el} class="display" style="width:100%">
<thead>
<tr>
<th>Title</th>
<th>Updated</th>
</tr>
</thead>
<tbody>
{#await dataPromise}
<tr><td>...fetching</td></tr>
{:then rows}
{#each rows as row}
<tr>
<td>{row.title}</td>
<td>{row.updated_at}</td>
</tr>
{/each}
{/await}
</tbody>
<tfoot>
<tr>
<th>Title</th>
<th>Updated</th>
</tr>
</tfoot>
</table>
上面是在渲染資料表之前Blog.svelte等待承諾的組件。dataPromise在資料表的search輸入中;當搜索詞發生變化時,我呼叫該fetchData函式將新資料傳遞給變數。dataPromise reactively declaredPromise 將多次呼叫長搜索詞,并在完成 Promise 后多次更新表。
為了克服這個問題,我創建了一個 Sveltestore writable onReady變數來檢查 promise 是否忙。
// Store.svelte
<script context="module">
import { writable } from 'svelte/store'
export const onReady = writable(true)
</script>
// ... amendments Load.svelte
export async function fetchData(page, search = undefined) {
onReady = false;
// before return
onReady = true;
// ... amendments Blog.svelte
// before calling promise in input function check onReady?
if (!onReady) return false;
dataPromise = fetchData(table.page.info().page, input.value);
這沒有解決問題:有人可以幫忙嗎?
uj5u.com熱心網友回復:
您不能只替換由資料表管理的 HTML。您將不得不更新基礎資料。
由于您的資料是異步加載的,因此無論如何都不應該這樣做。如果您不能或不想實作符合默認請求/回應格式的服務器端點,您應該設定serverSide并true可能用于提供用于獲取和格式化資料的自定義函式。ajax
不這樣做也會干擾過濾,默認情況下發生在客戶端。啟用服務器端處理后,Datatables 還將自動應用 400 毫秒的搜索延遲,可以通過searchDelay選項進行更改。
例子:
<script>
import jQuery from '[email protected]';
import dt from '[email protected]';
import { onMount } from 'svelte';
let table;
let tableApi;
onMount(() => {
dt(window, jQuery);
tableApi = jQuery(table).DataTable({
serverSide: true,
ajax: async (data, callback, settings) => {
const json = await fetch('https://jsonplaceholder.typicode.com/posts')
.then(r => r.json());
// This should happen on server
const search = data.search.value;
const filtered = json.filter(x => !search || x.title.indexOf(search) != -1);
const page = filtered.slice(data.start).slice(0, data.length);
// Expected format for callback:
callback({
draw: data.draw,
data: page,
recordsFiltered: filtered.length,
recordsTotal: json.length,
});
},
columns: [
// Set JSON data source for columns
{ data: 'id' },
{ data: 'title' },
]
});
})
</script>
<svelte:head>
<link rel=stylesheet href="https://cdn.datatables.net/1.12.1/css/jquery.dataTables.min.css"/>
</svelte:head>
<table id=table bind:this={table}>
<thead>
<tr>
<th>ID</th>
<th>Title</th>
</tr>
</thead>
</table>
REPL
在這里使用 Svelte 是沒有意義的,API 不適合它。
唯一可以/應該使用 Svelte 的情況是列是否實際包含 HTML。為此,columns.render可以使用該功能。不幸的是,組件無法行內,而且 Datatables API 似乎也沒有提供僅渲染整行的方法,因此必須將需要 Svelte 驅動的渲染的每個單元格提取到單獨的組件中。
帶有列渲染器的 REPL 示例
(由于某種原因,分頁會導致在 REPL 中打開新選項卡。)
轉載請註明出處,本文鏈接:https://www.uj5u.com/yidong/497719.html
標籤:javascript jQuery es6-承诺 苗条 苗条3
