實(shí)例詳解angularjs和ajax的結(jié)合使用
這是一篇關(guān)于easyui配合ajax使用的文章,順帶介紹angularjs的使用以及讓你感受到angularjs的威力。網(wǎng)上對于ajax 的文也是多如牛毛 。我就不直接從那種原生的httpxmlrequest 對象的js 寫起了哈??茨欠N東西也存粹是了解 高層的東西是怎么來的 原理是啥真正做的時候?qū)懩欠N東西 不是扯淡么 你叼你技術(shù)牛逼整站的代碼你全用那種寫。html js 這種東西最開始設(shè)計出來就沒考慮周全就是坨屎。還好現(xiàn)在有各種框架 可以幫助我們更容易的把這坨屎做的更美味。也還好由于互聯(lián)網(wǎng)事業(yè)如日中天 的推動 讓瀏覽器端的這堆東西正在往統(tǒng)一規(guī)范的方向發(fā)展。
我們來建立一個webform頁面 HelloAjaxNet.aspx。先說下ajax 這里我使用網(wǎng)上流傳甚廣的那個AjaxPro.2.dll 他的網(wǎng)站是 http://www.ajaxpro.info/ 這是一個個人作品 ,很好用。
本來新的asp.net 里自帶了服務(wù)端方法用webmethod 屬性聲明 客戶端pagemethods訪問的方式 ,各種對象也可以json數(shù)據(jù)化 ,功能跟上面一樣的。微軟自帶的是aspx的codebehind 代碼方法 一定要加static ,至于webconfig 在新版的vs2013開發(fā)環(huán)境下無須配置 如果是老的則新建ajax網(wǎng)站項目則webconfig自動弄好了然后服務(wù)端頁面載入事件中 ScriptManager.GetCurrent(Page).EnablePageMethods = true; 客戶端 必須有runat=server 的form 和 <asp:ScriptManager ID="ScriptManager1" runat="server"> </asp:ScriptManager> 然后客戶端就可以pagemethods 的方式訪問。
我始終還是認(rèn)為上面那個更好用 。關(guān)于他的原理我就不多說了 ,通過頁面載入時注冊服務(wù)端對象 ,然后生成的html頁面上就多了這么幾句
<script type="text/javascript" src="/ajaxpro/prototype.ashx"></script> <script type="text/javascript" src="/ajaxpro/core.ashx"></script> <script type="text/javascript" src="/ajaxpro/converter.ashx"></script> <script type="text/javascript" src="/ajaxpro/WebApplication.StudentsInfo,WebApplication.ashx"></script> <script type="text/javascript" src="/ajaxpro/WebApplication.Grad,WebApplication.ashx"></script> <script type="text/javascript" src="/ajaxpro/WebApplication.NewFolder.HelloAjaxNet,WebApplication.ashx"></script> <script type="text/javascript" src="/ajaxpro/WebApplication.DataEntity,WebApplication.ashx"></script>
為是什么呢 為的是引用一段js文件 ajaxpro/WebApplication1.NewFolder2.HelloAjaxNet,WebApplication1.ashx
然后你就明白了噻 這段客供你進(jìn)行客戶端js調(diào)用的腳本 是服務(wù)端自動生成的 跟你 服務(wù)端的名字一模一樣 然后你就可以貌似像在客戶端回調(diào)服務(wù)端方法樣的 沒什么神奇的,我們主要就是想利用他的這個特性和json化數(shù)據(jù)的方便之處 來實(shí)現(xiàn)客戶端服務(wù)端數(shù)據(jù)的無縫傳遞。
關(guān)于json數(shù)據(jù)的序列化 要是以前就只有利用外部json庫 或者微軟自帶的來進(jìn)行手動解析:
服務(wù)端:
public string ServerProcerMethod(string stu) { //System.Web.Script.Serialization.JavaScriptSerializer jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); //StuInfo s= jsSerializer.Deserialize<StuInfo>(stu); System.Web.Script.Serialization.JavaScriptSerializer jsSerializer = new System.Web.Script.Serialization.JavaScriptSerializer(); List<StuInfo> s = jsSerializer.Deserialize<List<StuInfo>>(stu); if (s != null && s.Count > ) { StuInfo stu= s[]; StringBuilder sb = new StringBuilder(); jsSerializer.Serialize(stu, sb); return sb.ToString(); } else return null; }
客戶端:
//javascript 字符串轉(zhuǎn)json對象: var obj = JSON.parse(str); //javascript json 對象轉(zhuǎn)字符串: JSON.stringify(obj);
關(guān)于AjaxPro.2.dll 和ajax.dll的關(guān)系 ,網(wǎng)上說他們不一樣 其實(shí)壓根就是一個人搞的吧 我擦 。請在上面網(wǎng)站下載ajaxpro 這個才是完善的版本
引用dll文件后需要配置webconfig httphandler 作用就是讓 上面的ashx請求轉(zhuǎn)到我們的 ajaxpro代碼 ,進(jìn)而讓我們的客戶端js直接調(diào)用服務(wù)端方法調(diào)用成功。
<system.webServer> <directoryBrowse enabled="true"/> <handlers> <add verb="*" path="*.ashx" name="myhandler" type="AjaxPro.AjaxHandlerFactory,AjaxPro."/> <!--<add verb="POST,GET" path="ajax/*.ashx" name="myhandler" type="Ajax.PageHandlerFactory, Ajax" />--> </handlers> </system.webServer>
然后其他的我就不多說了哈待會直接看服務(wù)端代碼。
easyui 你就可以理解為一堆擴(kuò)展了的控件。就像jquery一樣 你把js對象 原生的html控件用他的東西一包 然后就可以點(diǎn)得出他一些為你寫好的方法 幫助你方便的處理數(shù)據(jù)。并且還有默認(rèn)的還可以的控件外觀,這點(diǎn)對于做企業(yè)管理類軟件來說 還是真心不錯的,做其他的就只能呵呵了。下載easyui的文件 放到項目中 并引入easyui 相關(guān)js和樣式文件 還有jquery:
<script type="text/javascript" src="../jquery-easyui-../jquery.min.js"> </script> <link rel="stylesheet" type="text/css" href="../jquery-easyui-../themes/default/easyui.css" /> <link rel="stylesheet" type="text/css" href="../jquery-easyui-../themes/icon.css" /> <script type="text/javascript" src="../jquery-easyui-../jquery.easyui.min.js"></script>
然后 ,然后你就可以使用easyui了 就像easyui 首頁 http://jeasyui.com/ 上介紹的那樣 通過css樣式 或者js代碼 把原生html控件渲染成easyui控件
<div class="easyui-dialog" style="width:px;height:px" data-options=" title:'My Dialog', iconCls:'icon-ok', onOpen:function(){}"> dialog content. </div> <input id="cc" style="width:px" /> $('#cc').combobox({ url: ..., required: true, valueField: 'id', textField: 'text' });
是的 非常方便。其實(shí)國內(nèi)還有好些js寫的比較牛的 弄了一些這樣ui 那樣ui 選來選去還是用這個吧。用的最多的需求就是ajax服務(wù)端分頁 ,我們來弄個吧。
我們先說下這個easyui的datagrid 打他狗日的,客戶端html放個table標(biāo)簽 :<table id="studb"></table> 然后用js這么一搞 $('#studb').datagrid() 他就給你渲染成easyui datagrid控件了 ,你可以在document.ready()時做這個事情。我們的數(shù)據(jù)表格是需要填充數(shù)據(jù)的 這些數(shù)據(jù)從哪來 顯示哪些列 怎么分頁 每頁顯示多少條,這些都是參數(shù),怎么傳進(jìn)去。easyui很多地方都接收json對象形式的一坨參數(shù) ,比如這個datagrid:
function bindDataToTb() { var keywordStr = $('#keyword').val(); $('#studb').datagrid( { queryParams: { keyword: keywordStr }, //url:"WebForm.aspx/BindData", toolbar: '#searchBar', pagination: true, pageNumber: , singleSelect: true, pageSize: , pageList: [, , ], loader: function (param, success, error) { var da = WebApplication.NewFolder.HelloAjaxNet.BindData(param.keyword, param.page, param.rows) if (da.value.rows == null) { success(); } else success(da.value); }, pagePosition: 'bottom', columns: [[ { field: 'stuNo', title: 'Id', width: }, { field: 'name', title: '名字', width: }, { field: 'age', title: '年齡', width: }, { field: 'loginName', title: '登錄名', width: }, { field: 'loginPwd', title: '密碼', width: }, { field: 'GradId', title: '班級Id', width: }, { field: 'gradName', title: '班級', width: }, { field: 'none', title: '操作', width: , formatter: function (value, row, index) { var btn = '<a class="editcls" href="#" onclick="delstuClick(' + row.stuNo + ')">刪除</a>'; return btn; } } ]] }); }
具體看loader 和columns ,loader用于定義你以什么形式載入數(shù)據(jù) 定義了loader上面的url就沒有必要了。
我這里的WebApplication1.NewFolder2.HelloAjaxNet.BindData(param.keyword, param.page, param.rows) 自然也是服務(wù)端的方法 用于檢索數(shù)據(jù)的 。
關(guān)于這三個param.keyword, param.page, param.rows 是我們用于實(shí)現(xiàn)loader時 easyui那種設(shè)計方式故意暴露給我們的參數(shù) 方便我們使用。
param.keyword 是我們上面定義的 我們點(diǎn)搜索的時候需要往服務(wù)端傳一個查詢關(guān)鍵詞 queryParams: { keyword: keywordStr }
param.page 是easyui自己的參數(shù)表示當(dāng)前第幾頁 param.rows表示每頁行數(shù),每當(dāng)你 點(diǎn)表格的 上一頁 下一頁 的時候 就會自動往loader 發(fā)翻頁的參數(shù) 這個是自動的。
然后就從服務(wù)端獲取數(shù)據(jù)填充表格 ,就是這么一個工作過程。 還有colums 我就不說了就是定義顯示哪些列 和自定義列 那個很容易看懂。
easyui控件有屬性 方法,調(diào)用方法 的形式總算像這樣 :$('#studb').datagrid('reload') 這就相當(dāng)于調(diào)用了#studb這個表格控件的reload方法了 然后數(shù)據(jù)就會自動刷新,每個控件的具體見文檔。
服務(wù)端數(shù)據(jù)處理我們還是用entityframework 我一般都用codefirst的方式 這東西跟他自己的mssql數(shù)據(jù)庫 結(jié)合的很好 用起很方便。
服務(wù)端代碼:
//查詢(帶分頁 [AjaxPro.AjaxMethod] public static WebApplication.DataEntity BindData(string keyword, int page, int rows) { //, ref int pageIndex, out int totalPage if (keyword == null) keyword = ""; int pageIndex = ; int pageSize = ; int totalPage; if (page != ) pageIndex = page; if (rows != ) pageSize = rows; MyDb db = new MyDb(); var data = from studentInfo in db.Students where studentInfo.name.Contains(keyword) select new { stuNo = studentInfo.stuNo, name = studentInfo.name, age = studentInfo.age, gradName = studentInfo.grad.gradName }; //var data = from studentInfo in db.Students where studentInfo.name.Contains(keyword) select studentInfo; totalPage = data.Count() % pageSize == ? data.Count() / pageSize : data.Count() / pageSize + ; if (pageIndex > totalPage) pageIndex = totalPage; else if (pageIndex < ) pageIndex = ; //var dt = DataList<object>.Create(data.OrderBy(r => r.stuNo), new StudentsInfo(), pageIndex, pageSize).Value; object dt=null ; if(data.Count()>) dt= DataList<object>.Create(data.OrderBy(r => r.stuNo), new { stuNo = , name = "", age = , gradName = "" }, pageIndex, pageSize).Value; WebApplication.DataEntity result = new WebApplication.DataEntity(); result.total = data.Count(); result.rows = dt; return result; }
關(guān)于數(shù)據(jù)部分 和EF linq 分頁那些我就不貼出來了 完整示例下載里面有。走走看吧 試試看吧 完全無刷新 服務(wù)端分頁,感覺棒棒噠
搜索那個我也不想說了哈 就是重新載入下數(shù)據(jù)而已,刪除是通過自定義 列的方式 傳id到j(luò)s函數(shù) 然后調(diào)用服務(wù)端刪除。然后要說下 錄入功能 以及easyui自帶 的表單驗證也是相當(dāng)方便的。
新建一個div 作為彈出層 里面有一個錄入信息的表格 各種html控件 只要寫上easyui對應(yīng)的樣式 就自動渲染了 看彈出層的 class="easyui-dialog" data-options="closed:true,title:'新學(xué)生注冊',modal:true"
其實(shí)很簡單噻看字面意思就明白了 這些參數(shù) 都在easyui的文檔里有。驗證 也是在html元素上寫data-options 就可以了, :
<div id="addBox" class="easyui-dialog" data-options="closed:true,title:'新學(xué)生注冊',modal:true" style="width: px; height: px"> <table class="auto-style"> <tr> <td>學(xué)生姓名:</td> <td> <input id="stuname" class=" easyui-textbox" data-options="required:true,missingMessage:'必填項!',validType:'email',invalidMessage:'email格式不正確!'" type="text" /></td> </tr> <tr> <td>班級: </td> <td> <input class="easyui-combobox" id="grad" name="grad" data-options="valueField:'id',textField:'gradName',required:true,missingMessage:'必填項!'" /></td> </tr> <tr> <td> <input id="saveBtn" onclick="saveClick()" type="button" value="保存" /></td> <td> <input id="Button" type="button" onclick="$('#addBox').dialog('close');" value="關(guān)閉" /></td> </tr> </table> </div>
新建按鈕:
<a id="Button1" onclick="$('#addBox').dialog('open');" class="easyui-linkbutton">加新的</a>
注意千萬別用button 元素 就是這種 <button>新加的</button> 這是個坑 ,折騰了好久。
保存按鈕調(diào)用 的js函數(shù):
//保存信息 function saveClick() { var isvaliok = $("#addBox").form('validate');//包起來的需要提交信息的那個div框的id if (isvaliok == false) { $.messager.show({ title: '提示', msg: '請完善不正確的項后再提交', showType: 'show' }); return; } var stu = {}; stu.name = $("#stuname").val(); stu.age = ; stu.GradId = $("#grad").combobox('getValue'); stu.gradName = $("#grad").combobox('getValue'); if (isNaN(stu.GradId)) stu.GradId = null; var rst = WebApplication.NewFolder.HelloAjaxNet.addStu(stu); if (rst.value == "ok") { $('#addBox').dialog('close'); $('#studb').datagrid('reload'); var gradData = WebApplication.NewFolder.HelloAjaxNet.getGrad().value; $('#grad').combobox({ data: gradData }).combobox('reload'); } else { $.messager.show({ title: '提示', msg: rst.error.Message + rst.value, showType: 'show' }); } }
注意到了噻:
var isvaliok = $("#addBox").form('validate');//包起來的需要提交信息的那個div框的id if (isvaliok == false) { $.messager.show({ title: '提示', msg: '請完善不正確的項后再提交', showType: 'show' }); return; }
在easyui里進(jìn)行驗證很簡單噻 只要在html代碼里把驗證格式定義好了 ,只需要傳入一個最外面容器控件的id $("#addBox").form('validate') 就自動幫我們驗證了。并且界面上還有提示 焦點(diǎn)自動放到第一個驗證不通過的控件上去了 完全不需要我們動手。
當(dāng)然我們在客戶端 document.ready()的時候 必須要綁定表格和下拉框的數(shù)據(jù):
$(function () { //頁面初始化 //載入表格數(shù)據(jù) bindDataToTb(); //載入班級下拉框 var gradData = WebApplication.NewFolder.HelloAjaxNet.getGrad().value; $('#grad').combobox({ data: gradData }).combobox('reload'); var fd = new FormData(); });
服務(wù)端保存的代碼:
//添加 [AjaxPro.AjaxMethod] public string addStu(StudentsInfo stu) { MyDb db = new MyDb(); if(stu.GradId==null) { if (string.IsNullOrEmpty(stu.gradName) == false) { Grad grd = new Grad(); grd.gradName = stu.gradName; Grad grdOld = db.grads.FirstOrDefault(r => r.gradName == stu.gradName); if(grdOld!=null) { return "類別已存在"; } else { db.grads.Add(grd); stu.grad = grd; } } } db.Students.Add(stu); db.SaveChanges(); return "ok"; }
服務(wù)端代碼 如果我們沒有這個id的類別我們就認(rèn)為這個類別是新的 ,新加一個類別 然后立即綁定 perfect 完美 ,棒棒噠
看上去是不是有模有樣。做管理類軟件還行。
這樣ui 那樣ui當(dāng)你需要自定義樣式的時候發(fā)現(xiàn)什么ui都是浮云,例如我說的國內(nèi)的寫js比較牛的 就已經(jīng)造出來很多ui了 ,表格是很漂亮 很強(qiáng)大。 其實(shí)很多功能你還是用不到 你想改還很困難 當(dāng)然我的js也是很菜的。 當(dāng)你用到另一套u(yù)i 的時候又要熟悉它那一套 。我只想用個簡簡單單的自定義分頁表格而已 或者像asp.net里的服務(wù)器控件repeat 流式布局 四個數(shù)據(jù)一行那種 你怎么做。 還是自己動手吧。php里面有前端模板。
我這里只是簡單從實(shí)際需求了解下angular的威力 php里面模板什么的都是浮云 新建一個webform HelloAjaxNetAngular.aspx
注意這個例子 服務(wù)端代碼我一律用上面的絲毫都不會變 只是前端變了,angularjs 的主打思想是mvvm 模式 就是wpf里面那種依賴屬性 動態(tài)綁定 ,不知道你們用過沒 反正我用過 感覺就一個字 爽 ,做這種數(shù)據(jù)庫平臺程序 mfc winform 都是渣。
angularjs 的基礎(chǔ)我就不介紹了 哈 直接從需求入手 做一個分頁表格 加 信息更新 功能
angularjs的網(wǎng)站是 http://www.angularjs.org/ 這個網(wǎng)址在國內(nèi)也是訪問不了的。一些相關(guān)的其他人的學(xué)習(xí)筆記有 http://www.angularjs.cn/ http://www.zouyesheng.com/angular.html
反正這兩個教程看了下對我沒 對我沒起到啥作用 感覺跟嚼木渣樣的 ,angularjs的理念雖然是mvvm 但是angularjs本身還是感覺晦澀難懂。
我就在這樣一個半懂不懂的狀態(tài)下寫了這個例子 ,所有的操作 幾乎都完全不需要向jquery那樣動dom 。真心感覺到了他的強(qiáng)大。前端就一個controller函數(shù) 管整個頁面,怎么一個一個的分 我也不明白 只知道controller 跟html限定一樣的樹狀結(jié)構(gòu)。沒在范圍的html元素不能訪問其controller里的 變量。
我們來看這個controller 函數(shù) ,我寫的時候也沒什么感覺 。就是感覺很存粹 就只感覺到兩個東西存在 。業(yè)務(wù)邏輯在操作數(shù)據(jù)。 就像在寫c#數(shù)據(jù)操作代碼樣:
function myCtr($scope) { var mod = [{ name: 'xiang', age: }, { name: 'xiang', age: }, { name: 'xiang', age: }]; $scope.data = mod; $scope.curobj = {}; $scope.pageEntity = { total: , rows: , page: , pgmsg: '' } //初始化默認(rèn)第一頁 $scope.initPage = function () { var firstPage = WebApplication.NewFolder.HelloAjaxNetAngular.BindData($("#txtkeyword").val(), $scope.pageEntity.page, $scope.pageEntity.rows); $scope.data = firstPage.value.rows; var pageEntityMod = {}; pageEntityMod.total = firstPage.value.total; pageEntityMod.rows = $scope.pageEntity.rows; pageEntityMod.page = $scope.pageEntity.page; var totalpage = pageEntityMod.total % pageEntityMod.rows == ? parseInt(pageEntityMod.total / pageEntityMod.rows) : parseInt(pageEntityMod.total / pageEntityMod.rows) + ; pageEntityMod.pgmsg = "共 " + pageEntityMod.total + "條記錄 每頁 " + pageEntityMod.rows + "條,共 " + totalpage + "頁 ,當(dāng)前第 " + pageEntityMod.page + "頁"; $scope.pageEntity = pageEntityMod; $scope.curobj = {}; } //更新當(dāng)前 選定的 $scope.modifyCur = function () { var rst = WebApplication.NewFolder.HelloAjaxNetAngular.updateStu($scope.curobj) //刷新表格 當(dāng)前選中信息 復(fù)原 $scope.initPage(); alert(rst.value); } //下翻頁 $scope.nextPage = function () { var totalpage = $scope.pageEntity.total % $scope.pageEntity.rows == ? parseInt($scope.pageEntity.total / $scope.pageEntity.rows) : parseInt($scope.pageEntity.total / $scope.pageEntity.rows) + ; var pagenewnum = $scope.pageEntity.page + ; if (pagenewnum <= totalpage) $scope.pageEntity.page += ; $scope.initPage(); } //上翻頁 $scope.previousPage = function () { var pagenewnum = $scope.pageEntity.page - ; if (pagenewnum >= ) $scope.pageEntity.page -= ; $scope.initPage(); } //搜索 $scope.search = function () { } //選中一行 $scope.del = function (sender, curobj) { //所有行的顏色還原//設(shè)置選中那一行的顏色 var rows = $(sender.target).parent().parent().parent().find("tbody").find("tr"); for (var i = ; i < rows.length; i++) { $(rows[i]).css("background", "white"); } $(sender.target).parent().css("background", "#ffed"); $scope.curobj = curobj; } //首次先調(diào)用下 以獲取第一頁 $scope.initPage(); }
界面部分:
<div ng-controller="myCtr" id="mygrid"> <input id="txtkeyword" type="text" /><input ng-click="initPage()" type="button" value="搜索" /> <br /> <br /> <div style="height: px"> <table cellspacing="" border="" class="gridtable"> <thead> <th width="px">name</th> <th width="px">age</th> </thead> <tbody ng-repeat="stu in data"> <tr ng-click='del($event,stu)' style="background-color: white"> <td>{{stu.name}}</td> <td>{{stu.age}}</td> </tr> </tbody> </table> </div> <div id="pager"> <a href="#" ng-click="previousPage()">上一頁</a> <a href="#" ng-click="nextPage()">下一頁</a> <span>{{pageEntity.pgmsg}}</span> </div> <div> 姓名:<input type="text" value="{{curobj.name}}" ng-model="curobj.name" /><br /> 年齡:<input type="text" value="{{curobj.age}}" ng-model="curobj.age" /> <input id="Button" type="button" ng-click="modifyCur()" value="更改" /> </div> </div>
看到我自己搞了一個數(shù)據(jù)綁定函數(shù) 參照easyui里datagrid的loader。 第一次請求得到分頁信息后 我立即把數(shù)據(jù)綁定到表格 你可以看到完全就像做模板樣的,然后初始化自己的分頁控件。 在ng-click 的時候像原來一樣觸發(fā)客戶端單擊 然后調(diào)用controller里的方法去更新數(shù)據(jù) ,注意僅僅是根據(jù)業(yè)務(wù)邏輯去更新數(shù)據(jù) 其他的不需要做。關(guān)于上面兩段代碼不明白的自行去看angularjs 入門和數(shù)據(jù)綁定 用不了10分鐘,
由于有wpf那種雙向綁定機(jī)制,數(shù)據(jù)模型 數(shù)據(jù)更新了 頁面內(nèi)容自動跟著變。甚至你可以看到我編輯下面文本框里的數(shù)據(jù)的時候 都還沒提交 上面表格的數(shù)據(jù)就跟著變 因為他們的數(shù)據(jù)是從同一個地方來的,看著恍惚都感覺是ajax哈。
上面所有示例的項目源碼下載 可直接運(yùn)行,由于引了些外部庫進(jìn)來十兆差點(diǎn)放不下
說點(diǎn)后話
其實(shí)照互聯(lián)網(wǎng)這樣推動發(fā)展下去的話 前端會統(tǒng)一 前端才是王道 到時候一個網(wǎng)頁 就是一個系統(tǒng) 一個客戶端。 后端只負(fù)責(zé)數(shù)據(jù)和安全。 現(xiàn)在的什么html5不是幾乎都成為工業(yè)標(biāo)準(zhǔn)了么 有些嵌入式設(shè)備都支持
暫時像博客園里我看到的有幾個講的 前后端天人合一的那種mvc模式 前端后端操作同一個model 前端更新屬性了有一種機(jī)制自動就更新到后端持久化到數(shù)據(jù)庫去了 或者后端更新model的某個屬性 前端html頁面的值自動就變了。 不是說做不到 畢竟牛人這么多 ,我覺得至少還不穩(wěn)定吧。
各種ui有easyui ligerui fineui miniui Devexpress 還有很多js框架 seajs requirejs JavaScriptMVC backbone avalonjs knockout angular jquery jqueryui js真是屎一樣的東西啊各種框架學(xué)都學(xué)不完
尤其是軟件行業(yè)日新月異 基于框架 和平臺的技術(shù)太多了 不精通某樣技術(shù)沒關(guān)系 能使用就行 ,但是作為一個技術(shù)人員 你至少得精通一樣 或者一門技術(shù) 要不然就是個搬磚的 很遺憾 我基本還在搬磚的路上。寫業(yè)務(wù)代碼就是用一年的經(jīng)驗混十年,寫業(yè)務(wù)代碼是他的工作 工作之余還得有點(diǎn)精神追究 研究下事情的本質(zhì) ,只要是還不錯的程序員 做這種數(shù)據(jù)庫系統(tǒng)久了都會自己搞點(diǎn)能快速開發(fā)的所謂的小框架 積累一些自己的工具庫 和經(jīng)驗。
在工作上不要有什么偏見 只要他每天把業(yè)務(wù)代碼寫的出來 軟件開發(fā)也只是一門職業(yè) 你不是英雄 ,目的是解決問題 不是轉(zhuǎn)牛角尖。
我本人對js是不怎么感冒的 js也很爛,當(dāng)初設(shè)計這個東西的時候就不完善給我們使用它造成了各種阻礙 ,但是你做web開發(fā)又不得不用它。這里也并不是對做前端的有什么偏見 感謝那些前端吃的很透的人 像司徒正美那些高手 制造了這些工具讓我們更容易的去完成這些網(wǎng)站程序。
相關(guān)文章
AngularJS中的$parse服務(wù)與$eval服務(wù)用法實(shí)例
這篇文章主要介紹了AngularJS中的$parse服務(wù)與$eval服務(wù)用法,結(jié)合實(shí)例形式分析了AngularJS中$parse服務(wù)與$eval服務(wù)的功能、使用方法與相關(guān)注意事項,需要的朋友可以參考下2023-05-05Angular 2.x學(xué)習(xí)教程之結(jié)構(gòu)指令詳解
結(jié)構(gòu)指令通過添加和刪除 DOM 元素來更改 DOM 布局。Angular 中兩個常見的結(jié)構(gòu)指令是 *ngIf 和 *ngFor,下面這篇文章主要給大家介紹了關(guān)于Angular 2.x結(jié)構(gòu)指令的相關(guān)資料,需要的朋友可以參考下。2017-05-05Angular2.0/4.0 使用Echarts圖表的示例代碼
本篇文章主要介紹了Angular2.0/4.0 使用Echarts的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-12-12淺談Angular2 ng-content 指令在組件中嵌入內(nèi)容
本篇文章主要介紹了淺談Angular2 ng-content 指令在組件中嵌入內(nèi)容,具有一定的參考價值,有興趣的可以了解一下2017-08-08深入理解Angularjs中$http.post與$.post
本篇文章主要介紹了深入理解Angularjs中$http.post與$.post ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-05-05Angularjs過濾器實(shí)現(xiàn)動態(tài)搜索與排序功能示例
這篇文章主要介紹了Angularjs過濾器實(shí)現(xiàn)動態(tài)搜索與排序功能,涉及AngularJS過濾器相關(guān)搜索、查詢、排序操作技巧,需要的朋友可以參考下2017-12-12AngulaJS路由 ui-router 傳參實(shí)例
本篇文章主要介紹了AngulaJS路由 ui-router 傳參實(shí)例 ,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04