数据/逻辑层放在前端的什么地方

Where to put data / logic layer in front end

我读过很多文章,指出我应该避免将复杂的逻辑放入我的 HTML 模板中, 所以我的问题是,如果我编写的模块需要某些特定属性或 class 名称,基于加载到我页面的数据类型,我应该将这一层写在我的模块内部作为方法还是错误的意识形态?

例如,在此代码中,我从 JSON 文件中加载数据

{
    "slideShow": [
        {
            "img": "aaaaaaaa.jpg",
            "link": "aaaaaaaaa.html",
            "title": "aaaaaa",
            "date": "aaaaaaaa",
            "detail": "aaaaaaaaaaaaa"
        },
        {
            "img": "bbbbbbbbbbb.jpg",
            "link": "bbbbbbbbbbb.html",
            "title": "bbbbbbbbbbb",
            "date": "bbbbbbbbbbbbb",
            "detail": "bbbbbbbbbbbbb"
        },
        {
            "img": "ccccccccccc.jpg",
            "title": "ccccccc",
            "date": "ccccccccccccc"
        },
        {
            "img": "dddddddddd.jpg",
            "title": "ddddddddd",
            "date": "dddddddddd",
            "detail": "dddddddddd"
        }
    ]   
}

到此模板

<section id="slideShow">
    <script id="slideShow-template" type="text/template">
        <ul>
            {{#slideShow}}
            <li class="{{{class}}}">
                <img src="{{{img}}}" alt="{{{title}}}">
                <a href="{{{link}}}">
                    <h1 class="slideShowTitle">{{title}}</h1>
                    <p class="slideShowDate">{{date}}</p>
                    <p class="slideShowDetail">{{detail}}</p>
                </a>
            </li>
            {{/slideShow}}
        </ul>
        <nav>
            {{#slideShow}}
                <a href="javascript:;"></a>
            {{/slideShow}}
        </nav>
        <a href="javscript:void(0)" class="prevSlide"></a>
        <a href="javscript:void(0)" class="nextSlide"></a>

    </script>
</section>

然后我写了这个

(function() {

    var slideShow = {

        slideShow: [],

        importData: function() {
            var xhr = new XMLHttpRequest(),
                url = 'data/slideShow.json',
                _self = this,
                result;
            xhr.onreadystatechange = function() {
                if(this.readyState == 4 && this.status == 200) {
                    result = JSON.parse(this.responseText);
                    _self.slideShow = result.slideShow;
                    _self.dataProcess();
                    _self.init();
                }
            };
            xhr.open('GET', url, true);
            xhr.send();

        },

        dataProcess: function() {
            this.slideShow.forEach(function(element, index) {
                element.class = '';
                if(!element.detail) {
                    element.class += 'noDetail ';
                }
                if(!element.link) {
                    element.link = 'javascript:void';
                    element.class += 'noLink ';
                }
                element.class = element.class.replace('undefined', '');
            });
        },

        init: function() {
            this.render();
            this.cacheDom();
            this.bindEvents();
            this.autoRun();
        },

        bindEvents: function() {
            this.$el.addEventListener('click', this.actionEvent.controlDirection.bind(this));
            this.$nav.addEventListener('click', this.actionEvent.selectSlide.bind(this));
        },

        render: function(cacheDom) {
            var data = {
                slideShow: this.slideShow
            };
            this.$el = document.getElementById('slideShow');
            this.template = document.getElementById('slideShow-template').innerHTML;
            this.$el.innerHTML = Mustache.render(this.template, data);
        },

        cacheDom: function() {
            this.$ul = this.$el.querySelector('ul');
            this.$li = this.$ul.querySelectorAll('li');
            this.$nav = this.$el.querySelector('nav');
            this.$a = this.$nav.querySelectorAll('a');
            this.$next = this.$el.querySelector('.nextSlide');
            this.$prev = this.$el.querySelector('.prevSlide');
        },

        autoRun: function() {
            this.$ul.style.left = '0';
            this.$ul.style.width = this.slideShow.length * 100 + '%';
            this.$li.forEach(function(element) {
                element.style.width = (100 / this.slideShow.length) + '%';
            }.bind(this));
            this.$a[0].classList.add('activated');
            this.autoTimer();
        },

        calc(direction, index) {
            this.left = parseInt(this.$ul.style.left);
            if(direction) {
                this.newLeft = this.left + (direction * 100);
                this.index = this.newLeft / 100;
            } 
            else {
                this.index = index;
                this.newLeft = index * 100;
            }
            if(this.newLeft > ((this.slideShow.length - 1) * 100)) {
                this.index = 0;
                this.newLeft = 0;
            } else if(this.newLeft < 0) {
                this.index = (this.slideShow.length - 1);
                this.newLeft = ((this.slideShow.length - 1) * 100);
            }
        },

        autoTimer: function() {
            this.timer = setTimeout(function() {
                this.transitSlide(+1);
            }.bind(this), 3000);
        },

        transitSlide: function(direction, index) {
            this.$el.removeEventListener('click', this.actionEvent.controlDirection);
            this.calc(direction, index);
            this.$ul.classList.add('fade');
            setTimeout(function() {
                this.changeSlide();
                this.bindEvents();
            }.bind(this), 700);
        },

        changeSlide: function() {
            clearTimeout(this.timer);
            this.autoTimer();
            this.$a.forEach(function(element) {
                element.classList.remove('activated');
            });
            this.$a[this.index].classList.add('activated');
            this.$ul.style.left = this.newLeft + '%';
            this.$ul.classList.remove('fade');
        },

        eventHandling: function() {
            clearTimeout(this.timer);
            event.stopImmediatePropagation();
            event.preventDefault();
        },

        actionEvent: {

            controlDirection: function() {
                this.eventHandling();
                if(event.target == this.$next) {
                    this.transitSlide(+1);
                } else if(event.target == this.$prev) {
                    this.transitSlide(-1);
                }
            },

            selectSlide: function() {
                this.eventHandling();
                this.$a.forEach( function(element, index) {
                    if((event.target == element) && (!element.classList.contains('activated'))) {
                        this.transitSlide(false, index);
                    }
                }.bind(this));
            }

        }

    };

    slideShow.importData();

})();

我问的是 this.dataProcess() 检查数据对象以添加 class 名称和属性 这是某种与服务器端和数据库无关的数据

我应该把它留在这里还是我的结构有误?

通常,当人们谈论在演示文稿中避免复杂的逻辑时,他们指的是业务逻辑。数据中改变处理流程的条件。

在你的情况下,你谈论的是表示逻辑,而不是业务逻辑,它绝对应该保留在你拥有它的表示层中。

您应该避免的事情是如果您有控制逻辑,例如,如果您根据日期更改标题。这将是最好在服务器端的专用层内完成的逻辑,这样它就可以是 reused/tested/enforced 等

我个人使用的测试是,如果我为不同的交付渠道(例如 thick-client)重写整个应用程序,逻辑是否有用,那是有用的逻辑吗?或者我必须大幅改变它吗?如果它在很大程度上保持完整(尽管存在语言差异),那么它可能属于 server-side 在 Logic/Service/Business 层中。在您的情况下,您正在谈论修改 CSS。它特定于表示,因此如果使用不同的表示层,可能会有很大的不同。