實例演示 kino.razor (前端 Javascript 模板工具,Razor 風格)的使用


前言

對於習慣了 ASP.NET MVC Razor 模板引擎的人來說,比如我,一直在尋找前端 Javascript 端的 Razor 模板工具。這之前,我也了解到很多Javascript 端的模板工具,比如:jquery.tmplKnockoutfront.js 等等。園子里很多大牛推薦 Knockout,比如:蔣金楠(Artech)老師湯姆大叔(TomXu)。個人覺得 Knockout 太強大了,強大到入門都是那么的困難,我看了官網上的幾個例子,最后還是放棄了,覺得太復雜了,殺雞還需要用牛刀嗎?且並不是所有的“綁定”都要交給前端的,比如 Hello World 那個例子,FirstName、LastName、FullName 這些本該由服務器端直接輸出的東西,何必又要交給 Knockout 呢。團隊成員入門難就不適合了(PS:也許是我本人太笨,自黑一下,呵呵...)。在園子里搜了 kino.razor 一下,正好還沒有人來寫文來介紹它,於是就有了本文。kino.razor 正如官方的介紹:

 kino.razor  - an easy to use,razor style javascript template tool

它是一個簡單易用、Razor 風格的 Javascript 模板工具。用過之后感覺確實如此。

開始實戰

1. 首先我們來建立一個名為 Message 的模型類。

public class Message
{
    public Guid SenderKey { get; set; }
    public int SenderUserId { get; set; }
    public string SenderName { get; set; }
    public string Content { get; set; }

    private DateTime _date { get; set; }
    public DateTime Date
    {
        get { return _date; }
        set
        {
            _date = value;
            _formattedDate = _date.ToLongDateString() + " " + _date.ToLongTimeString();
        }
    }
    private string _formattedDate;
    public string FormattedDate
    {
        get { return _formattedDate; }
    }
}

2. 建立一個名為 MessageRepository 的數據訪問類。

public class MessageRepository
{
    // 為了演示,不保存到數據庫了
    private static readonly IList<Message> dbMessage = new List<Message>()
    {
        new Message{ SenderKey = Guid.NewGuid(), SenderUserId = 1, SenderName = "張學友", Date = DateTime.Now, Content = "你好,請問今天星期幾?" },
        new Message{ SenderKey = Guid.NewGuid(), SenderUserId = 2, SenderName = "李世民", Date = DateTime.Now, Content = "今天真的很冷!" },
        new Message{ SenderKey = Guid.NewGuid(), SenderUserId = 3, SenderName = "王大山", Date = DateTime.Now, Content = "吃早飯了么?" },
        new Message{ SenderKey = Guid.NewGuid(), SenderUserId = 4, SenderName = "劉德華", Date = DateTime.Now, Content = "要不我們今晚去游泳吧?" },
        new Message{ SenderKey = Guid.NewGuid(), SenderUserId = 5, SenderName = "郭富城", Date = DateTime.Now, Content = "雙手的溫柔是你的錯!" },
    };

    public static IList<Message> GetAll()
    {
        return dbMessage;
    }

    public static Message AddMessge(int senderUserId, string senderName, string content)
    {
        var message = new Message { SenderKey = Guid.NewGuid(), SenderUserId = senderUserId, SenderName = senderName, Date = DateTime.Now, Content = content };
        dbMessage.Add(message);
        return message;
    }
}

為了演示,就增加了 2 個方法,一個得到所有的消息,另一個插入消息,不保存到數據庫了。

3. 建立一個名為 SysConst 的系統常用的資源

/// <summary>
/// 系統常用的資源
/// </summary>
public class SysConst
{
    /// <summary>
    /// 默認的發送者ID
    /// </summary>
    public static readonly int DefaultSenderUserId = 3;

    /// <summary>
    /// 默認的發送者姓名
    /// </summary>
    public static readonly string DefaultSenderUserName = "王大山";
}

4. 建立 Default.aspx 頁面或者 View.cshtml

首先在 Default.aspx.cs 頁面中獲取所有的消息,保存在 Messages 屬性中,供 Default.aspx 頁面調用。PS:沒有用服務器控件,才出此策。

public partial class Default : System.Web.UI.Page
{
    /// <summary>
    /// 保存獲取的消息集合,供頁面調用
    /// </summary>
    protected IList<Message> Messages { get; private set; }

    protected void Page_Load(object sender, EventArgs e)
    {
        if(!IsPostBack)
        {
            LoadData();// 調用加載數據的方法
        }
    }

    /// <summary>
    /// 加載數據
    /// </summary>
    private void LoadData()
    {
        Messages = MessageRepository.GetAll();
    }
}

5. 在頁面引用 css 和 js

<link href="css/bootstrap.min.css" rel="stylesheet" type="text/css" />
<link href="css/chat.css" rel="stylesheet" type="text/css" />
<script src="js/jquery-1.8.2.min.js" type="text/javascript"></script>
<script src="js/kino.razor.min.js" type="text/javascript"></script>

6. 完成靜態頁面布局

效果圖:

代碼:

<div id="chat">
    <div class="chat_content" style="height: 485px">
        <!-- 這里是需要循環的項 -->
        <script type="text/template" id="temp-message-gallery">
            @for(var i = 0; i < list.length; i++ )
            {
            <div class="@list[i].msgClass">
                <div class="chat_mes_title clearfix">
                    <span class="date" style="display: inline">@list[i].message.FormattedDate</span>
                    <span class="name" style="display: inline">@list[i].message.SenderName</span>
                </div>
                <div class="clear"></div>
                <div class="chat_mes_text clearfix">
                    @list[i].message.Content
                </div>
            </div>
            }
        </script>
    </div>
</div>
<div class="chat_form">
    <form action="#">
        <button class="btn btn-success" type="button" id="sendmessage">
            發送
        </button>
        <div class="chat_field">
            <textarea id="msg" placeholder="請輸入消息"></textarea>
        </div>
    </form>
</div>

不知道大家注意到那段注釋“這里是需要循環的項”下面的代碼沒有,是不是很熟悉,很爽?千萬不要以為這是用 ASP.NET MVC Razor 寫的服務器端代碼,呵呵,這就是按照 kino.razor 模板的規則來寫的,是客戶端代碼!!!!!!

其中 @list[i].msgClass 是樣式輸出,判斷這條消息是否是當前登錄用戶發的,如果不是,樣式就是“chat_message”。如果是,樣式就是“chat_message chat_mes_my”。

其中 @list[i].message 就是我們定義的 Message 模型類對應的 json 對象。

7. 把后台 Default.aspx.cs 傳遞過來的 List<Message> 序列化成 json 數組。

<%
    int currentUserId = SysConst.DefaultSenderUserId; // 當前用戶的 ID
    const string defaultClass = "chat_message"; // 默認樣式
    const string mineClass = "chat_mes_my"; // 發送者是自己時的樣式
    List<dynamic> list = new List<dynamic>();
    if (this.Messages != null && this.Messages.Count > 0)
    {
        foreach (var msg in this.Messages)
        {
            string msgClass = msg.SenderUserId == currentUserId ? defaultClass + " " + mineClass : defaultClass;
            // 上面是判斷這條消息是否是當前登錄用戶發的,如果是,則添加一個樣式
            list.Add(new { msgClass = msgClass, message = msg });
        }
    }
    string json = new JavaScriptSerializer().Serialize(list);
%>

上面是為了展示歷史消息,而做的。為了區分消息的發送者是否是自己,就自己新建了一個 dynamic 的集合,用來保存樣式值、消息對象。最后把這個 dynamic 的集合序列化成 json,放到下一步(第 8 步)中。

8.  用 kino.razor 來呈現 json 集合

<script type="text/javascript">
    // 顯現所有消息的方法
    function renderAllMessage(dataArray)
    {
        var htmlTempl = $("#temp-message-gallery").html();// 找到模板
        var resultContent = kino.razor(htmlTempl, { list: dataArray });
        // 上面就是把 json 數組傳遞給 kino.razor。list 就是我們在模板
        // 中用到的變量名
        $(".chat_content").append(resultContent);// 找到容器 DIV,附加
        setScrollTop();
    }
    $(document).ready(function()
    {
        // 把當前服務器的消息實體集合序列化成 JSON,然后呈現。
        renderAllMessage(<%= json %>);
    });
    // 把滾動條設置到最下,以便呈現最新的消息。
    function setScrollTop()
    {
        var chatContent = $(".chat_content"); // 找到容器 DIV
        var scrollHeightValue = chatContent.get(0).scrollHeight;
        var heightValue = chatContent.height();// 得到容器的高度
        var scrollTopValue = scrollHeightValue - heightValue;
        chatContent.scrollTop(scrollTopValue);
    }
</script>

注釋都已經加上了,如果還不明白,請在評論里反饋,讓筆者 知道,相互學習,謝謝!

做到這里,運行,就可以看到效果了。

9. 給 發送 按鈕綁定點擊事件

代碼:

<script type="text/javascript">
    $('#sendmessage').click(function ()
    {
        var content = $.trim($('#msg').val());
        if (content.length == 0)
        {
            alert("請輸入消息!");
            return;
        }
        if (content.length > 1000)
        {
            alert("每次發送的消息不能超過 1000 字!");
            return;
        }
        $('#msg').attr("disabled", "disabled");
        $.ajax({
            type: "POST",
            url: "/post-message.ashx",
            data: { content: content },
            success: function (data)
            {
                // 返回成功后,調用呈現單條消息的方法
                renderSingleMessage(data);
                $('#msg').removeAttr("disabled").val('').focus();
            },
            error: function (msg)
            {
                alert("發送失敗,請稍后再提交!");
                $('#msg').removeAttr("disabled").focus();
            }
        });
    });
    // 呈現單條消息
    function renderSingleMessage(msg)
    {
        var msgClass = '<%= defaultClass %>';
        var currentUserId = <%= currentUserId %>;

        if (msg.SenderUserId == currentUserId)
        {
            msgClass += ' <%= mineClass %>';
        }
        var list = [];
        list[0] = { msgClass: msgClass, message: msg };
        renderAllMessage(list);// 調用呈現所有消息的方法
    }
</script>

在 renderSingleMessage 中判斷當前消息是否是本人添加的(目前發送者肯定是自己,后期會做成聊天室的形式,基於 ASP.NET SignalR 來做。),如果是,則什么樣式,如果不是,則又是什么樣式。最后把 json 對象傳遞給上面已經定義了的 renderAllMessage 函數用來呈現。

10. 在 ashx 保存消息

新建一個名為“post-message.ashx” 的一般處理程序,完成如下代碼:

public class post_message : IHttpHandler
{

    public void ProcessRequest(HttpContext context)
    {
        string content = context.Request.Form["content"];// 獲取消息內容

        var message = MessageRepository.AddMessge(SysConst.DefaultSenderUserId, 
            SysConst.DefaultSenderUserName, 
            content); // 保存消息

        string json = new JavaScriptSerializer().Serialize(message);

        context.Response.ContentType = "text/json";
        context.Response.Write(json);
    }

    public bool IsReusable{get{return false;}}
}

至此,流程已經走完。如果還不明白,請在評論里反饋,讓筆者 知道,相互學習,謝謝!

總結

完整的流程如下:

oo1:

002:

003:

004:

也許你還會喜歡:

自定義 Javascript 模板規則,打造輕量級模板引擎

一個簡單的 JavaScript 模板引擎

一個輕量級 Javascript 模板引擎 front.js【二】

謝謝瀏覽!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM