V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
18510047382
V2EX  ›  React

使用 ale.js 制作一个小而美的表格编辑器(4)

  •  
  •   18510047382 · 2019-01-21 14:19:59 +08:00 · 1845 次点击
    这是一个创建于 2166 天前的主题,其中的信息可能已经有所发展或是发生改变。

    今天来教大家如何使用 ale.js 制作一个小而美的表格编辑器,首先先上 gif:

    是不是还是有一点非常 cool 的感觉的?那么我们现在开始吧!

    这是我们这篇文章结束后完成的效果(如果想继续完成请访问第五篇文章):

    ok,那继续开始吧**(本篇文章是表格编辑器系列的第四篇文章,如果您还没有看过第一篇,请访问 第一篇文章(开源中国)):**

    首先我们需要先添加一个 Sreach 按钮(在 handleTemplateRender 函数里):

    //把 定义 DOM 基本结构 的 returnVal
    var returnVal = "<table><thead><tr>"
    
    //改为
    var returnVal = "<table><thead><button class='a-btn' onclick='this.methods.trigSearch()'>Search</button><tr>"
    

    之后我们需要在 methods 里面添加一个 trigSearch 函数:

    trigSearch(){
        if (this.data.isOpenSearch) {
            this.data.data = this.staticData.preData;
            this.data.isOpenSearch = false;
        } else {
            this.data.isOpenSearch = true;
        }
    }
    

    接下来,我们需要在 data 里添加一个 isOpenSearch 变量,默认为 false:

    isOpenSearch: false
    

    还要在 staticData 里添加一个 preData,用来存储 bookData 数据:

    preData: [
        ["The Lord of the Rings", "	J. R. R. Tolkien", "English", "1954-1955", "150 million"],
        ["The Little Prince", "Antoine de Saint-Exupéry", "French", "1943", "140 million"],
        ["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1791", "100 million"]
    ]
    

    之后我们要在 handleTemplateRender 函数中增加一个判断,判断是否 openSearch 开启了:

    //把
    
    //循环遍历 bookHeader 数据并输出
    this.data.bookHeader.forEach(function(val, i, arr) {
        returnVal += "<th onclick='this.methods.handleTheadOnclick(event)'>" + val + (sortBy === i ? getSortSign() : '') + "</th>";
    })
    
    returnVal += "</thead></tr><tbody>";
    
    
    
    //改为
    
    //循环遍历 bookHeader 数据并输出
    this.data.bookHeader.forEach(function(val, i, arr) {
        returnVal += "<th onclick='this.methods.handleTheadOnclick(event)'>" + val + (sortBy === i ? getSortSign() : '') + "</th>";
    })
    
    var cellId = -1;
    
    if (this.data.isOpenSearch) { //这里增加判断
        returnVal += "</tr><tr>";
        for (var i = 0; i < this.data.bookHeader.length; i++) {
            cellId++;
            returnVal += "<th><input data-cell='" + cellId + "' type='text' oninput='this.methods.handleSearch(this, event)' placeHolder='Search...'></th>";
        }
    }
    
    returnVal += "</thead></tr><tbody>";
    

    然后我们要继续在 methods 里面添加一个名叫 handleSearch 的函数:

    handleSearch(el, e) {
        var newData = [],
            elVal = el.value;
        this.staticData.preData.forEach(function(val, i, arr) {
            //判断是否拥有输入的字段
            if (val[e.target.dataset.cell].indexOf(elVal) !== -1) {
                //添加到返回对列中
                newData.push(val);
            }
        });
    
        this.data.bookData = newData;
    }
    

    现在我们就已经实现了搜索功能,恭喜!

    这是我们目前全部的 js 代码:

    Ale("excel", {
                template() {
                    return this.methods.handleTemplateRender();
                },
                methods: {
                    handleTemplateRender() {
                        //定义 DOM 基本结构
                        var returnVal = "<table><thead><button class='a-btn' onclick='this.methods.trigSearch()'>Search</button><tr>",
                            getSortSign = this.methods.getSortSign,
                            sortBy = this.staticData.sortBy,
                            rowId = -1,
                            edit = this.data.edit;
    
                        //循环遍历 bookHeader 数据并输出
                        this.data.bookHeader.forEach(function(val, i, arr) {
                            returnVal += "<th onclick='this.methods.handleTheadOnclick(event)'>" + val + (sortBy === i ? getSortSign() : '') + "</th>";
                        })
    
                        var cellId = -1;
    
                        if (this.data.isOpenSearch) {
                            returnVal += "</tr><tr>";
                            for (var i = 0; i < this.data.bookHeader.length; i++) {
                                cellId++;
                                returnVal += "<th><input data-cell='" + cellId + "' type='text' oninput='this.methods.handleSearch(this, event)' placeHolder='Search...'></th>";
                            }
                        }
    
                        returnVal += "</thead></tr><tbody>";
    
                        //循环遍历 bookData 数据并输出
                        this.data.bookData.forEach(function(thisBook, i, arr) {
                            var cellId = -1;
                            rowId++;
                            //输出一行
                            returnVal += "<tr>";
                            thisBook.forEach(function(val, i, arr) {
                                cellId++;
                                if (rowId === edit.row && cellId === edit.cell) {
                                    returnVal += "<td><form data-cell='" + cellId + "' data-row='" + rowId + "' onsubmit='this.methods.save(event)'><input type='text' value='" + val + "'></form></td>";
                                } else {
                                    returnVal += "<td data-cell='" + cellId + "' data-row='" + rowId + "' ondblclick='this.methods.handleBlockOndblclick(event)'>" + val + "</td>";
                                }
                            })
                            returnVal += "</tr>";
                        })
                        returnVal += "</tbody></table>";
    
                        //返回 DOM 结构
                        return returnVal;
                    },
                    handleTheadOnclick(e) {
                        this.methods.changeSortType(e);
                        this.methods.sortList(e);
                    },
                    changeSortType(e) {
                        this.staticData.sortBy = e.target.cellIndex;
                        if (this.staticData.sortType === "up") {
                            this.staticData.sortType = "down";
                        } else {
                            this.staticData.sortType = "up";
                        }
                    },
                    sortList(e) {
                        var index = e.target.cellIndex;
                        if (this.staticData.sortType === "up") {
                            this.data.bookData.sort(function(a, b) {
                                return a[index].charCodeAt(0) > b[index].charCodeAt(0) ? 1 : -1;
                            })
                        } else {
                            this.data.bookData.sort(function(a, b) {
                                return a[index].charCodeAt(0) < b[index].charCodeAt(0) ? 1 : -1;
                            })
                        }
    
                        this.data.bookData = this.data.bookData;
                    },
                    getSortSign() {
                        if (this.staticData.sortType === "up") {
                            return '\u2191';
                        } else {
                            return '\u2193';
                        }
                    },
                    handleBlockOndblclick(e) {
                        if (!this.staticData.isOpenEdit) {
                            this.staticData.isOpenEdit = true;
                            this.data.edit = {
                                row: parseInt(e.target.dataset.row),
                                cell: parseInt(e.target.dataset.cell)
                            }
                        }
                    },
                    save(e) {
                        e.preventDefault();
                        var input = e.target.firstChild;
                        this.staticData.isOpenEdit = false;
                        this.data.edit = {
                            row: -1,
                            cell: -1
                        }
                        this.data.bookData[e.target.dataset.row][e.target.dataset.cell] = input.value;
                        this.data.bookData = this.data.bookData;
                    },
                    trigSearch() {
                        if (this.data.isOpenSearch) {
                            this.data.bookData = this.staticData.preData;
                            this.data.isOpenSearch = false;
                        } else {
                            this.data.isOpenSearch = true;
                        }
                    },
                    handleSearch(el, e) {
                        var newData = [],
                            elVal = el.value;
                        this.staticData.preData.forEach(function(val, i, arr) {
                            if (val[e.target.dataset.cell].indexOf(elVal) !== -1) {
                                newData.push(val);
                            }
                        });
    
                        this.data.bookData = newData;
                    }
                },
                data: {
                    bookHeader: [
                        "Book", "Author", "Language", "Published", "Sales"
                    ],
                    bookData: [
                        ["The Lord of the Rings", "	J. R. R. Tolkien", "English", "1954-1955", "150 million"],
                        ["The Little Prince", "Antoine de Saint-Exupéry", "French", "1943", "140 million"],
                        ["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1791", "100 million"]
                    ],
                    edit: {
                        row: -1,
                        cell: -1
                    },
                    isOpenSearch: false
                },
                staticData: {
                    sortBy: -1,
                    sortType: 'down',
                    isOpenEdit: false,
                    preData: [
                        ["The Lord of the Rings", "	J. R. R. Tolkien", "English", "1954-1955", "150 million"],
                        ["The Little Prince", "Antoine de Saint-Exupéry", "French", "1943", "140 million"],
                        ["Dream of the Red Chamber", "Cao Xueqin", "Chinese", "1791", "100 million"]
                    ]
                }
            })
            Ale.render("excel", {
                el: "#app"
            })
    

    如果想了解更多,欢迎关注我在明天推出的第五篇教程,同时也关注一下 alejs 哦,感谢各位!

    (非常重要:如果有能力的话不妨去 Github 或 码云 上 star 一下我们吧!不过如果您特别喜欢 alejs 的话也可以 watch 或 fork 一下哦!十分感谢!)

    目前尚无回复
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   2360 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 20ms · UTC 16:09 · PVG 00:09 · LAX 08:09 · JFK 11:09
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.