在 innerHTML 中调用带参数的 javascript 函数

Calling a javascript function with parameters in innerHTML

我正在尝试构建自己的评论系统。

以下是单击“回复”按钮时显示评论框的代码:

function postComment(i, parentId) {
    let content;
    if (parentId === undefined) {
        content = commentBox.value
    } else {
        content = eval("subCommentBox"+i).value
    }
    const body = JSON.stringify({
        "post_slug": location.pathname.slice(1),
        "username": "quantong",
        "parent_id": parentId,
        "content": content,
    })
    fetch("http://localhost:8080/comments", {
        method: "post",
        headers: { "Content-Type": "application/json" },
        body: body
    })
        .then(resp => {
            if (resp.status === 200) {
                return resp.json()
            } else {
                console.log("Status: " + resp.status)
            }
        })
    commentBox.value = "";
    window.location.reload();
}

let allElements = document.body.getElementsByClassName("replybtn");

let addCommentField = function () {
    for (let i = 0; i < allElements.length; i++) {
        if (allElements[i] === this) {
            if (document.getElementsByClassName("replyform")[i].innerHTML.length === 0) {
                document.getElementsByClassName("replyform")[i].innerHTML = `
                    <div class="form-group">
                        <textarea class="form-control" id="subCommentBox`+i+`" rows="3"></textarea>
                    </div>
                    <div class="d-flex flex-row-reverse">
                        <button type="button" class="btn btn-success" onclick="postComment(` + i + `, ` + allElements[i].id + `)">Comment</button>
                    </div>
                `
            }
        }
    }
};

window.onload = function() {
    for (let i = 0; i < allElements.length; i++) {
        allElements[i].addEventListener('click', addCommentField, false)
    }
}

如果我放入 .js 文件,它工作正常。

事情是在用户登录后,我想将用户名和个人资料图片作为主体传递给后端,所以我将其移动到 App.svelte 文件:

    let commentBox;
    function postComment(i, parentId) {
        let content;
        if (parentId === undefined) {
            content = commentBox
        } else {
            content = eval("subCommentBox"+i).value
        }
        const body = JSON.stringify({
            "post_slug": location.pathname.slice(1),
            "image_url": responsePayload.picture,
            "username": responsePayload.name,
            "parent_id": parentId,
            "content": content},
        )
        fetch("http://localhost:8090/comments", {
            method: "post",
            headers: { "Content-Type": "application/json" },
            body: body
        })
            .then(resp => {
                if (resp.status === 200) {
                    return resp.json()
                } else {
                    console.log("Status: " + resp.status)
                }
            })
        commentBox = "";
        window.location.reload();
    }

如果我保留 innerHTML 文本原样,会导致:

Uncaught ReferenceError: postComment is not defined

如果我将其更改为:

<button type="button" class="btn btn-success" onclick="postComment(` + i + `, ` + allElements[i].id + `)">Comment</button>

至:

<button type="button" class="btn btn-success" on:click={() => postComment(i, allElements[i].id)}>Comment</button>

它将呈现为:

那么,在 .svelte 文件中,如何在 innerHTML 中调用带参数的 javascript 函数?

如果你想在 Svelte 中做到这一点,你也应该尝试以 'Svelte' 的方式进行,这意味着将所有这些构建 html 放入 javascript 并注入它。

而是将您的标记视为 'state' 的反映,并使用组件让您的生活更轻松。 例如,您的状态将是一组评论,如果用户单击 'reply'。

<!-- This will render a 'Comment' component for each item in the comments -->
{#each comment as comment}
  <Comment {...comment} />
{/each}
<!-- Comment.svelte -->
<script>
  export let id = "";
  export let children = [];
  export let text = "";

  let isReplying = false;
  let reply = ""

  async function postComment() {
    // Hide comment box
    isReplying = false;
    // Send to server, the inputted text is available in 'reply'
    const res =  await fetch(...).then(res => res.json();
    // Append to children so it appears 'live'
    children = [...children, res]
  }
</script>

<!-- The post itself -->
<div>{text}</div>

<!-- Each child is a comment of it's own so render it with this component -->
{#each children as child}
  <svelte:self {...child} />
{/each}

<!-- The reply button simply toggles a state -->
<button on:click={() => isReplying = !isReplying}>Reply</button>

<!-- Show this based on state -->
{#if isReplying}
  <textarea bind:value={reply}>Blabla</textarea>
  <button on:click={postComment}>Send</button>
{/if isReplying}

这应该让您清楚地知道前进的方向。

请记住,您的UI是您状态的反映。所以只要改变状态,Svelte 就会处理剩下的事情(插入、移除、更新圆顶元素)