Typescript can';web组件类中的t set属性

Typescript can';web组件类中的t set属性,typescript,web-component,Typescript,Web Component,我想创建一个从php服务器获取json数据的组件,然后将数据放入ResultGrid类属性中,名为jsonProps我定义了属性,typescript没有抱怨,但是,当我在浏览器中运行代码时,浏览器无法识别我设置的属性,下面是代码 我还尝试在typescript中使用setter,但它不起作用(我发布的typescript代码没有使用它,而是以前的版本) HTML文件 <!DOCTYPE html> <html lang="en"> <head&

我想创建一个从php服务器获取json数据的组件,然后将数据放入
ResultGrid
类属性中,名为
jsonProps
我定义了属性,typescript没有抱怨,但是,当我在浏览器中运行代码时,浏览器无法识别我设置的属性,下面是代码

我还尝试在typescript中使用setter,但它不起作用(我发布的typescript代码没有使用它,而是以前的版本)

HTML文件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>File</title>
</head>
<body>
</body>
<script src="ract.js"></script>
</html>
错误消息是:


未捕获类型错误:this.jsonProps未定义

您正在获取数据异步

let SHOW: boolean = false;

class InputText extends HTMLElement {
    constructor() {
        super();
        let template = document.createElement("template");
        template.innerHTML = this.render();
        this.attachShadow({mode: "open"});
        this.shadowRoot.appendChild(template.content.cloneNode(true));
    }

    render(): string {
        return(`
            <div>
                1. Nama: 
                <input type="text" name="nama">
            </div>
            <div>
                2. NRP:
                <input type="text" name="nrp">
            </div>
            <div>
                3. Kelas:
                <input type="text" name="kelas">
            </div>
            <div>
                4. Jenis kelamin:
                <input type="radio" name="kelamin" value="pria">
                Pria
                <input type="radio" name="kelamin" value="wanita">
                Wanita
            </div>
            <div>
                5. Agama:
                <select name="agama">
                    <option value="islam">Islam</option>
                    <option value="kristen">Kristen</option>
                    <option value="katolik">Katolik</option>
                    <option value="hindu">Hindu</option>
                    <option value="budha">Budha</option>
                    <option value="konghucu">Konghucu</option>
                </select>
            </div>
            <div>
                6. Tempat / Tanggal lahir:
                <input type="text" name="tempat">
                <input type="text" name="tgl">
            </div>
            <div>
                7. Alamat
            </div>
                <textarea name="alamat" cols="30" rows="10"></textarea>
            <div>
                8. Riwayat pendidikan:
                <ul type="a">
                    <li>
                        SD:
                        <input type="text" name="sd">
                    </li>
                    <li>
                        SMP:
                        <input type="text" name="smp">
                    </li>
                    <li>
                        SMA:
                        <input type="text" name="sma">
                    </li>
                </ul>
            </div>
            <div>
                9. Email
                <input type="email" name="email">
            </div>
            <div>
                10. Homepage
                <input type="url" name="homepage">
            </div>
            <div>
                11. Hobby
                </div>
                <textarea name="hobby" cols="30" rows="10"></textarea>
            <div>
                12. interest:
                <input type="checkbox" name="interest1" value="komputer">
                komputer
                <input type="checkbox" name="interest2" value="sport">
                sport
                <input type="checkbox" name="interest3" value="travelling">
                travelling
                <input type="checkbox" name="interest4" value="writing">
                writing
                <input type="checkbox" name="interest5" value="reading">
                reading
                </div>
            <div>
                <button onclick="router()">Simpan</button>
                <button type="reset">Reset</button>
            </div>
        `);
    }
}

class ResultGrid extends HTMLElement {
    jsonProps: Record<string, string | string[]>;

    constructor() {
        super();
        this.jsonProps; // this property is undefined in the browser
    }

    connectedCallback() {
        this.getData();
        let template = document.createElement("template");
        template.innerHTML = this.render();
        this.attachShadow({mode: "open"});
        this.shadowRoot.appendChild(template.content.cloneNode(true));
    }

    async getData() {
        let url = // read.php url;
        try {
            let res = await fetch(url, {
                headers: {
                    'Accept': 'application/json;text/plain'
                }
            });

            if(res.status !== 200) {
                throw new Error(await res.text());
            } else {
                this.jsonProps = await res.json(); // setting property here
            }
        } catch(e) {
            console.error(e.message);
        }
    }

    render() {
        return (`
            <style>
                #grid {
                    display: grid;
                    width: 40vw;
                    grid-template-columns: 1fr 1fr;
                }
            </style>

            <div id="grid">
                <div>Nama</div>
                <div>${this.jsonProps.nama}</div>
                <div>Nrp</div>
                <div>${this.jsonProps.nrp}</div>
                <div>Kelas</div>
                <div>${this.jsonProps.kelas}</div>
                <div>Jenis Kelamin</div>
                <div>${this.jsonProps.kelamin}</div>
                <div>Agama</div>
                <div>${this.jsonProps.agama}</div>
                <div>Tempat</div>
                <div>${this.jsonProps.tempat}</div>
                <div>Tanggal lahir</div>
                <div>${this.jsonProps.tgl}</div>
                <div>Alamat</div>
                <div>${this.jsonProps.alamat}</div>
                <div>SD</div>
                <div>${this.jsonProps.sd}</div>
                <div>SMP</div>
                <div>${this.jsonProps.smp}</div>
                <div>SMA</div>
                <div>${this.jsonProps.sma}</div>
                <div>Email</div>
                <div>${this.jsonProps.email}</div>
                <div>Homepage</div>
                <div>${this.jsonProps.homepage}</div>
                <div>Hobby</div>
                <div>${this.jsonProps.hobby}</div>
                <div>Interest</div>
                <div>${(this.jsonProps.interests as string[]).map((itr: string) => itr)}</div>
                <button onclick="router()">return</button>
            </div>
        `);
    }
}

(function init() {
    customElements.define("input-text", InputText);
    customElements.define("result-grid", ResultGrid);
    let input = document.createElement("input-text");
    document.body.appendChild(input);
})()

function router() {
   if(SHOW === false) {
       (async () => {
            let inputShadow = document.querySelector("input-text").shadowRoot;    
            const url: string = // savetofile.php url;

            let intagr: string[] = [];
        
            (function() {
                (inputShadow.querySelector('input[name="interest1"]') as HTMLInputElement).checked &&
                    intagr.push((inputShadow.querySelector('input[name="interest1"]') as HTMLInputElement).value);
                (inputShadow.querySelector('input[name="interest2"]') as HTMLInputElement).checked &&
                    intagr.push((inputShadow.querySelector('input[name="interest2"]') as HTMLInputElement).value);
                (inputShadow.querySelector('input[name="interest3"]') as HTMLInputElement).checked &&
                    intagr.push((inputShadow.querySelector('input[name="interest3"]') as HTMLInputElement).value);
                (inputShadow.querySelector('input[name="interest4"]') as HTMLInputElement).checked &&
                    intagr.push((inputShadow.querySelector('input[name="interest4"]') as HTMLInputElement).value);
                (inputShadow.querySelector('input[name="interest5"]') as HTMLInputElement).checked &&
                    intagr.push((inputShadow.querySelector('input[name="interest5"]') as HTMLInputElement).value);
            })();       
        
            let send: Record<string, string | string[]> = {
                nama: (inputShadow.querySelector('input[name="nama"]') as HTMLInputElement).value,
                nrp: (inputShadow.querySelector('input[name="nrp"]') as HTMLInputElement).value,
                kelas:  (inputShadow.querySelector('input[name="kelas"]') as HTMLInputElement).value,
                kelamin: (inputShadow.querySelector('input[name="kelamin"]') as HTMLInputElement).value,
                agama: (inputShadow.querySelector("select") as HTMLSelectElement).value,
                tempat: (inputShadow.querySelector('input[name="tempat"]') as HTMLInputElement).value,
                tgl: (inputShadow.querySelector('input[name="tgl"]') as HTMLInputElement).value,
                alamat: (inputShadow.querySelector('textarea[name="alamat"]') as HTMLTextAreaElement).value,
                sd: (inputShadow.querySelector('input[name="sd"]') as HTMLInputElement).value,
                smp: (inputShadow.querySelector('input[name="smp"]') as HTMLInputElement).value,
                sma: (inputShadow.querySelector('input[name="sma"]') as HTMLInputElement).value,
                email: (inputShadow.querySelector('input[name="email"]') as HTMLInputElement).value,
                homepage: (inputShadow.querySelector('input[name="homepage"]') as HTMLInputElement).value,
                hobby: (inputShadow.querySelector('textarea[name="hobby"]') as HTMLTextAreaElement).value,
                interests: intagr
            }
        
            try {
                let res = await fetch(url, {
                    method: 'POST',
                    body: JSON.stringify(send),
                    headers: {
                        'Content-type': "application/json",
                        'Accept': "text/plain"
                    }
                });
                if(res.status !== 200) {
                    let text = await res.text();
                    throw new Error(text);
                }
            } catch (error) {
                alert(error.message);
            }
       })();
        document.querySelector("input-text").remove();
        let resultPage = document.createElement("result-grid");
        document.body.appendChild(resultPage);
        SHOW = true;
    } else {
        document.querySelector("result-grid").remove();
        let inputPage = document.createElement("input-text");
        document.body.appendChild(inputPage);
        SHOW = false;
    }
}
  • 因此,
    this.jsonProps
    未定义的
    ,直到
    getData()
    函数收到它:

  • 移动
    render()
    调用

  • (而且不需要昂贵的
    来创建HTML)


正如@danny-365csi-engelman所建议的 读过之后呢

我将整个异步函数移到了connectedCallback()中

并更新渲染方法

render(jsonProps: Record<string, string | string[]>) {
        return (`
            <style>
                #grid {
                    display: grid;
                    width: 40vw;
                    grid-template-columns: 1fr 1fr;
                }
            </style>

            <div id="grid">
                <div>Nama</div>
                <div>${jsonProps.nama}</div>
                <div>Nrp</div>
                <div>${jsonProps.nrp}</div>
                <div>Kelas</div>
                <div>${jsonProps.kelas}</div>
                <div>Jenis Kelamin</div>
                <div>${jsonProps.kelamin}</div>
                <div>Agama</div>
                <div>${jsonProps.agama}</div>
                <div>Tempat</div>
                <div>${jsonProps.tempat}</div>
                <div>Tanggal lahir</div>
                <div>${jsonProps.tgl}</div>
                <div>Alamat</div>
                <div>${jsonProps.alamat}</div>
                <div>SD</div>
                <div>${jsonProps.sd}</div>
                <div>SMP</div>
                <div>${jsonProps.smp}</div>
                <div>SMA</div>
                <div>${jsonProps.sma}</div>
                <div>Email</div>
                <div>${jsonProps.email}</div>
                <div>Homepage</div>
                <div>${jsonProps.homepage}</div>
                <div>Hobby</div>
                <div>${jsonProps.hobby}</div>
                <div>Interest</div>
                <div>${(jsonProps.interests as string[]).map((itr: string) => itr)}</div>
                <button onclick="router()">return</button>
            </div>
        `);
    }
render(jsonProps:Record){
返回(`
#网格{
显示:网格;
宽度:40vw;
网格模板柱:1fr 1fr;
}
纳米
${jsonProps.nama}
Nrp
${jsonProps.nrp}
卡拉斯
${jsonProps.kelas}
杰尼斯·克拉明
${jsonProps.kelamin}
阿加玛
${jsonProps.agama}
坦帕
${jsonProps.tempat}
唐加拉希尔
${jsonProps.tgl}
阿拉马特
${jsonProps.alamat}
SD
${jsonProps.sd}
开关电源
${jsonProps.smp}
SMA
${jsonProps.sma}
电子邮件
${jsonProps.email}
主页
${jsonProps.homepage}
爱好
${jsonProps.hobby}
兴趣
${(jsonProps.interests as string[]).map((itr:string)=>itr)}
返回
`);
}

@danny-365csi-engelman我将渲染移到了异步部分中,可以说它现在可以工作了。您仍然在使用臃肿的
模板
仅用于插入HTML。这将完成:
This.attachShadow({mode:“open”}).innerHTML=This.render(wait rs.json())
<?php
        try {
        $filename = './data.json';
        $json_file = fopen($filename, 'r');
        if(!$json_file) {
            throw new Exception("error opening file", 1);
        } else {
            header("Content-type: application/json");
            $read_file = fread($json_file, filesize($filename));
            echo json_encode(json_decode($read_file));
        }
        fclose();
    } catch (Exception $th) {
        header("Content-type: text/plain");
        http_response_code(500);
        echo $th->getMessage();
    }
?>
{
    "compilerOptions": {
        "target": "esnext",
        "module": "commonjs",
        "lib": ["ESNext", "DOM"],
        "noImplicitAny": true,
        "preserveConstEnums": true,
        "outDir": "./",
        "sourceMap": true
    },
    "include": ["ract.ts"],
    "exclude": ["node_modules", "**/*.spec.ts"]
}
class ResultGrid extends HTMLElement {
    constructor() {
        super();
    }

    connectedCallback() {
        this.getData();
    }

    async getData() {
        let url = // read.php url;
        try {
            let res = await fetch(url, {headers:'Accept': 'application/json;text/plain'}});
            if(res.status !== 200) {
                throw new Error(await res.text());
            } else {
                this.jsonProps = await res.json(); // setting property here

                // !! NOW .render() can access this.jsonProps
                this.attachShadow({mode:"open"}).innerHTML = this.render();

            }
        } catch(e) {
            console.error(e.message);
        }
    }
class ResultGrid extends HTMLElement {
    constructor() {
        super();
    }

    connectedCallback() {
        (async () => {
            let url = // read.php url
            try {
                let res = await fetch(url, {
                    headers: {
                        'Accept': 'application/json;text/plain'
                    }
                });
    
                if(res.status !== 200) {
                    throw new Error(await res.text());
                } else {
                    let template = document.createElement("template");
                    template.innerHTML = this.render(await res.json());
                    this.attachShadow({mode: "open"});
                    this.shadowRoot.appendChild(template.content.cloneNode(true));
                }
            } catch(e) {
                console.error(e.message);
            }
        })();
    }
render(jsonProps: Record<string, string | string[]>) {
        return (`
            <style>
                #grid {
                    display: grid;
                    width: 40vw;
                    grid-template-columns: 1fr 1fr;
                }
            </style>

            <div id="grid">
                <div>Nama</div>
                <div>${jsonProps.nama}</div>
                <div>Nrp</div>
                <div>${jsonProps.nrp}</div>
                <div>Kelas</div>
                <div>${jsonProps.kelas}</div>
                <div>Jenis Kelamin</div>
                <div>${jsonProps.kelamin}</div>
                <div>Agama</div>
                <div>${jsonProps.agama}</div>
                <div>Tempat</div>
                <div>${jsonProps.tempat}</div>
                <div>Tanggal lahir</div>
                <div>${jsonProps.tgl}</div>
                <div>Alamat</div>
                <div>${jsonProps.alamat}</div>
                <div>SD</div>
                <div>${jsonProps.sd}</div>
                <div>SMP</div>
                <div>${jsonProps.smp}</div>
                <div>SMA</div>
                <div>${jsonProps.sma}</div>
                <div>Email</div>
                <div>${jsonProps.email}</div>
                <div>Homepage</div>
                <div>${jsonProps.homepage}</div>
                <div>Hobby</div>
                <div>${jsonProps.hobby}</div>
                <div>Interest</div>
                <div>${(jsonProps.interests as string[]).map((itr: string) => itr)}</div>
                <button onclick="router()">return</button>
            </div>
        `);
    }