<address id="ttjl9"></address>

      <noframes id="ttjl9"><address id="ttjl9"><nobr id="ttjl9"></nobr></address>
      <form id="ttjl9"></form>
        <em id="ttjl9"><span id="ttjl9"></span></em>
        <address id="ttjl9"></address>

          <noframes id="ttjl9"><form id="ttjl9"></form>

          首頁

          根據輸入實時發送請求(防抖函數)

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          有這樣一種常見的需求:有一個搜索框,需要根據用戶的輸入進行實時的查詢。也就是說用戶每輸入一個字符就要發送一次請求。

          想到的做法是監聽輸入框的keyup時間然后在回調里發送異步請求。

          這樣做的不足也很明顯:

          其實我們并不需要用戶每次輸入時都發送請求,這樣會給服務器造成不必要的壓力。

          因為發送的是異步請求,有可能查詢的結果和最后輸入的內容并不匹配。

          如何解決以上兩種問題呢? 有兩種解決方案

          首先我們規定當用戶停止輸入1秒(具體時間根據自己需求而定)后再根據輸入框的值發送請求。
          其次我們利用定時器來解決以上問題。
          第一種方案:直接看代碼吧

          vat timer
          $('.input').on('keyup', function(e) {
              clearTimeout(timer)
              timer = setTimeout(function() {
                // do something
              }, 1000)
          })

          首先定義一個定時器timer
          監聽輸入框的keyup事件,在回調函數里先清除timer,這一步總能保證在用戶停止輸入1秒后執行最后一個timer。如果用戶輸入的間隔小于1秒就不會執行timer
          這么寫似乎不太抽象,而且定義了一個全局變量timer,不友好!稍加改動一下:

          function debounce(func,delay){
              var timer
              return function(){
                  clearTimeout(timer)
                  var event = arguments[0]  // 獲取原生event參數
                  timer = setTimeout(function(){
                      func(event)
                  },delay)
              }
          }
          function handle(event){
              // do something 
          }
          $('.input').on('keyup', debounce(handle, 1000))

          這樣是不是復用性更高,我們只需要在handle函數中寫我們的處理邏輯就可以了。而且沒有了全局變量,避免了全局污染的可能??!

          *第二種方案: *

          var lastTime
          $('.input').on('keyup', function(e) {
              lastTime = e.timeStamp
              setTimeout(function() {
                  console.log('timeout')
                  if (lastTime == e.timeStamp) {
                      // do something
                  }
              }, 1000)
          })

          首先定義一個時間戳來保存最后一次輸入的時間
          然后1秒后在定時器里判斷保存的時間戳和觸發事件的時間戳e.timeStamp是否相同,只要1秒內又輸入了內容,e.timeStamp就回變化。
          但是這種寫法有個弊端,用戶鍵入幾次就會執行幾次setTimeout,也就是說當用戶連續鍵入多個字符后,會有多個任務被推入待執行隊列,然后每隔1秒執行,只是在執行的時候判斷要不要發送異步請求,這種方式不會發送多余的異步請求,但是會執行多余的任務,這無疑浪費了性能。

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。

          JQuery中的DOM操作(1)

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          DOM樹

                                           

              在訪問頁面時,需要與頁面中的元素進行交互式的操作。在操作中,元素的訪問是最頻繁、最常用的,主要包括對元素屬性、內容、值CSS的操作。

          一、操作元素的屬性

          attr()   prop() 獲取或設置元素的屬性值

          兩者區別:簡單來說,對于HTML元素本身就帶有的固有屬性,在處理時,使用prop方法。對于HTML元素我們自己自定義的DOM屬性,在處理時,使用attr方法。

          針對屬性對象不同

          prop( )是針對Dom元素屬性,attr( )針對HTML元素屬性,和attribute與property區別一樣。

          用于設置的屬性值類型不同

          attr()函數操作的是文檔節點的屬性,因此設置的屬性值只能是字符串類型,如果不是字符串類型,也會調用其toString()方法,將其轉為字符串類型。

          prop()函數操作的是JS對象的屬性,因此設置的屬性值可以為包括數組和對象在內的任意類型。

          應用版本不同

          attr()是jQuery 1.0版本就有的函數,prop()是jQuery 1.6版本新增的函數。毫無疑問,在1.6之前,你只能使用attr()函數;1.6及以后版本,你可以根據實際需要選擇對應的函數。

          其他不同

          對于表單元素的checked、selected、disabled等屬性,Attr()方法拿不到值,請使用prop()函數來設置或獲取checked、selected、disabled等屬性。對于其它能夠用prop()實現的操作,也盡量使用prop()函數。如下圖代碼:

          <!DOCTYPE html>
          <html>
          <head lang="en">
              <meta charset="UTF-8">
              <title></title>
              <script src="js/jquery-1.9.1.min.js"></script>
          </head>
          <body>
          <input type="button" id="btn1" value="按鈕">
          <input type="button" id="btn2" value="按鈕">
          <script>
              //操作元素的屬性
              //attr() prop()獲取或設置元素的屬性值
              $("#btn1").attr("value","按鈕1");//將#btn1的value值改為按鈕1
              $("#btn1").prop("value","按鈕2");//將#btn1的value值改為按鈕2
              console.log( $("input[type='button']").prop("value"));//獲取#btn1的value值,輸出為按鈕2
              console.log($("#btn2").attr("value"));//獲取#btn1的value值,輸出為按鈕
              //設置多個屬性值
              $("input[type='button']").prop({
                  width:"200px",
                  value:"hello"
              });//同時設置寬度為100px,value值為hello
              //根據輸出結果,width值設置失敗,value值設置成功
              console.log($("input[type='button']").prop("width"));//0
              console.log($("input[type='button']").attr("width"));//0
              $("input[type='button']").attr({
                  width:"200px",
                  value:"HELLO"
              })//同時設置寬度為200px,value值為HELLO
              //根據輸出結果可以看到,width和value均設置成功
              console.log($("input[type='button']").prop("width"));//0
              console.log($("input[type='button']").attr("width"));//200px
           
          //    var btn=$("input[type='button']");
          //    btn.attr("data-src","pink");
          //    console.log(btn.attr("data-src"));//pink
          //    console.log(btn.prop("data-src"));//undefined
              
              
              var btn=$("input[type='button']");
              btn.prop("data-src","pink");
              console.log(btn.attr("data-src"));//undefined
              console.log(btn.prop("data-src"));//pink
           
          </script>
          二、刪除元素的屬性

          removeAttr( name ) ,其中name為元素屬性的名稱

          removeProp( name ) ,其中name為元素屬性的名稱

           

          三、元素內容的操作

          在JQuery中,操作元素內容的方法包括html( )和text( )。前者與JavaScript中的innerHTML屬性類似,即獲取或設置元素的HTML內容;后者類似于JavaScript中的innerText屬性,即獲取或設置元素的文本內容。區別如下:

          語法格式 參數說明 功能描述
          html() 無參數 用于獲取元素的HTML內容
          html(val) val參數為元素的HTML內容 用于設置元素的HTML內容
          text() 無參數 用于獲取元素 的文本內容
          text(val) val參數為元素的文本內容 用于設置元素的文本內容
          <script>
              //js中的寫法 innerHTML  innerText
              var sd=document.getElementById("block");
              sd.innerText="小貓吃魚";
              console.log(sd.innerHTML);//小貓吃魚
              console.log(sd.innerText);//小貓吃魚
          //    //jquery  html()  text() 和js一致  獲取或設置元素的html值或文本值
              console.log($("#block").html());//小貓吃魚
              console.log($("#block").text());//小貓吃魚
              $("#block").text("小貓抓老鼠");//修改innerText內容
              console.log($("#block").html());//小貓抓老鼠
              console.log($("#block").text());//小貓抓老鼠
              $("#block").html("小貓吃肉肉");//修改innerHTML內容
              console.log($("#block").html());//小貓吃肉肉
              console.log($("#block").text());//小貓吃肉肉
          </script>
          四、操作表單元素的值

          val()   獲取或設置表單元素的value值

          <!DOCTYPE html>
          <html>
          <head lang="en">
              <meta charset="UTF-8">
              <title></title>
              <script src="js/jquery-1.9.1.min.js"></script>
          </head>
          <body>
          <input type="text" id="txt" value="請輸入...">
          <script>
              console.log( $("#txt").val());// 獲取#txt的value值  輸出為:請輸入...
              $("#txt").val("12345");//修改#txt的value值為12345
              console.log( $("#txt").val());//12345
          </script>
          </body>
          </html>
          五、元素樣式的操作

          1.直接設置元素樣式值

          在JQuery中,通過css()方法為某個指定的元素設置樣式值,語法格式如下:

          css(name,value) ,其中name為樣式名稱,value為樣式的值

          css()可以設置樣式也可以獲取樣式



          2.增加CSS類別

          通過addClass()方法增加元素類別的名稱,語法格式如下:

          addClass(class) ,其中參數class為類名稱,可以同時增加多個,用空格隔開即可,如addClass(class0 class1 class2 ...)

          3.刪除CSS類別

          與addClass()方法相對應,removeClass()方法用于刪除類別,語法格式與addClass()相同,如果不設定參數,則刪除元素中的所有類名稱

          4.類別切換

          通過toggleClass()方法切換不同的元素類別,語法格式如下:

          toggleClass(class) ,其中參數class為類別名稱,其功能是當元素中含有名稱為class的CSS類別時,刪除該類別,若沒有,則增加該類別

          <!DOCTYPE html>
          <html>
          <head lang="en">
              <meta charset="UTF-8">
              <title></title>
              <script src="js/jquery-1.9.1.min.js"></script>
          </head>
          <body>
          <button id="btn" class="btndata">按鈕</button>
          <script>
              $("#btn").addClass("btn1");//追加一個類名稱
              $("#btn").addClass("btn2 btn3");//追加多個類名稱
              $("#btn").removeClass("btn2 btn1");//移除類名稱
              $("#btn").removeClass();//移除所有類名稱
              $("#btn").toggleClass("btn1");//類的切換 toggleClass()  如果有類名稱則替換  如果沒有就添加
          </script>
          </body>
          </html>
          六、jquery操作子父節點

          children()  找父元素里面的子節點

          <!DOCTYPE html>
          <html>
          <head lang="en">
              <meta charset="UTF-8">
              <title></title>
              <script src="js/jquery-1.9.1.min.js"></script>
          </head>
          <body>
          <ul>
              <li class="lilist">1</li>
              <li class="lidata">2</li>
              <span>6</span>
              <li class="lilist">3</li>
              <span>5</span>
              <li class="lilist">4</li>
              <span>7</span>
          </ul>
          <script>
                  console.log($("ul").children());//輸出ul 下的所有子節點
                  console.log($("ul").children()[0]);//輸出ul下索引為0的子節點
                  console.log($("ul>li").first());//輸出ul里面第一個li
                  console.log($("ul>li").last());//輸出ul里面最后一個li
                  console.log($("ul>li").eq(2));//eq()  根據索引找元素
                  console.log($("ul>li").first().siblings(".lilist"));//找同胞元素  輸出和first()相同類名稱的元素
                  console.log($("ul>li").eq(1).prev());//找當前元素的前一個元素
                  console.log($("ul>li").eq(2).prevAll("span"));//當前元素前面的所有指定元素
                  console.log($("ul>li").eq(2).prevAll());//當前元素前面的所有元素
                  console.log($("ul>li").eq(1).next());//找當前元素的下一個元素
                  console.log($("ul>li").eq(1).nextAll("li"));//當前元素后面的所有指定元素
                  console.log($("ul>li").eq(1).nextAll());//當前元素后面的所有元素
                  console.log($("ul>li").eq(0).is(".qq"));//is() 判斷當前對象是誰  輸出true  or  false  當前元素與類名稱相符  輸出true
          </script>
          </body>
          </html>
          七、JQuery中的尺寸問題

          下面以高度為例進行說明

          <!DOCTYPE html>
          <html>
          <head lang="en">
              <meta charset="UTF-8">
              <title></title>
              <script src="js/jquery-1.9.1.min.js"></script>
              <style>
                 .ss{
                     width: 200px;
                     height: 200px;
                     margin: 10px 10px;
                     padding: 20px 20px;
                 }
              </style>
          </head>
          <body>
          <div class="ss"></div>
          <script>
                  console.log($(".ss").height());//200  可視區域  不包括內外邊距 
                  console.log($(".ss").innerHeight());//240  包括內邊距的距離  
                  console.log($(".ss").outerHeight());//240  包括內邊距的距離
          </script>
          </body>
          </html>
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          vue-router的兩種模式的區別

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          1、大家都知道vue是一種單頁應用,單頁應用就是僅在頁面初始化的時候加載相應的html/css/js一單頁面加載完成,不會因為用戶的操作而進行頁面的重新加載或者跳轉,用javascript動態的變化html的內容

          優點: 良好的交互體驗,用戶不需要刷新頁面,頁面顯示流暢, 良好的前后端工作分離模式,減輕服務器壓力,
          缺點: 不利于SEO,初次加載耗時比較多

          2、hash模式
          vue-router默認的是hash模式—使用URL的hash來模擬一個完整的URL,于是當URL改變的時候,頁面不會重新加載,也就是單頁應用了,當#后面的hash發生變化,不會導致瀏覽器向服務器發出請求,瀏覽器不發出請求就不會刷新頁面,并且會觸發hasChange這個事件,通過監聽hash值的變化來實現更新頁面部分內容的操作

          對于hash模式會創建hashHistory對象,在訪問不同的路由的時候,會發生兩件事:
          HashHistory.push()將新的路由添加到瀏覽器訪問的歷史的棧頂,和HasHistory.replace()替換到當前棧頂的路由

          在這里插入圖片描述

          在這里插入圖片描述

          3、history模式

          主要使用HTML5的pushState()和replaceState()這兩個api來實現的,pushState()可以改變url地址且不會發送請求,replaceState()可以讀取歷史記錄棧,還可以對瀏覽器記錄進行修改

          window.history.pushState(stateObject, title, URL)
          window.history.replaceState(stateObject, title, URL)

          包括back,forward , go 三個方法
          history.go(-2);//后退兩次
          history.go(2);//前進兩次
          history.back(); //后退
          hsitory.forward(); //前進

          區別:

          前面的hashchange,你只能改變#后面的url片段。而pushState設置的新URL可以是與當前URL同源的任意URL。
          history模式則會將URL修改得就和正常請求后端的URL一樣,如后端沒有配置對應/user/id的路由處理,則會返回404錯誤

          參考于: https://www.cnblogs.com/ceceliahappycoding/p/10552620.html

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。

          ElementUI表格中獲取當前行數據(實現對table數據的修改和刪除)

          seo達人

          如果您想訂閱本博客內容,每天自動發到

          前言

          在此之前,已經實現了vue+ElementUI的跨域查詢并渲染查詢結果的功能,現在想要在每一行中添加修改和刪除的按鈕。于是乎就需要獲取當前行的數據,于是就有了下面兩種方式的獲取。


          1 獲取當前行的數據

          1.1 我的笨辦法

          這里是我記錄自己的學習過程,這個方法也能實現,但是麻煩,如果您只是為了尋找最終方案,請直接查看1.2章節。

          首先我查看了官方文檔,打算使用對話框來渲染修改頁面和刪除警告頁面。這個實現起來很簡單,就是對按鈕綁定一個click事件,然后控制對話框的顯示和隱藏:


          <el-table @row-click="handleEdit" :data="dengmiQueryForm.list" stripe border width="100%" height="350">

          <el-table-column prop="mimian" label="謎面" width="300" fixed="left">

          </el-table-column>

          <el-table-column prop="dengmiSeq" label="序號">

          </el-table-column>

          <el-table-column prop="mimu" label="謎目">

          </el-table-column>

          <el-table-column prop="mige" label="謎格">

          </el-table-column>

          <el-table-column prop="midi" label="謎底">

          </el-table-column>

          <el-table-column prop="zuozhe" label="作者">

          </el-table-column>

          <el-table-column prop="mizhu" label="注">

          </el-table-column>

          <el-table-column prop="shangxi" label="賞析">

          </el-table-column>

          <el-table-column prop="leixing" label="類型">

          </el-table-column>

          <el-table-column label="操作" fixed="right" width="200px">

          <el-col :span="10">

          <el-tooltip effect="dark" content="編輯當前行" placement="top">

          <el-button size="mini" @click="dengmiQueryForm.dialogVisible = true">編輯</el-button>

          </el-tooltip>

          </el-col>

          </el-table-column>

          </el-table>

          <div style="margin-top: 5px;"></div><!--這個只是為了在頁面上顯示間隔-->

          <el-dialog title="編輯燈謎" :visible.sync="dengmiQueryForm.dialogVisible">

          <el-form :model="modifyForm">

          <el-form-item label="謎面" :label-width="modifyForm.formLabelWidth">

          <el-input v-model="modifyForm.mimian" auto-complete="off"></el-input>

          </el-form-item>

          <el-form-item label="謎目" :label-width="modifyForm.formLabelWidth">

          <el-input v-model="modifyForm.mimu" auto-complete="off"></el-input>

          </el-form-item>

          </el-form>

          <div slot="footer" class="dialog-footer">

          <el-button @click="dengmiQueryForm.dialogVisible = false">取 消</el-button>

          <el-button type="primary" @click="dengmiQueryForm.dialogVisible = false">確 定</el-button>

          </div>

          </el-dialog>


          <script>

          export default {

          name: "dengmiQuery",

          comments: {

          DengmiModify

          },

          data() {

          return {

          modifyForm:{

          formLabelWidth:'120px',

          mimian:'',

          mimu:''

          },

          dengmiQueryForm: {

          dialogDeleteVisible:false,

          dialogVisible: false,

          list: []

          }

          };

          },

          methods: {

          submitForm(formName) {

          console.log(formName.mimu);

          this.$http.get('http://localhost:909/dengmi/showDengmi2').then(function (success) {

          console.log("This request is succeed! Here is the response:");

          this.dengmiQueryForm.list = success.body.result;

          this.dengmiQueryForm.requestResult = true;

          }, function (error) {

          console.log("This request is failed! Here is the response:");

          console.log(error);

          this.dengmiQueryForm.requestResult = false;

          })

          },

          handleEdit(row) {

          this.dengmiQueryForm.deleteShow = row.mimian + "(" + row.mimu + ")" + row.midi + "/" + row.zuozhe;

          this.modifyForm.mimian=row.mimian;

          this.modifyForm.mimu=row.mimu;

          }

          }

          }

          </script>


          如上代碼,是在el-table標簽上綁定了行單擊事件*@row-click=“handleEdit”*,該方法的參數row即為當前行的數據。

          在handleEdit方法中,通過對data中的參數賦值,然后新增窗口中通過使用data中的參數來獲取當前行的數據,從而實現將當前行的數據傳遞到新的對話框中。


          這個方法雖然也能實現需求,但是比較麻煩:當有別的操作的時候,比如我再添加一個刪除操作,就需要在點擊刪除按鈕的時候,獲取當前行的數據,然后進行刪除操作;而因為新增和刪除使用的是不同的對話框,其取值也是要通過handleEdit方法來獲取,因此,當按鈕較多,或者當前行的字段值較多的時候,就需要在handleEdit中對許多許多的變量進行賦值,而且是對所有按鈕的所有參數。這個工作量想想還是挺恐怖的。


          1.2 使用slot-scope獲取數據

          slot-scope是屬于VUE的東東,叫做插槽;至于插槽是個什么東東,來戳這里。

          在操作列,對操作按鈕先用帶有slot-scope屬性的dom進行包裝,即可獲取當前行的數據,具體的代碼,除了操作列不同外,還需要刪除el-table標簽中綁定的*@row-click*方法,剩下的都一樣:


          <el-table-column label="操作嘗試2">

          <template slot-scope="scope">

          <el-button type="text" @click="checkDetail(scope.row)">查看詳情</el-button>

          </template>

          </el-table-column>

          <script>

          export default {

                 name: "dengmiQuery",

                 data() {

                     return {

                         modifyForm:{

                             formLabelWidth:'120px',

                             mimian:'',

                             mimu:''

                         },

                         dengmiQueryForm: {

                             dialogVisible: false,

                             list: [],

                         }

                     };

                 },

                 methods: {

                     checkDetail(val){

                         console.log(val)

                     }


                 }

             }

            </script>


          通過<template slot-scope=“scope”>來定義當前行的數據對象,然后通過scope.row來獲取當前行的數據。


          全部代碼

          <template>

             <div>

                 <el-form :model="dengmiQueryForm" ref="dengmiQueryForm" label-width="100px" class="demo-ruleForm" size="mini">

                     <el-row>

                         <el-col span="8">

                             <el-form-item label="謎面">

                                 <el-input v-model="dengmiQueryForm.mimian"></el-input>

                             </el-form-item>

                         </el-col>

                         <el-col span="8">

                             <el-form-item label="謎目">

                                 <el-input v-model="dengmiQueryForm.mimu"></el-input>

                             </el-form-item>

                         </el-col>

                         <el-col span="8">

                             <el-form-item label="謎格">

                                 <el-input v-model="dengmiQueryForm.mige"></el-input>

                             </el-form-item>

                         </el-col>

                     </el-row>

                     <el-row>

                         <el-col span="8">

                             <el-form-item label="謎底">

                                 <el-input v-model="dengmiQueryForm.midi"></el-input>

                             </el-form-item>

                         </el-col>

                         <el-col span="8">

                             <el-form-item label="作者">

                                 <el-input v-model="dengmiQueryForm.zuozhe"></el-input>

                             </el-form-item>

                         </el-col>

                         <el-col span="8">

                             <el-form-item label="謎底字數">

                                 <el-input v-model="dengmiQueryForm.midiLength"></el-input>

                             </el-form-item>

                         </el-col>

                     </el-row>

                     <el-row>

                         <el-col>

                             <el-button type="primary" @click="submitForm" icon="el-icon-search">查詢</el-button>

                             <el-button type="warning" @click="resetForm" icon="el-icon-search" plain>重置</el-button>

                         </el-col>

                     </el-row>

                 </el-form>

                 <el-header></el-header>

                 <div v-if="dengmiQueryForm.requestResult">

                     <el-table :data="dengmiQueryForm.list.slice((dengmiQueryForm.currentPage-1)*dengmiQueryForm.pagesize,dengmiQueryForm.currentPage*dengmiQueryForm.pagesize)"

                               stripe border width="100%" height="350">

                         <el-table-column type="index" fixed="left"></el-table-column>

                         <el-table-column prop="mimian" label="謎面" width="300" fixed="left">

                         </el-table-column>

                         <el-table-column prop="dengmiSeq" label="序號">

                         </el-table-column>

                         <el-table-column prop="mimu" label="謎目">

                         </el-table-column>

                         <el-table-column prop="mige" label="謎格">

                         </el-table-column>

                         <el-table-column prop="midi" label="謎底">

                         </el-table-column>

                         <el-table-column prop="zuozhe" label="作者">

                         </el-table-column>

                         <el-table-column prop="mizhu" label="注">

                         </el-table-column>

                         <el-table-column prop="shangxi" label="賞析">

                         </el-table-column>

                         <el-table-column prop="leixing" label="類型">

                         </el-table-column>

                         <el-table-column label="操作" fixed="right" width="200px">

                             <el-row>

                                 <el-col :span="10">

                                     <el-tooltip effect="dark" content="編輯當前行" placement="top">

                                         <el-button size="mini" @click="dengmiQueryForm.dialogVisible = true">編輯</el-button>

                                     </el-tooltip>

                                 </el-col>

                                 <el-col :span="10">

                                     <el-tooltip effect="light" content="刪除當前行" placement="top">

                                         <el-button size="mini" @click="dengmiQueryForm.dialogDeleteVisible = true" type="danger" plain>刪除</el-button>

                                     </el-tooltip>

                                 </el-col>

                             </el-row>

                         </el-table-column>

                         <el-table-column label="操作嘗試2">

                             <template slot-scope="scope">

                                 <el-button type="text" @click="checkDetail(scope.row)">查看詳情</el-button>

                             </template>

                         </el-table-column>

                     </el-table>

                     <div style="margin-top: 5px;"></div>

                     <el-pagination

                             prev-text="上一頁"

                             next-text="下一頁"

                             background

                             @size-change="handleSizeChange"

                             @current-change="handleCurrentChange"

                             :current-page="dengmiQueryForm.currentPageA"

                             :page-sizes="[5,10,50,100]"

                             :page-size="5"

                             layout="total, sizes, prev, pager, next, jumper"

                             :total="dengmiQueryForm.list.length">

                     </el-pagination>

                 </div>

                 <div v-else>

                     請求失??!

                 </div>

                 <el-dialog title="編輯燈謎" :visible.sync="dengmiQueryForm.dialogVisible">

                     <el-form :model="modifyForm">

                         <el-form-item label="謎面" :label-width="modifyForm.formLabelWidth">

                             <el-input v-model="modifyForm.mimian" auto-complete="off"></el-input>

                         </el-form-item>

                         <el-form-item label="謎目" :label-width="modifyForm.formLabelWidth">

                             <el-input v-model="modifyForm.mimu" auto-complete="off"></el-input>

                         </el-form-item>

                     </el-form>

                     <div slot="footer" class="dialog-footer">

                         <el-button @click="dengmiQueryForm.dialogVisible = false">取 消</el-button>

                         <el-button type="primary" @click="dengmiQueryForm.dialogVisible = false">確 定</el-button>

                     </div>

                 </el-dialog>

                 <el-dialog title="刪除燈謎" :visible.sync="dengmiQueryForm.dialogDeleteVisible">

                     <h1><span style="color: red"><strong>確定刪除該行數據?刪除后不可恢復!</strong></span></h1>

                     <el-form>

                         <el-form-item label="當前行數據">

                             <el-col :span="18">

                                 <el-input v-model="dengmiQueryForm.deleteShow" readonly></el-input>

                             </el-col>

                         </el-form-item>

                     </el-form>

                     <div slot="footer" class="dialog-footer">

                         <el-button @click="dengmiQueryForm.dialogDeleteVisible = false">取 消</el-button>

                         <el-button type="primary" @click="dengmiQueryForm.dialogDeleteVisible = false">確 定</el-button>

                     </div>

                 </el-dialog>

             </div>

          </template>

          <script>

             export default {

                 name: "dengmiQuery",

                 data() {

                     return {

                         modifyForm:{

                             formLabelWidth:'120px',

                             mimian:'',

                             mimu:''

                         },

                         dengmiQueryForm: {

                             deleteShow:'',

                             dialogDeleteVisible:false,

                             dialogVisible: false,

                             currentRow: null,

                             visibleA: false,

                             currentPage: 1, //初始頁

                             pagesize: 5,    //    每頁的數據

                             currentPageA: 1,

                             mimian: '',

                             mimu: '',

                             mige: '',

                             midi: '',

                             zuozhe: '',

                             midiLength: '',

                             list: [],

                             requestResult: true,

                             thisRowData:{}

                         }

                     };

                 },

                 methods: {

                     submitForm(formName) {

                         console.log(formName.mimu);

                         this.$http.get('http://localhost:909/dengmi/showDengmi2').then(function (success) {

                             console.log("This request is succeed! Here is the response:");

                             this.dengmiQueryForm.list = success.body.result;

                             this.dengmiQueryForm.requestResult = true;

                         }, function (error) {

                             console.log("This request is failed! Here is the response:");

                             console.log(error);

                             this.dengmiQueryForm.requestResult = false;

                         })

                     },

                     resetForm(formName) {

                         this.$refs[formName].resetFields();

                     },

                     handleSizeChange(size) {

                         this.dengmiQueryForm.pagesize = size;

                         console.log(this.dengmiQueryForm.pagesize)  //每頁下拉顯示數據

                     },

                     handleCurrentChange(currentPage) {

                         this.dengmiQueryForm.currentPage = currentPage;

                         console.log(this.dengmiQueryForm.currentPage)  //點擊第幾頁

                     },

                     handleEdit(row) {

                         this.dengmiQueryForm.deleteShow = row.mimian + "(" + row.mimu + ")" + row.midi + "/" + row.zuozhe;

                         // this.dengmiQueryForm.currentRow = row;

                         console.log(this.dengmiQueryForm.deleteShow);

                         this.modifyForm.mimian=row.mimian;

                         this.modifyForm.mimu=row.mimu;


                         // console.log("event=" + event);

                         // console.log(colunm)

                     },

                     handleClose(done) {

                         this.$confirm('確認關閉?')

                             .then(_ => {

                                 done();

                             })

                             .catch(_ => {});

                     },

                     checkDetail(val){

                         console.log(val)

                     }


                 }

             }

          </script>

          <style scoped>

          </style>


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。

          Vue 插槽之 作用域插槽

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          現在我有如下需求,子組件 <user /> 中此時有一條用戶的信息(userInfo);我要在父組件通過插槽展示這個用戶的姓名(userInfo.name);

          注意:這里的父組件并沒有這個用戶的信息,子組件中有,如果直接在父組件{{userInfo.name}} 獲取這條信息是獲取不到的;因為,只有 <user /> 組件可以訪問到 userInfo,而我們提供的內容是在父組件渲染的;
          模板在哪寫,就是用哪里的變量,跟插槽用在哪無關
          模板是在父組件中寫好,被編譯過后,傳到子組件的插槽中的

          為了讓父組件的插槽內容可以讀取到子組件的數據,我們可以將userInfo 作為一個 <slot> 元素的特性綁定上去;

          // 子組件
          const card = {
              data() {
                  return {
                      userInfo: {name: '宮鑫'}
                  }
              },
              template: `
              <div class='card'>
                  <!-- 在插槽上綁定子組件的數據 -->
                  <slot :userInfo="userInfo"/>
              </div>
              `
          };

          綁定在 元素上的特性被稱為插槽 prop?,F在在父級作用域中,我們可以給v-slot帶一個值來定義我們提供的插槽 prop 的名字:

          // 父組件
          template: `
          <div>
              <card>
                  <template v-slot:default="userInfo">
                      用戶姓名: {{userInfo}}
                  </template>
              </card>
          </div>
          `

          // 輸出:
          // 用戶姓名: { "userInfo": { "name": "宮鑫" } }

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。

          z-index不起作用的大坑

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          今天遇到的就是z-index不起作用的問題。一個后臺小哥不知道抽什么瘋,寫元素覆蓋偏不讓用absolute,搞的我之后廢了9牛二虎之力寫了一下,問題描述是這樣的,

           一對兄弟節點,insert和parent,parent有兩個子節點subtop和subbottom,展現的結果是想讓subtop在insert上面,subbottom在insert下面,

          代碼如下:

          <!DOCTYPE html>
          <html lang="en">
          <head>
              <meta charset="UTF-8">
              <title>Document</title>
              <style type="text/css">
                  .insert{
                      position: relative;
                      z-index:100;
                      background: green;
                      width:300px;
                      height:300px;
                      top:100px;
                  }
                  .parent{
                      /*position:relative;
                      z-index: 1000;*/
                      width:200px;
                      height:200px;
                      /*left:0;
                      top:-50px;*/
                      border:1px solid #eee;
                  }
                  .subbottom{
                      position:relative;
                      z-index: 50;
                      width:200px;
                      height:200px;
                      background: red;
                      top:-100px;
                      left:0;
           
                  }
                  .subtop{
                      position: relative;
                      z-index:1100;
                      width:100px;
                      height:100px;
                      left:0;
                      top:0;
                      background: blue;
                  }
              </style>
          </head>
          <body>
              <div class="insert"></div>
              <div class="parent">
                  <div class="subtop"></div>
                  <div class="subbottom"></div>
              </div>
          </body>
          </html>

          其實原理也很簡單,就是利用了z-index的覆蓋問題,在寫的過程中我發現無論怎么改變,insert的z-index總是無效的,于是百度了一下z-index無效的情況,一共有三種:
          1、父標簽 position屬性為relative;

          2、問題標簽無position屬性(不包括static);

          3、問題標簽含有浮動(float)屬性。

          這樣也很好理解為什么parent設置了position和z-index之后insert的z-index就會失效的問題了,他的解決辦法有是三個:


          1、position:relative改為position:absolute;

          2、浮動元素添加position屬性(如relative,absolute等);

          3、去除浮動。

          所以,去掉parent的position和z-index,達到了我想要的效果,如下圖所示:

          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、網站建設 、平面設計服務。

          Vue+Electron下Vuex的Dispatch沒有效果的解決方案

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          這個問題是解決基于 vue 和 electron 的開發中使用 vuex 的 dispatch 無效的問題,即解決了 Please, don't use direct commit's, use dispatch instead of this. 問題。

          先允許我梳理一下目錄結構,以便閱讀的時候不會一頭霧水,你到底說的這個文件是哪個……



          其中 /src/main 是存放主配置文件的,/src/render 下面有 store、router、components 等。

          components 下面就是很多 .vue 文件,router 下面就是一些路由配置的 js 文件和一些攔截器的 js。

          關鍵是 store,store 下面有一個 index.js 的主配置文件 index.js,和一個 modules 文件夾。

          index.js 里面寫的是(記住這句話,后面會用到):

          import Vue from 'vue'
          import Vuex from 'vuex'

          import { createPersistedState, createSharedMutations } from 'vuex-electron'

          import modules from './modules'

          Vue.use(Vuex)

          export default new Vuex.Store({
            modules,
            plugins: [
              createPersistedState(),
              createSharedMutations()
            ],
            strict: process.env.NODE_ENV !== 'production'
          })

          而 modules/ 下面存放各個實體,例如上圖中的 Auth.js 和 Counter.js,并通過 index.js 全部引入。

          /**
           * The file enables `@/store/index.js` to import all vuex modules
           * in a one-shot manner. There should not be any reason to edit this file.
           */

          const files = require.context('.', false, /\.js$/)
          const modules = {}

          files.keys().forEach(key => {
            if (key === './index.js') return
            modules[key.replace(/(\.\/|\.js)/g, '')] = files(key).default
          })

          export default modules


          然后來看一個 vuex 的官方樣例:

          const state = {
            main: 0
          }

          const mutations = {
            DECREMENT_MAIN_COUNTER (state) {
              state.main--
            },
            INCREMENT_MAIN_COUNTER (state) {
              state.main++
            }
          }

          const actions = {
            someAsyncTask ({ commit }) {
              // do something async
              commit('INCREMENT_MAIN_COUNTER')
            }
          }

          export default {
            state,
            mutations,
            actions
          }


          之后很顯然的,我想要在 Vue 的組件調用 INCREMENT_MAIN_COUNTER 對計數器加 1。

          this.$store.commit('INCREMENT_MAIN_COUNTER');
          // this.$store.commit('INCREMENT_MAIN_COUNTER', payload);
          1
          2
          如果是一般的 vue,就 OK 了,但是,我遇到了報錯,說,Please, don't use direct commit's, use dispatch instead of this.



          那好吧,沒事,不就是不然用 Commit,非要用 Dispatch 嘛,那我就寫一個 Action,里面直接調用 Mutation,就像這個樣子:

          const actions = {
            JUST_INCREASE ({ commit }) {
              commit('INCREMENT_MAIN_COUNTER')
            }
          }
          1
          2
          3
          4
          5
          然而奇怪的事情是,this.$store.dispatch('JUST_INCREASE') 并不能運行,沒反應,計數器還是 0,不能賦值,就像是這個函數沒有被執行一樣。沒有報錯,沒有任何異常,查也查不出什么問題。





          網上的資料似乎也挺少。

          折騰了很久,后來發現是 vuex-electron 里面一個插件的鍋。

          解決方法有兩個。

          方法一:

          在 store/index.js 里面,就是上文特別強調了的那個文件,去掉 createSharedMutations 插件。

          import Vue from 'vue'
          import Vuex from 'vuex'

          import { createPersistedState, createSharedMutations } from 'vuex-electron'

          import modules from './modules'

          Vue.use(Vuex)

          export default new Vuex.Store({
            modules,
            plugins: [
              createPersistedState(),
              createSharedMutations() // 注釋掉這一行
            ],
            strict: process.env.NODE_ENV !== 'production'
          })


          這是因為 vuex-electron 引入了一個用于多進程間共享 Vuex Store 的狀態的插件。如果沒有多進程交互的需求,完全可以不引入這個插件。

          注釋掉以后重啟項目,用 this.$store.commit('XXX') 就可以使用了。

          然而,如果需要多進程來處理怎么辦?

          方法二:

          https://github.com/vue-electron/vuex-electron#installation

          看第 3 條:

          In case if you enabled createSharedMutations() plugin you need to create an instance of store in the main process. To do it just add this line into your main process (for example src/main.js):

          import './path/to/your/store'
          1
          這種時候就不能用第一種方法來解決問題了。

          好在文檔也說了,加上一行導入。

          找到 /src/main/index.js,在前面加上一句:

          import '../renderer/store'
          1


          之后一切正常,可以使用 Dispatch 來進行操作了。



          最后還有一個比較奇怪的問題:



          在直接調用 state 的時候,這樣寫 this.$store.state.loginStatus 是不行的,會 undefined,必須寫成 this.$store.state.Auth.loginStatus,就像是 this.$store.state.Counter.main 一樣,似乎可以解釋為,不同的模塊不指定名字的話就找不到。

          但是,在寫 Dispatch 的時候又不需要指定名字了,直接 dispatch('changeLoginStatus') 就行了,不然難道不應該是也按照 dispatch('Auth/changeLoginStatus') 這樣子來寫嘛……
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、網站建設 、平面設計服務。

          Vue中使用Axios攔截器

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          需求是攔截前端的網絡請求和相應。
          廢話不多說,直接上干貨。



          我用的是vue-cli3所以這個config文件是我自己創建的。

          先介紹env.js

          //根據不同的環境更改不同的baseUrl
          let baseUrl = '';
           
          //開發環境下
          if (process.env.NODE_ENV == 'development') {
              baseUrl = '';
           
          } else if (process.env.NODE_ENV == 'production') {
              baseUrl = '生產地址';
          }
           
          export {
              baseUrl,//導出baseUrl
          }
          在這里我首先設置了開發環境和生產環境的地址,并向外拋出。

          在看一下axios.js

          import {
              baseUrl, //引入baseUrl
          } from "../config/env";
          import axios from 'axios';
          import qs from 'qs';
          //引入vuex的js文件
          import vuex from '../src/store/index';
           
          // 創建 axios 實例
          let service = axios.create({
              baseUrl: baseUrl,//請求前綴
              timeout: 20000,  // 請求超時時間
              crossDomain: true,//設置cross跨域
              withCredentials: true//設置cross跨域 并設置訪問權限 允許跨域攜帶cookie信息
          })
           
          // 設置 post 默認 Content-Type
          service.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=UTF-8';
           
          // 添加請求攔截器
          service.interceptors.request.use(
           
              (config) => {
                  // console.log()
                  //下面的代碼是如何在攔截器中調用vuex管理狀態。
                  //我這里主要是做了一個蒙層的遮蓋
                  // vuex.$store.commit('OPEN_LOADING');
           
           
                  //判斷請求方式是否為POST,進行轉換格式
                  config.method === 'post'
                      ? config.data = qs.stringify({...config.data})
                      : config.params = {...config.params};
                  // 請求發送前進行處理
                  return config
              },
              (error) => {
                  // 請求錯誤處理
                  return Promise.reject(error)
              }
          )
           
          // 添加響應攔截器
          service.interceptors.response.use(
              (response) => {
                  let { data } = response;
                  return data
              },
              (error) => {
                  let info = {},
                      { status, statusText, data } = error.response
           
                  if (!error.response) {
                      info = {
                          code: 5000,
                          msg: 'Network Error'
                      }
                  } else {
                      // 此處整理錯誤信息格式
                      info = {
                          code: status,
                          data: data,
                          msg: statusText
                      }
                  }
              }
          )
           
          /**
           * 向外拋出service
           */
          export default service
          最后將這個axios.js文件引入main.js中,并將引入的axios掛載到Vue實例上就ok了。

          完美!如有不對的地方還請各位大佬指點,萬分感謝。

          踩過的坑:

              怎么在axios攔截器中使用vuex,首先我們要引入vuex的js文件,然后就可以用了,就這么簡單。


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。

          Vue 全局變量,局部變量

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          全局組件和局部組件
          * 1.先定義組件   Vue.component('組件名', { 組件模板對象 })
          *   注意: 組件名不要使用原生的標簽名, 若組件名定義時用的是駝峰命名法, 則調用時用中劃線分割后小寫
          *                       例如: 組件-->mtText   使用時-->   <my-text></my-text>
          * 2.配置組件的模板  注意: 組件的模板內容有且只有一個根元素
          * 3.在視圖層里調用 ,用雙標簽
          * 4.組件是一個獨立的作用域, 也可以看成一個特殊的vue實例, 可以有data, methods,computed等等
          *   注意: 組件的data是函數, 函數中需要返回一個對象作為組件的data
          全局組件案例

          <body>
          <div id="app">
              <my-component></my-component>
          </div>
          <script src="lib/vue-2.4.0.js"></script>
          <script>
          //全局組件
              Vue.component('myComponent',{
                  //1.組件的內容/模板
                  template: '<div><div>頭部組件</div><h1 @click="fn">呵呵{{msg}}</h1></div>',
                  data(){
                      return {
                          msg:'hello,組件'
                      }
                  },
                  methods:{
                      fn(){
                          console.log(this.msg);
                      }
                  }
              })
              let vm = new Vue({
                  el:"#app",
                  data:{
                  },
                  methods:{

                  },

              })
          </script>
          </body>
          局部組件案例

          <body>
          <div id="app">
              <my-component></my-component>
              <my-test></my-test>
          </div>
          <template id="box1">
              <h1>haha</h1>
          </template>
          <template id="box2">
              <div>
                  <ul>
                      <li v-for="item in arr">
                          {{ item }}
                      </li>
                  </ul>
              </div>
          </template>
          <script src="lib/vue-2.4.0.js"></script>
          <script>
          let vm = new Vue({
                  el:"#app",
                  data:{
                  },
                  methods:{

                  },
                  //局部子組件
                  components:{
                      // 組件名: {配置項}
                      "myComponent":{
                          template:'#box1',
                          data(){
                              return {
                                  msg:"哈哈"
                              }
                          }
                      },
                      "myTest":{
                          template:"#box2",
                          data(){
                              return {
                                  arr:[1,2,3,4]
                              }
                          }
                      }
                  }
              })
          </script>
          </body>
          組件切換:法一

          <body>
          <div id="app">
              <a href="" @click.prevent="flag=true">登錄</a>
              <a href="" @click.prevent="flag=false">注冊</a>
              <login v-if="flag"></login>
              <register v-else="flag"></register>
          </div>
          <script src="lib/vue-2.4.0.js"></script>
          <script>
              Vue.component("login",{
                  template:"<h1>登錄組件</h1>"
              })
              Vue.component("register",{
                  template:"<h1>注冊組件</h1>"
              })
              let vm = new Vue({
                  el:"#app",
                  data:{
                      flag: false
                  },
                  methods:{
                  },
              })
          </script>
          </body>
          組件切換:法二

           <style>
                  .red{
                      color:red;
                  }
                  .v-enter{
                      opacity:0;
                      transform: translateX(150px);
                  }
                  .v-leave-to{
                      opacity:0;
                      transform: translateX(-150px);
                  }
                  .v-enter-active,
                  .v-leave-active{
                      transition: all 0.5s;
                      position: absolute;
                  }
              </style>
          </head>
          <body>
          <div id="app">
              <a href="" :class="{red: flag=='login'}" @click.prevent="flag='login'">登錄</a>
              <a href="" :class="{red: flag=='register'}" @click.prevent="flag='register'">注冊</a>
              <!--  vue提供了一個標簽  component標簽(理解為一個占位符), 用來展示對應名稱的組件  :is屬性設置指定的組件名  -->
              <transition>
                  <component :is="flag"></component>
              </transition>
          </div>
          <script src="lib/vue-2.4.0.js"></script>
          <script>
              Vue.component("login",{
                  template:"<h1>登錄組件</h1>"
              })
              Vue.component("register",{
                  template:"<h1>注冊組件</h1>"
              })
              let vm = new Vue({
                  el:"#app",
                  data:{
                      flag: "login"
                  },
                  methods:{

                  },
              })
          </script>
          </body>
          父組件向子組件傳值

          <body>
          <div id="app">
              <my-component :fromfather="father"></my-component>
          </div>
          <template id="box1">
              <h1 @click="change">
                  {{ fromfather }}
                  子組件的數據
              </h1>
          </template>
          <template id="grandSon">
              <h1>孫子組件的數據</h1>
          </template>
          <!--1.子組件不能訪問父組件的數據
          2. 解決辦法: ①在引用子組件時, 通過屬性綁定 v-bind方法, 把需要傳遞給子組件的數據以綁定的形式傳過來
                        ② 在子組件配置項里添加 props: ['傳遞過來的數據']-->
          <script src="lib/vue-2.4.0.js"></script>
          <script>
              let vm = new Vue({
                  el:"#app",
                  data:{
                      father:'啊~~這是父組件的數據'
                  },
                  methods:{
                  },
                  //局部子組件
                  components:{
                      // 組件名: {配置項}
                      "myComponent":{
                          template:'#box1',
                          data(){
                              return {
                                  msg:"哈哈"
                              }
                          },
                          //在子組件配置項里添加 props: ['傳遞過來的數據']
                          //注意: 組件中所有的props中的數據, 都是通過父組件傳遞給子組件的, props中的數據是只讀, 無法修改
                          props:['fromfather'],
                          methods:{
                              change(){
                                 // this.fromfather = "被修改了"
                              }
                          },
                          //局部子子組件
                          components:{
                              'grandSon':{
                                  template:'#grandSon'
                              }
                          }
                      }
                  }
              })
          </script>
          </body>
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。

          玩轉javascript異步編程

          seo達人

          如果您想訂閱本博客內容,每天自動發到您的郵箱中, 請點這里

          一般知道,js腳步語言的執行環境是單線程的,就是它會等一個任務完成,才會進行第二個任務,然后一直向下進行,這樣的執行環境簡單,但是處理不了復雜的運用,當一個請求需要非常舊的時間的時候,下一個流程就會被擱淺,如果長時間得不到反饋,進程就這樣的奔潰了。

          為了解決這個硬性需求,Javascript語言提出了二種語言模式: 同步(Synchronous)和 異步 (Asynchronous)。

          異步的幾種常用方法

          回調函數

          訂閱和發布模式

          Promise

          generator

          async/await

          回調函數方法

          通過把一個函數(callback)作為參數傳入另一個函數,當滿足一定條件的時候,就執行callback函數。

          用法:

          640?wx_fmt=jpeg

          通過回調函數的方式處理異步,是在異步早期的情況,其中jquery中的很多都是通過callback來實現回調的。但是這種模式代碼編寫比較耦合,不利于代碼維護。

          發布訂閱模式

          pub/sub模式是js設計模式中的一種,本身是借鑒于java的模式,但是在處理異步處理的時候非常有作用。通過一個信息中心EventCenter 來處理的監聽(on)和觸發(triggle)。

          640?wx_fmt=jpeg

          通過pub/sub模式,我們可以在信息中心清楚的看到有多少信號來源,方便的集中管理,更加方便于模塊化的管理,但是如果整個項目都使用pub/sub模式的話,流程就變得不太清晰了,數據的得到和數據的處理分開,對于后期的維護也是一個很大的問題。

          Promise

          Promise構造函數成為承諾,它分為三種狀態resolve, reject, pending ,一旦狀態從pending改為其它2個狀態之后,就不能修改了,就一個承諾一樣。

          Promise接收2個參數resolve , reject,分別表示成功后執行和失敗后執行,可以通過實例的then()方法傳遞對于的函數。

          640?wx_fmt=jpeg

          這里看了之后,你可能會說,這個和異步處理有什么聯系嗎?你思考一下,當一個異步操作后,我們可以不去管它什么時候結束,什么時候出錯,就像一個人承諾了,我只需要按照他的承諾去當這個事情已經被處理好了,是不是方便很多,下面直接上手一個例子。

          640?wx_fmt=jpeg

          我完全不用擔心它里面怎么實現了,反正它已經承諾了會給我結果,我只需要通過then()方法去接受,我需要得到的值就可以了。

          Promise.resolve(value) value可以是三種值

          單個值

          一個promsie實例

          一個thenable對象

          Promise.resolve(value).then((value) => {})

          處理一個請求依賴另一個請求的情況

          如果一個請求的結果是下一個請求的參數,如果我們使用原始的請求方法,就是出現一個像右的箭頭的回調地獄。

          一層層嵌套,非常的恐怖,不利于維護。那么通過prmise怎么處理回調地獄呢?

          640?wx_fmt=jpeg

          上面處理回調地獄是不是看著方便很多,代碼也簡單命令,依賴性也很強,后面我們會繼續通過async/await繼續簡化。

          處理多個請求并發的情況(不需要管服務器的返回順序)

          Promise.all(arr) 接受一個promise實例的數組,可以并發多個請求給服務器,但是并不能保證接受到的先后順序,這個取決于服務器的處理速度。

          640?wx_fmt=jpeg

          處理多個請求并發,并且需要保證返回數據的順序(運用場景比較少)

          上面一個方法并不會保證請求返回的結果,按照你發送的順序返回,如果我想把完整的響應的結果按照我

          希望的順序返回給我,那應該怎么辦呢?

          640?wx_fmt=jpeg

          這樣,會等待每一個請求完成后,并把得到的數據push到totalData中,就可以按照順序得到我們想要的值了。當然使用async/await會更加的方便。之后我們會講解。

          generator構造器

          generator是一個構造器,generator函數執行并不會執行函數體內部部分,而是返回一個構造器對象,通過構造器對象的next()方法調用函數主體,并且每當遇到yield都會暫停執行,并返回一個對象。

          640?wx_fmt=jpeg

          注意yield本身是不會反悔內容的,只是給構造器對象返回了內容,如果想yield表達式也返回內容,可以通過給下一個next()傳遞參數。

          640?wx_fmt=jpeg

          通過next()傳遞參數,我們可以做到值向內部傳遞,對于后面的異步處理很有幫助。

          generator異步運用

          利用構造器的暫停和繼續的功能,我們可以很好的處理異步請求,得到數據后再進行其他內容。主要是運用yield表達式返回一個promise對象的原理。

          640?wx_fmt=jpeg

          這樣我們就得到了接口請求的數據,相比于之前的promise函數的書寫是不是要簡單很多。和同步是一樣的操作。

          如果我們想內部對得到的數據進行進一步的處理呢?

          640?wx_fmt=jpeg

          簡單的co模塊處理generator多個函數請求

          從上面我的調用方法就可以看出,利用Promise + generator的異步處理不斷地通過then()方法處理數據。有沒有一個方式是我可以直接運行一個函數,然后就可以得到我想要的值。 例如:

          640?wx_fmt=jpeg

          網上已經封裝了很多的方法,例如常見的run庫,co函數就是來處理這樣的處理方式。但是當我們發送多個請求的時候,可能你會這樣寫:

          640?wx_fmt=jpeg

          這樣寫是會發送請求,但是并不是并發多個請求,而是等第一個請求p1之后,再進行第二個請求p2,在性能優化方面是不利的,也不符合我們的要求,怎么做到2個請求是獨立的,并且我們還可以通過得到2個請求的結果后,進行其他請求?;蛟S我們可以這樣:

          640?wx_fmt=jpeg

          這樣寫是不是和我們之前寫的Promise.all()很像?所以還可以改成這樣的:

          640?wx_fmt=jpeg

          async/await異步處理

          ES7出現了async/await進行異步的處理,使得異步操作就像同步代碼一樣簡單,方便了使用,由于async/await內部封裝了generator的 處理,所有就很少有人用generator來處理異步了,但是在異步的推動中generator起到了很大的作用。

          await: 后面接受一個promise實例

          **async: 返回一個promise對象 **

          一個簡單的異步請求

          640?wx_fmt=jpeg

          上面的例子是不是和generator中的異步請求很像?可以像同步一樣的編寫代碼,但是相比generator,await后面加上promise后直接返回相應的數據,不像yield還需要從外部傳入。

          處理多個請求并發的情況(不需要管服務器的返回順序)

          用async/await處理多個請求并發,由于await后面需要添加Promise實例,是不是腦袋里面一下子就想到了一個Promise.all()

          640?wx_fmt=jpeg

          你可能會很好奇,為什么不需要像generator那樣通過額外的函數來調用,因為async已經幫你想好了,內部已經調用了,是不是很爽?

          處理多個請求并發,并且需要保證返回數據的順序(運用場景比較少)

          如果數據中沒有相互的聯系,但是又想一個個發送,可以這樣

          640?wx_fmt=jpeg


          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務。

          日歷

          鏈接

          個人資料

          藍藍設計的小編 http://www.syprn.cn

          存檔

          亚洲va欧美va天堂v国产综合