互联网菜鸟历险记之二

最近一段时间前端开发的经验

1.使用localStorage:(包括选项筛选(不涉及后台请求;绑下拉框数据))

当你的频繁的向后台拿数据进行处理的时候,系统会很卡,如果在第一次加载时获取所有的后台数据,然后放到localStorage中,接下来的处理完全都在前端处理,这样做可以提升系统的性能,我是这样写的:

SetItemData:function(){
            //把数据保存到loacalStorage中
            var itemData = new Array();
            $("#ItemContainer table tbody tr td").find("input").each(function(){
                var item = new Object();
                item.value = $(this).attr("value");
                item.itemname = $(this).attr("itemname");
                item.url = $(this).attr("url");
                item.id = $(this).attr("itemid");
                item.style = $(this).attr("style");
                itemData.push(item);
            });
            if (action.check_support())  
            {  
                localStorage.setItem("ContentItem", JSON.stringify(itemData));  
            }
        },

    check_support:function ()
    {
      if(typeof(Storage) == "undefined")
        {
          alert("Sorry! No web storage support!");
          return false;
        }
      return true;
    },

当你在使用数据时可以直接拿出来用,我是拿这些数据做筛选的,如下,我先定义一个Array result,接收筛选之后的数据,并将数据绑定到html中显示。

//Filter and Process SubItem
        btnfilter:function(){
            var filter = $("#txtfilter").val();
            if(typeof (filter) == "undefined" || filter == null){return;}
            //read data from localStroage
            if (action.check_support())  
            {  
                var result = new Array();
                var storage = window.localStorage;   
                var strJson =  storage.getItem("ContentItem");
                var Content = JSON.parse(strJson);    
                for(var i in Content){
                    if(filter != ""){
                        if(Content[i].itemname.indexOf(filter) > -1){
                            result.push(Content[i]);
                        }
                    }
                    else{
                        result.push(Content[i]);
                    }
                }
                var str = "<div class="row-fluid" style="display:block;" id="menuListEditor"><div class="col-sm-12"><input id="txtfilter" class="input-sm"> <input id="btnfilter" type="button" value="Filter"></div><div class="col-sm-12"><div class="form-group"><table class="table table-striped table-bordered table-hover" style="margin-bottom:0px;"><thead><tr class="info"><th>选择</th><th>选项名称</th></tr></thead><tbody>";
                for(var r in result){
                    str +="<tr><td><input type="checkbox" name="menuId" value=""+ result[r].value+"" url=""+ result[r].url +"" itemid=""+ result[r].id +"" itemname=""+ result[r].itemname +"" style=""+result[r].style +"" /></td><td>"+ result[r].itemname +"("+ result[r].value +")</td></tr>";
                }
                str += "</tbody></table></div><div class="btn-group col-sm-12 text-center"><span><button type="button" class="btn btn-default" id="btnDetailClose">关闭</button></span></div></div></div>";
                
                $("#ItemContainer").html(str);
                $("#txtfilter").val(filter);
            }
            action.processItem(MIndex);
        },

2.可编辑状态下,为一级菜单添加二级选项,显示出归属关系

我在做一些可视化菜单的时候,编辑菜单生成具有层级关系的结构,我们用菜单模板xml,一级菜单已经确定了,我没有用ZTree这样的框架,只是用简单的js满足这样的需求:

进入可编辑页面,一级菜单已经确定,在每个具有子菜单的导航后面有个+ button,点击button 弹出你要选择的菜单选项:其中注意的是,一你要记住你选择的一级导航的index,不然会使二级菜单乱掉,二是

关掉当前的选择框后,再打开一个新的时要是新的(checkbox不能有选中),而打开已经编辑过的时需要显示上次的选中状态。

//process subItem
        processItem:function(data){
            //通过选择器找到点击的一级菜单
        var levelOne = $("#sideNav dl[index='" + data + "']").eq(0);//data就是从外边传入的参数,确定了你点击的是哪一个一级导航
        //打开已经编辑过的,要显示上次编辑选中的状态
            $(levelOne).find("dd").each(function (index,item) {
                $("#ItemContainer input[itemid='" + $(item).attr("id") + "']").attr("checked", "checked");
            });
            //添加二级菜单 触发checkbox
            $("#ItemContainer input[name='menuId']").change(function () {
                var hasAdded = false;//标记在当前一级导航中,这个选项只能被添加一次
                var ItemHref = $(this).attr("url");
                var ItemValue = $(this).val();
                var ItemName = $(this).attr("itemname");
                var ItemStyle = $(this).attr("style");
                var ItemId = $(this).attr("itemid");

                if ($(this).is(':checked')) {
                    var that = $(this);
                    $(levelOne).find("dd").each(function (index, item) {
                        if ($(item).attr("id") == ItemId) {
                            alert("已添加此链接,请勿重复添加!");
                            hasAdded = true;
                        }
                    });
                    if (!hasAdded) {
                        $("<dd class="" + ItemId + "" name="" + ItemName + "" value="" + ItemValue + "" style="" + ItemStyle + "" id="" + ItemId + ""><a href="" + ItemHref + ""><span>" + ItemName + "</span></a></dd>").appendTo(levelOne).children("dt");
                    }
                }
                else {//将选中的移除
                    $(levelOne).find("dd[id='" + ItemId + "']").remove();
                }
            });

3.mvc 中Razor的一些前端方法介绍

Razor我也是刚刚接触,发现有很多意想不到的惊喜,首先是节省了不少的js量,(1)通常,我们在前端写一些button a,都会用js来控制其响应,用Razor的话推荐这三种:

a.@Html.ActionLink("title", "action", new { agrs = OO, backurl = Request.Url.OriginalString }, new { @class = "btn btn-default btn-sm" }),这是一个通过直接访问后台controller action的方法,可以

加上参数,以及后退url和控制其样式。

b.@Ajax.RouteLink("title", "RouteName", new { agrs = XX }, new AjaxOptions { HttpMethod = "Get", OnSuccess = "jsCode" },new { @class = "btn btn-default btn-sm"}),这个是ajax请求,需要在App_Start RouteConfig中配置路由,一般用在不需要跳转页面的请求中,在请求完成时会调用jsCode。

c.@Url.Action(“controller/action”).这个跟a差不多,直接访问后台的controller action

(2)一些标签使用:在项目中,我们有一些输入要做非空验证的,结合使用Razor的表单提交一起使用,同时我们使用ViewModel 进行数据绑定,这样开发非常方便,首先你要引用你的Model(这应该是

MVVM设计模式吧)@model OOXXViewModel,

 @Html.TextBoxFor就是我们平时用的text,@Html.TextAreaFor是textarea,另外还有@Html.PasswordFor(m => m.UserPass),@Html.LabelFor(m => m.UserName)
       @using (Ajax.BeginForm("action", "Controller", new AjaxOptions() { OnSuccess = "jsCode()" }, new { @class = "form-horizontal", @role = "form" }))
        {
            @Html.AntiForgeryToken()//这是防止CSRF攻击的,防止别人伪造页面,黑掉我们网站
            <div class="form-group">
                <label for="ContentId" class="col-sm-3 control-label">菜单项ID</label>
                <div class="col-sm-8">
                    @Html.TextBoxFor(m => m.ContentId, new { @class = "form-control", @readonly = "readonly" })
                </div>
            </div>
            <div class="form-group">
                <label for="ContentName" class="col-sm-3 control-label">菜单名</label>
                <div class="col-sm-8">
                    @Html.ValidationMessageFor(m => m.ContentName, null, new { @class = "text-danger" })
                    @Html.TextBoxFor(m => m.ContentName, new { @class = "form-control", @placeholder = "", @id = "txtName" })
                </div>
            </div>
            <div class="btn-group col-sm-12 text-center">
                <span>
                    <button type="button" class="btn btn-primary" id="btnDetailSubmit">提    交</button>&nbsp;
                    <button type="button" class="btn btn-default" id="btnDetailClose">关闭</button>
                </span>

            </div>
        }

(3)在Razor中调用JS文件可以直接用<script src="@Url.Content("~/Content/jquery.js")"></script>,当然最好的处理静态资源还是用require.js框架,这样可以方便管理加载其他依赖的js;另外对于绑定

页面控件可以使用backbone.js,可以很实时方便的将后台数据绑定到页面控件,

require.config({
    baseUrl: document.getElementById("appPath").value + '/js/lib',
    paths: {
        app: document.getElementById("appPath").value + "/js/app",
        main: document.getElementById("appPath").value + "/js",
        "jquery": "jquery",
        "bootstrap": "bootstrap.min",
        "validate": "jquery.validate.min",
        "ubo-ajax": "jquery.unobtrusive-ajax.min",
        "validate-ubo": "jquery.validate.unobtrusive.min"
    },
    shim: {
        "ubo-ajax": ["jquery"],
        "validate": ["jquery"],
        "bootstrap": ["jquery"],
        "validate-ubo": ["jquery", "validate"]
    }
})
require(["app/action", "underscore", "backbone", "jquery", "jquery-ui", "bootstrap", "validate", "validate-ubo"], function (action, underscore, Backbone) {
    var AppView = Backbone.View.extend({//将时间数据,以及页面所触发的事件绑定到控件中
        el: $('body'),
        initialize: function () {
            $("#OnlineDay").datepicker({
                dateFormat: 'yy-mm-dd',
                showTime: true,
                constrainInput: false
            });
            $("#OfflineDay").datepicker({
                dateFormat: 'yy-mm-dd',
                showTime: true,
                constrainInput: false
            });
        },
        events: {
            'click #btnSearch': action.btnSearch,
            'click #btnSaved': action.btnSaved,
            'click #ddltemplateId': action.ddltemplateId,
            'click #btnReturnList': action.btnReturnList,
            'click #EditTemplateId': action.EditTemplateId,
            'click #btnfilter': action.btnfilter    
        }

    });
    var app = new AppView();

    return app;
})

(4)Razor的Ajax.BeginForm()使用,UpdateTargetId是对DOM id为txtResult的模块进行更新处理

@using (Ajax.BeginForm(new AjaxOptions { UpdateTargetId="txtResult" })) 

        <input type="submit" value="Button"/>             
        <span id="txtResult"/> 

4.Jquery .$Post()请求

当你的系统js访问的域名发生变化时,即从a.com访问了b.com的资源时,这就是跨域的请求处理:

$.ajax({
        url: "http://.......",
        type: 'GET',
        dataType: 'JSONP',//here,这是跨域的ajax请求处理
        success: function (data) {

        }
    });

 5.关于js中的this问题

this在js中我们通常用来作为一个对象使用,如

$("#ItemContainer input[name='menuId']").change(function () {
var hasAdded = false;
var ItemHref = $(this).attr("url");我们一般认为this就是当前change的对象,但是对于ie浏览器中尤其是ie10之下的版本,this是指向的window的,这就让人很纠结,但是解决的方法还是有的,

可以用参数来重新定位this:下面代码是一个for循环中,对一个array进行遍历当某一个被click时触发addFloatEventHandler()方法

 addFloatEventHandler(langlis[i], 'click', function (e) {
                var _this = e.srcElement || e.target;//_this重新指向事件
                var langid = _this.id;
            });
原文地址:https://www.cnblogs.com/walt/p/5080519.html