<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>

          首頁

          js_防抖與節流(閉包的使用)

          前端達人

          js的防抖與節流

          防抖事件

          定義:持續觸發事件,一定時間內沒有觸發事件,事件處理函數只會執行一次,
          當設定的時間內觸發過一次事件后會重新開始延時。
          例:輸入框的事件(2s顯示內容,不是實時刷新顯示內容),對比輸入框的內容事件。
          實時刷新的效果

           <div class="container"> <div class="left"> <p>實時刷新顯示內容</p> <input type="text" id="leftInput" /> <div class='textDiv' id="textShow"></div> </div> <div class="right"></div> </div> <script> var inputDom=document.getElementById('leftInput'); inputDom.addEventListener('keyup',function(e){ var textDom=document.getElementById('textShow'); console.log(e.target.value); textDom.innerText=e.target.value; }) </script>  
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17

          輸入123456會依次打印123456的金字塔
          在這里插入圖片描述

          防抖(1s內顯示輸入內容)

           <div class="container"> <div class="left"> <p>防抖(1s內顯示輸入內容)</p> <input type="text" id="leftInput" /> <div class='textDiv' id="textShow"></div> </div> <div class="right"></div> </div> <script> // 防抖 var inputDom = document.getElementById('leftInput'); // 函數柯里化 function debounce(delay, callback) { let timer return function(value) { //閉包內存泄漏 clearTimeout(timer) timer = setTimeout(function() { //執行 callback(value) }, delay) } } // 顯示內容的函數 function showText(value) { var textDom = document.getElementById('textShow'); console.log(value) textDom.innerText = value; } var debounceFunc = debounce(1000, showText); inputDom.addEventListener('keyup', function(e) { let value = e.target.value debounceFunc(value) }) </script>  
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36

          1s內輸入123456只會打印一次123456
          在這里插入圖片描述

          節流事件

          定義:一段時間直只調用一次事件處理函數
          實際用例:提交事件 、游戲的技能cd(在游戲cd中點擊n次都不會發動技能)

          // 節流
                      var skillDom = document.getElementById('skillTriger');
                      function throttle(wait,callback) {
                          let timeOut;
                          return function(value) {
                              if (!timeOut) {
                                  timeOut = setTimeout(function() {
                                      callback(value);
                                      //執行一次,時間段內的都不知執行
                                      timeOut = null;
                                  }, wait)
                              }
                          }
                      }
                      function skillEvent(value){
                          var textDom = document.getElementById('skillEventId');
                          console.log(value)
                          ++count
                          textDom.innerText = value+count;
                      }
                      var skillAc=throttle(3000,skillEvent)
                      var count=0
                      skillDom.addEventListener('click', function(e) {
                          let value = e.target.value
                          skillAc(value)
                      })  
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26

          在這里插入圖片描述

          完整的html

          <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>防抖與節流</title> </head> <style> * { margin: 0; padding: 0; } .container { position: absolute; left: 50%; top: 50%; transform: translate(-50%, -50%); width: 600px; height: 400px; background: #262626; display: flex; } .left { position: relative; width: 50%; height: 100%; background: #00cec9; box-sizing: border-box; overflow: hidden; } .right { position: relative; width: 50%; height: 100%; background: #b2bec3; } </style> <body> <div class="container"> <div class="left"> <p>防抖(1s內顯示輸入內容)</p> <input type="text" id="leftInput" /> <div class='textDiv' id="textShow"></div> </div> <div class="right"> <p>節流(3s內觸發一次)</p> <input type="submit" id="skillTriger" value="發動技能" /> <div class='skillEvent' id="skillEventId"></div> </div> </div> <script> // 防抖 var inputDom = document.getElementById('leftInput'); // 函數柯里化 function debounce(delay, callback) { let timer return function(value) { //閉包內存泄漏 clearTimeout(timer) timer = setTimeout(function() { //執行 callback(value) }, delay) } } // 顯示內容的函數 function showText(value) { var textDom = document.getElementById('textShow'); console.log(value) textDom.innerText = value; } var debounceFunc = debounce(1000, showText); inputDom.addEventListener('keyup', function(e) { let value = e.target.value debounceFunc(value) }) // 節流 var skillDom = document.getElementById('skillTriger'); function throttle(wait, callback) { let timeOut; return function(value) { if (!timeOut) { timeOut = setTimeout(function() { callback(value); //執行一次,時間段內的都不知執行 timeOut = null; }, wait) } } } function skillEvent(value) { var textDom = document.getElementById('skillEventId'); console.log(value) ++count
                          textDom.innerText = value + count; } var skillAc = throttle(3000, skillEvent) var count = 0 skillDom.addEventListener('click', function(e) { let value = e.target.value skillAc(value) }) </script> </body> </html>  
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109
          • 110
          • 111
          • 112
          • 113

          1

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          轉自:csdn
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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

          配合前端vue實現表格的增刪改查

          前端達人

          前言:

                  這個章節內容是比較多的,分為前端部分和后端部分。

          目錄:

          實現效果:增刪改查

           一、后端部分:

          (1)數據庫:

                  新建一張表user,設置幾個字段,效果如下:

           (2)egg邏輯部分:

          提供的接口:http://localhost:7001/setUserList

           (3)egg具體實現步驟:

          1、router.js中添加:

          2、新建:app / controller / new / user.js

          (1)查,模糊查詢 

          (2)增

           (3)改

           (4)刪

           user.js 源碼:

          3、引入mysql:點我

          4、跨域問題解決:點我

           二、前端部分:

          新建vue文件:testApi.vue

          1、初始化查詢列表數據:頁面展示列表,列表數據mouted獲取

          2、頁面點擊新增:展示彈框,并將彈框內容去除掉,點擊新增,將彈框內容發送給后端

           3、頁面點擊列表里面具體數據的編輯:彈框,并回填數據,修改將當前數據的id和表格數據傳給后端

          4、刪除按鈕,點擊出現二次確認彈框,點擊確認將當前數據的id給后端就行 

           testApi.vue 源碼:


          實現效果:增刪改查

           一、后端部分:

          (1)數據庫:

                  新建一張表user,設置幾個字段,效果如下:

           (2)egg邏輯部分:

          提供的接口:http://localhost:7001/setUserList

          1. get 請求,獲取數據,支持模糊查詢
          2. post 請求,新增數據
          3. put 請求,給后端當前數據id,修改內容
          4. delete 請求,根據數據id刪除當前條數據

           (3)egg具體實現步驟:

          1、router.js中添加:

           
          
          1. /**
          2. * 路由配置
          3. * @param app
          4. */
          5. module.exports = app => {
          6. const { router, controller } = app;
          7. //--------------------------------------------------
          8. // server接口
          9. //--------------------------------------------------
          10. app.get('/setUserList', controller.new.user.getUserList);
          11. app.post('/setUserList', controller.new.user.postUserList);
          12. app.put('/setUserList', controller.new.user.putUserList);
          13. app.delete('/setUserList', controller.new.user.deleteUserList);
          14. }

          2、新建:app / controller / new / user.js

          (1)查,模糊查詢 

          select * from user where name like ? % 內容 %

          (2)增

          this.app.mysql.insert('表名',內容)

           (3)改

          UPDATE loginlist SET `password` = 'Ad123456' WHERE id = 2

           (4)刪

          delete from user where id = 1

           user.js 源碼:

           
          
          1. /**
          2. * 用戶信息路由
          3. * @param app
          4. * @returns {HomeController}
          5. */
          6. const Controller = require('egg').Controller;
          7. class NewsController extends Controller {
          8. async getUserList() {
          9. //查詢庫里的user表
          10. let params = this.ctx.query //獲取路徑后面的參數
          11. console.log('用戶的參數:');
          12. console.log(params);
          13. let sql = 'select * from user'
          14. let initSql = sql
          15. let content = [];//參數
          16. let isMore = false;//是否有多個查詢參數
          17. /**
          18. * @模糊查詢-量大的時候效率低
          19. * select * from user where name like ? % 內容 %
          20. * 在user表中全局查找name值 == 內容的
          21. * % 內容 % 全局查找內容
          22. * 內容 % 查找以 內容 開頭的數據
          23. * */
          24. if(params.name){
          25. sql += " where name like ?";
          26. content.push( "%"+params.name+"%" );
          27. isMore = true;
          28. }
          29. if(params.age){
          30. if(isMore){//true代表有多個參數
          31. sql += "and age LIKE ?";//and是兩個條件都必須滿足,or是或的關系
          32. }else{
          33. sql += " WHERE age LIKE ?";
          34. }
          35. content.push( "%"+params.age+"%" )
          36. isMore = true;
          37. }
          38. if(params.address){
          39. if(isMore){//true代表有多個參數
          40. sql += "and address LIKE ?";//and是兩個條件都必須滿足,or是或的關系
          41. }else{
          42. sql += " WHERE address LIKE ?";
          43. }
          44. content.push( "%"+params.address+"%" )
          45. isMore = true;
          46. }
          47. if(params.phone){
          48. if(isMore){//true代表有多個參數
          49. sql += "and phone LIKE ?";//and是兩個條件都必須滿足,or是或的關系
          50. }else{
          51. sql += " WHERE phone LIKE ?";
          52. }
          53. content.push( "%"+params.phone+"%" )
          54. }
          55. //開啟分頁
          56. if(params.page || params.pageSize){
          57. let current = params.page;//當前頁碼
          58. let pageSize = params.pageSize;//一頁展示多少條數據
          59. sql += " limit ?,?";
          60. content.push((current-1)*pageSize,parseInt(pageSize));
          61. }
          62. let allList = await this.app.mysql.query(initSql);
          63. let userList= await this.app.mysql.query(
          64. sql,content
          65. );
          66. this.ctx.body = {
          67. code:200,
          68. masg:'success',
          69. data: {
          70. list:userList,
          71. total:allList.length
          72. }
          73. };
          74. }
          75. /**
          76. * 新增用戶信息
          77. * INSERT INTO loginlist (aaa,bbb,ccc) VALUES ('"'+111+'","'+222+'","'+333+'"')
          78. * this.app.mysql.insert('表名',內容)
          79. * this.app.mysql.insert('表名',{
          80. * name:123,
          81. * age:1,
          82. * address:西安
          83. * })
          84. */
          85. //
          86. async postUserList() {
          87. console.log(this.ctx.request.body);
          88. //新增數據-user表
          89. let data = this.ctx.request.body
          90. data.id = parseInt(Math.random()*100000)
          91. let insertResult = await this.app.mysql.insert(
          92. 'user', data
          93. );
          94. this.ctx.body = {
          95. code:200,
          96. masg:'success',
          97. data:insertResult
          98. };
          99. }
          100. /**
          101. * 修改用戶信息
          102. * UPDATE loginlist SET `password` = 'Ad123456' WHERE id = 2(唯一值),修改一個
          103. * UPDATE loginlist SET username = 'admins', `password` = 'Ad123456' WHERE id = 2,修改多個
          104. */
          105. async putUserList(){
          106. //新增數據-user表
          107. let id = this.ctx.query.id //獲取路徑后面的參數
          108. let data = this.ctx.request.body
          109. let sql = 'update user set '
          110. let isMore = false;//是否有多個查詢參數
          111. if(!id){
          112. this.ctx.body = {
          113. code:200,
          114. masg:'warning',
          115. data:'id沒有傳'
          116. };
          117. return
          118. }
          119. //姓名
          120. if(data.name){
          121. sql += 'name = "'+data.name+'"'
          122. isMore = true
          123. }
          124. //年齡
          125. if(data.age){
          126. if(isMore){
          127. sql += ',age = "'+data.age+'"'
          128. }else{
          129. sql += 'age = "'+data.age+'"'
          130. }
          131. isMore = true
          132. }
          133. //地址
          134. if(data.address){
          135. if(isMore){
          136. sql += ',address = "'+data.address+'"'
          137. }else{
          138. sql += 'address = "'+data.address+'"'
          139. }
          140. isMore = true
          141. }
          142. //手機號
          143. if(data.phone){
          144. if(isMore){
          145. sql += ',phone = "'+data.phone+'"'
          146. }else{
          147. sql += 'phone = "'+data.phone+'"'
          148. }
          149. isMore = true
          150. }
          151. //郵箱地址
          152. if(data.email){
          153. if(isMore){
          154. sql += ',email = "'+data.email+'"'
          155. }else{
          156. sql += 'email = "'+data.email+'"'
          157. }
          158. }
          159. sql += ' where id = ' + id
          160. let insertResult = await this.app.mysql.query(sql)
          161. this.ctx.body = {
          162. code:200,
          163. masg:'success',
          164. data:insertResult
          165. };
          166. }
          167. /**
          168. * 注銷用戶接口
          169. * DELETE FROM loginlist WHERE username = 'superman'
          170. */
          171. async deleteUserList(){
          172. //查詢庫里的user表
          173. let params = this.ctx.query //獲取路徑后面的參數
          174. console.log('用戶的參數:');
          175. console.log(params);
          176. let sql = 'delete from user where id = '+ params.id
          177. let res = await this.app.mysql.query(
          178. sql
          179. );
          180. this.ctx.body = {
          181. code:200,
          182. masg:'success',
          183. data:res
          184. };
          185. }
          186. /**
          187. * 模糊查詢封裝方法
          188. * @params = auth
          189. * */
          190. async query( auth ) {
          191. const TABLE_NAME = 'user';
          192. const QUERY_STR = 'id, name, age, phone, address';
          193. let sql = `select ${QUERY_STR} from ${TABLE_NAME} where authName like "%${auth.authName}%"`;
          194. const row = await this.app.mysql.query(sql);
          195. return row;
          196. }
          197. }
          198. module.exports = NewsController;

          3、引入mysql:點我

          4、跨域問題解決:點我

           二、前端部分:

          新建vue文件:testApi.vue

          1、初始化查詢列表數據:頁面展示列表,列表數據mouted獲取

           
          
          1. <el-table
          2. :data="tableInfo.list"
          3. style="width: 100%">
          4. <el-table-column
          5. type="index"
          6. label="序號"
          7. align="center">
          8. </el-table-column>
          9. <el-table-column
          10. prop="name"
          11. label="姓名"
          12. align="center">
          13. </el-table-column>
          14. <el-table-column
          15. prop="age"
          16. label="年齡"
          17. align="center">
          18. </el-table-column>
          19. <el-table-column
          20. prop="address"
          21. label="地址">
          22. </el-table-column>
          23. <el-table-column
          24. prop="phone"
          25. label="手機號">
          26. </el-table-column>
          27. <el-table-column
          28. prop="email"
          29. label="郵箱">
          30. </el-table-column>
          31. <el-table-column
          32. label="操作"
          33. width="100">
          34. <template slot-scope="scope">
          35. <el-button type="text" size="small" @click="editFun(scope.row)">編輯</el-button>
          36. <el-button type="text" size="small" @click="deleteFun(scope.row)">刪除</el-button>
          37. </template>
          38. </el-table-column>
          39. </el-table>
           
          
          1. mounted(){
          2. this.initPage()
          3. },
          4. methods: {
          5. /***
          6. * 獲取列表數據
          7. */
          8. initPage() {
          9. let params = {
          10. page: this.tableInfo.page, //當前頁
          11. pageSize: this.tableInfo.pageSize //一頁展示多少條
          12. }
          13. this.$axios.get('http://localhost:7001/setUserList',{
          14. params
          15. }).then(res => {
          16. this.tableInfo.list = res.data.data.list
          17. this.tableInfo.total = res.data.data.total
          18. }).catch(error => {
          19. this.$message(error.data.message)
          20. })
          21. },
          22. }

          2、頁面點擊新增:展示彈框,并將彈框內容去除掉,點擊新增,將彈框內容發送給后端

           3、頁面點擊列表里面具體數據的編輯:彈框,并回填數據,修改將當前數據的id和表格數據傳給后端

           

           

          4、刪除按鈕,點擊出現二次確認彈框,點擊確認將當前數據的id給后端就行 

           testApi.vue 源碼:

           
          
          1. <template>
          2. <div class="pro_body">
          3. <el-button type='success' @click="addModal">新增</el-button>
          4. <el-table
          5. :data="tableInfo.list"
          6. style="width: 100%">
          7. <el-table-column
          8. type="index"
          9. label="序號"
          10. align="center">
          11. </el-table-column>
          12. <el-table-column
          13. prop="name"
          14. label="姓名"
          15. align="center">
          16. </el-table-column>
          17. <el-table-column
          18. prop="age"
          19. label="年齡"
          20. align="center">
          21. </el-table-column>
          22. <el-table-column
          23. prop="address"
          24. label="地址">
          25. </el-table-column>
          26. <el-table-column
          27. prop="phone"
          28. label="手機號">
          29. </el-table-column>
          30. <el-table-column
          31. prop="email"
          32. label="郵箱">
          33. </el-table-column>
          34. <el-table-column
          35. label="操作"
          36. width="100">
          37. <template slot-scope="scope">
          38. <el-button type="text" size="small" @click="editFun(scope.row)">編輯</el-button>
          39. <el-button type="text" size="small" @click="deleteFun(scope.row)">刪除</el-button>
          40. </template>
          41. </el-table-column>
          42. </el-table>
          43. <el-pagination
          44. class="work_pagination"
          45. background
          46. :layout="'total,prev, pager, next,sizes'"
          47. :total="tableInfo.total"
          48. :hide-on-single-page="false"
          49. :current-page="tableInfo.page"
          50. :page-size="tableInfo.pageSize"
          51. @current-change="pageChange"
          52. @size-change="pageSizeChange"
          53. >
          54. </el-pagination>
          55. <!--彈框部分-->
          56. <el-dialog
          57. custom-class="modalName"
          58. :visible.sync="modal.show"
          59. :width="modal.type === 'delete'? '470px' : '800px'">
          60. <h3 v-if="modal.type === 'add'" slot="title">新增</h3>
          61. <h3 v-if="modal.type === 'edit'" slot="title">修改</h3>
          62. <h3 v-if="modal.type === 'delete'" slot="title">提示</h3>
          63. <div v-if="modal.type !== 'delete'" class="editNameBody">
          64. <el-form class="editNameFrom" :model="modalFrom" label-width="120px" label-position="right">
          65. <el-form-item label="姓名:">
          66. <el-input v-model="modalFrom.name"></el-input>
          67. </el-form-item>
          68. <el-form-item label="年紀:">
          69. <el-input v-model="modalFrom.age"></el-input>
          70. </el-form-item>
          71. <el-form-item label="手機號:">
          72. <el-input v-model="modalFrom.phone"></el-input>
          73. </el-form-item>
          74. <el-form-item label="郵箱:">
          75. <el-input v-model="modalFrom.email"></el-input>
          76. </el-form-item>
          77. <el-form-item label="地址:">
          78. <el-input v-model="modalFrom.address" type="textarea"></el-input>
          79. </el-form-item>
          80. </el-form>
          81. </div>
          82. <div v-if="modal.type === 'delete'">
          83. <i class="el-icon-warning" style="margin-right:7px;color:#FFAA00;font-size: 16px;"></i>請確認是否刪除
          84. </div>
          85. <div slot="footer" class="dialog-footer">
          86. <el-button @click="modal.show = false">取 消</el-button>
          87. <el-button v-if="modal.type === 'add'" type="primary" @click="addUserList">新增</el-button>
          88. <el-button v-if="modal.type === 'edit'" type="primary" @click="editUserList">修改</el-button>
          89. <el-button v-if="modal.type === 'delete'" type="primary" @click="deleteUserList">確 認</el-button>
          90. </div>
          91. </el-dialog>
          92. </div>
          93. </template>
          94. <script>
          95. export default {
          96. data() {
          97. return {
          98. tableInfo:{
          99. columns:[
          100. {
          101. title: '序號',
          102. type: 'index',
          103. },{
          104. title: '姓名',
          105. prop: 'name',
          106. align: 'center'
          107. },
          108. {
          109. title: '年齡',
          110. prop: 'age',
          111. align: 'center'
          112. },{
          113. title: '地址',
          114. prop: 'address',
          115. align: 'center'
          116. },{
          117. title: '郵箱',
          118. prop: 'email',
          119. align: 'center'
          120. },{
          121. title: '手機號',
          122. prop: 'phone',
          123. align: 'center'
          124. },
          125. {//內容slot
          126. slot: 'operateT'
          127. }
          128. ],
          129. list:[],
          130. page:1,
          131. pageSize:10,
          132. total:0,
          133. },
          134. modal:{
          135. show:false,
          136. type:'add'
          137. },
          138. modalFrom:{
          139. name:'',
          140. age:'',
          141. phone:'',
          142. address:'',
          143. email:''
          144. }
          145. };
          146. },
          147. mounted(){
          148. this.initPage()
          149. },
          150. methods: {
          151. /***
          152. * 獲取列表數據
          153. */
          154. initPage() {
          155. let params = {
          156. page: this.tableInfo.page, //當前頁
          157. pageSize: this.tableInfo.pageSize //一頁展示多少條
          158. }
          159. this.$axios.get('http://localhost:7001/setUserList',{
          160. params
          161. }).then(res => {
          162. this.tableInfo.list = res.data.data.list
          163. this.tableInfo.total = res.data.data.total
          164. }).catch(error => {
          165. this.$message(error.data.message)
          166. })
          167. },
          168. /**
          169. * 當前頁發生改變
          170. * */
          171. pageChange(page) {
          172. this.tableInfo.page = page
          173. this.initPage() //刷新列表數據
          174. },
          175. /**
          176. * 當前第幾頁發生改變
          177. * */
          178. pageSizeChange(pageSize) {
          179. this.tableInfo.page = 1
          180. this.tableInfo.pageSize = pageSize
          181. this.initPage() //刷新列表數據
          182. },
          183. //新增彈框
          184. addModal(){
          185. this.modalFrom ={
          186. name:'',
          187. age:'',
          188. phone:'',
          189. address:'',
          190. email:''
          191. }
          192. this.modal.show = true
          193. this.modal.type = 'add'
          194. },
          195. //修改彈框
          196. editFun(row){
          197. this.modalFrom = row
          198. this.modal.show = true
          199. this.modal.type = 'edit'
          200. },
          201. //刪除彈框
          202. deleteFun(row){
          203. this.modalFrom = row
          204. this.modal.show = true
          205. this.modal.type = 'delete'
          206. },
          207. addUserList(){
          208. this.$axios({
          209. method:'post',
          210. url:'http://localhost:7001/setUserList',
          211. data:this.modalFrom
          212. }).then(res => {
          213. this.$message.success('新增成功')
          214. this.initPage() //刷新數據
          215. this.modal.show = false
          216. })
          217. },
          218. editUserList(){
          219. this.$axios({
          220. method:'put',
          221. url:'http://localhost:7001/setUserList',
          222. params:{
          223. id:this.modalFrom.id
          224. },
          225. data:this.modalFrom
          226. }).then(res => {
          227. this.$message.success('修改成功')
          228. this.initPage() //刷新數據
          229. this.modal.show = false
          230. })
          231. },
          232. deleteUserList(){
          233. this.$axios({
          234. method:'delete',
          235. url:'http://localhost:7001/setUserList',
          236. params:{
          237. id:this.modalFrom.id
          238. }
          239. }).then(res => {
          240. this.$message.success('刪除成功')
          241. this.initPage() //刷新數據
          242. this.modal.show = false
          243. })
          244. }
          245. }
          246. }
          247. </script>
          248. <style lang='scss'>
          249. .modalName{
          250. h3{
          251. padding:10px;
          252. }
          253. }
          254. </style>


          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          轉自:csdn
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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

          全面總結圖表設計的思路和方法

          資深UI設計者

          數據成為了日常工作的一大重要角色,越來越多的公司以數據驅動產品進行迭代。但令人困惑的是可視化圖表無處不矮,但卻給大家帶來了誤導。作者分享了一些簡單的思路與方法,以此來改善這些問題,希望對你有所幫助。


          越來越多的公司以數據驅動產品進行迭代,從中我們能看出數據的重要性。

          日常工作中,無論是匯報還是設計,都離不開圖表的使用。但令人困惑的可視化圖表無處不在,往往給人帶來誤導性,通過遵循下面這些簡單的思路和方法可以有效改善這些問題。

          一、選擇正確的圖表類型

          選擇錯誤的圖表類型,或默認使用最常見的類型,可能會混淆用戶對數據產生誤解。

          一組數據可以有多種表示方式,具體類型取決于用戶希望看到的內容。

          二、根據正負值確定方向

          當數據中出現正負值時,要先確定基線的位置,再確定數據位置,將正值分布在基線上側(X軸)或右側(Y軸),負值分布在下側(X軸)或左側(Y軸)。

          避免在基線的同一側同時添加正值和負值,造成用戶對圖表信息理解錯誤。

          三、始終從零開始繪制條形圖

          單看左側的條形圖,能發現B的值比D的值要多3倍以上,但在右側從零開始的條形圖中,實際差異要小得多。從零開始可確保用戶獲得更準確的數據展示。

          四、折線圖使用自適應Y軸

          對折線圖來說,如果始終將Y軸的比例限制為從零開始,一旦數據波動幅度很小,那整個折線圖會看起來很平坦,效果不明顯。

          折線圖主要用來表現趨勢,根據給定時間的數據調整比例,并保持折線區域能占到Y軸范圍的三分之二。

          五、使用折線圖時考慮時間間隔

          折線圖是由一條條小線段連接組成,這些線段展示了在短時間內數據是如何變化的。當時間間隔很大或數據更新不頻繁時,就要慎重考慮是否使用折線圖。

          例如想表示年收入,左側的兩個折線圖樣式都不太合適,每個月的收入是固定的數字,而折線圖展現的數據更像是收入的變化,相反右側的條形圖更適合來展示每月具體的收入。

          六、不要使用平滑的折線

          平滑的折線圖可能看著很舒服,但它們歪曲了背后的實際數據,而且過粗的線條掩蓋了真正的節點。

          七、謹慎使用雙軸折線圖

          當兩組數據出現X軸代表的信息相同但Y軸不同時,為節省空間我們可能會考慮用雙軸圖。

          但大部分雙軸圖難以閱讀,只是感覺圖表上有很多數據,但遠遠沒有單個圖表展示的清晰。

          八、限制餅圖的切片數量

          餅圖是最受歡迎但經常被誤用的圖表之一。在使用餅圖時,首先要注意切片的數量最好保持在5-7片。

          如果還有很多占比很小的切片,可以將這些全部歸到“其他”切片中。

          九、直接在圖表上標注

          如果沒有正確的標注,無論圖表設計的多好看都沒有意義。

          直接在圖表上標注數據或信息對使用者來說更直觀,更節省時間和精力。

          十、不要在切片上標注

          將數值放在切片上雖然很直觀,但可能會導致很多問題,例如左側餅圖數值的可讀性問題、切片太薄無法添加數值等,對比來看,右側餅圖添加標注的方式更合適。

          十一、餅圖切片的排序

          餅圖切片的排序是一個很容易忽略的問題,將餅圖切片只是一個開始,通過合理的排序保證用戶清晰觀看圖表才是關鍵。

          常見的排序方法是將面積最大的切片放在12點鐘位置,然后按順時針降序放置第二大的切片,以此類推。

          十二、避免隨機性

          同樣的建議適用于其他類型的圖表。盡量不要默認按字母順序排序,將最大值放在頂部(水平條形圖)或左側(對于垂直條形圖),以確保最重要的值占據最突出的空間,減少視線運動和閱讀圖表所需的時間。

          十三、避免極端的環形圖

          環形圖,又稱為甜甜圈圖,是餅圖的一種變體,本質是餅圖將中間區域挖空,用在多樣品間的多種數據的比較中。

          雖然環形圖騰出中間區域來顯示額外的信息,但犧牲清晰度走極端會讓圖表變得毫無用處。

          十四、讓數據自己說話

          不必要的設計樣式不僅會分散注意力,還可能導致用戶對數據誤解并產生錯誤印象,圖表在設計上應避免:

          • 3D元素、陰影、漸變;
          • 斑馬紋、過多的網格線;
          • 裝飾性過強的斜體、粗體或襯線字體。

          十五、選擇與數據性質匹配的調色板

          顏色是保持數據可視化有效的組成部分,在設計時考慮3種調色板類型:

          • 分類色板(左)適合顯示分類數據,當你想區別不連續且內在沒有順序關系的數據時可以使用這種類型;
          • 連續色板(中)適用于需要按特定順序放置的變量中,使用色調/亮度或兩者組合創建色板。
          • 離散色板(右)是兩個連續色板的組合,中間有一個中心值(通常為零)。不同的調色板會傳達正值和負值。

          十六、無障礙設計

          根據眼科研究中心的數據,大約每12個人中就有1個色盲,圖表只有在廣泛受眾可以訪問的情況下才是成功的:

          • 在調色板中使用不同的飽和度、亮度;
          • 黑白打印可視化圖表,檢查對比度和可讀性。

          十七、注重易讀性

          確保圖表排版在傳達信息并幫助用戶專注于數據,而不是分散注意力:

          • 選擇字跡清晰的字體,避免使用襯線和裝飾性很強的字體;
          • 避免使用斜體、粗體和全部大寫;
          • 確保文本與背景形成高對比度;
          • 不要旋轉文本。

          十八、使用水平條形圖代替旋轉標注

          這個簡單的技巧可以確保用戶能夠更有效地瀏覽圖表,而不會使他們感到緊張。

          十九、建立圖表庫

          如果你的任務是將交互式圖表添加到Web和移動項目中,那么首要考慮問題是將使用什么樣的圖表?

          基于定義的庫(Highcharts)進行設計將確保易于實現,并為我們提供大量的交互想法。

          二十、超越靜態報告

          通過更改參數、可視化類型、時間線幫助用戶進行探索,得出最大價值化的結論。例如IOS Health結合使用了各種數據表示來發揮優勢。



          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼ben_lanlan,報下信息,會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          文章來源:人人都是產品經理  作者:Clippp
          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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



          如何提升用戶體驗

          資深UI設計者

          現代人的生活離不開應用程序,我們的手機中有著各種各樣的app幫我們處理各種瑣事。各大互聯網公司開發多種應用商店,努力使我們的生活變得有趣,但要想提高整體的用戶體驗,還需要注意五點,不然再好的app也會讓用戶放棄使用。


          1.禁止使用大段的功能介紹

          我們必須要提示一下:如果一個應用程序要在手機屏幕上發揮作用——必須簡單。這個應用需要使用冗長的功能介紹,才能讓用戶熟悉使用起來,那很可能是開發人員在這個版本中設置太多功能。用戶并不介意多次更新程序,適應新版本,但他們也不可能為了使用程序而閱讀長如圣經般的介紹。


          2.牢記用戶需求


          如果想要急于求成,跳過用戶調研,上線新的應用,那么失敗的概率會大大增加。大多數應用開發團隊都容易犯這樣的錯誤,只拿到了用戶發送給支持團隊的數據。通過分析數據,就能迅速確定用戶所需的功能,使用缺陷等,但是,總的來說,聯系支持團隊的用戶是那些產生挫敗感的人;那么99%(或更多)的用戶從來沒有和支持部門談過?難道你不愿意讓他們一直滿意,而是花費時間,只讓使用支持功能的1%用戶滿意?


          即使你認為自己了解用戶需求,也需要與他們進行溝通。


          3.使用屏幕技術


          當人們花費了近萬元買了一部智能手機時,他們希望能使用手機上的所有功能。所以制作這款手機時沒有任何借口在視覺內容上偷工減料(或忽視任何技術能力)。這就是用戶花錢的原因,要想提高用戶體驗,就需要滿足用戶期望。


          4.停用費時的設置向導


          設置向導的本意是為用戶提供更好的內容,更能讓用戶獲取自己想要的。為了優化用戶體驗可以讓用戶填寫一些內容,但并不意味著暴露全部隱私。最好在需要時索取,而非提前取得全部數據。


          5.減少通知次


          每個軟件都想要發送通知,但是每一個通知都是必要的嗎?每隔兩秒鐘就有一些應用告知用戶一些無用消息,比如誰誰誰又發了微博,誰誰誰上線了,又或者誰誰誰開始直播了,可以根據用戶的興趣選取推送而不是一股腦全部告知用戶,所以請盡量減少的通知消息吧!

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼ben_lanlan,報下信息,會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          文章來源:站酷  作者:馬克筆留學設計

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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


          B端產品設計規范之數據展示

          資深UI設計者


          數據展示有哪些?



          01.徽標

          是收納消息數量的樣式,一般出現在圖標或者頭像右上角。



          02.標簽

          數據展示里面抽取出來的共性特征,將它們轉化為標簽。標簽樣式有線框、帶不透明底或者面性。



          03.走馬燈

          相當于c端的輪播圖




          04.文字提示

          可以出現在鼠標懸浮按鈕時候的行為解釋說明,也可以是文案或者導航圖標的解釋說明。鼠標移入時候出現移出時候消失。



          05.氣泡卡片

          比起文字提示可以承載更多內容,相對彈窗,氣泡卡片操作更輕盈。




          06.標簽頁/選項卡

          標簽頁可以幫助用戶在一個頁面內快速切換不同類型內容,提升單個頁面整體的擴展性。標簽本質上就是內容區的導航。



          07.折疊面板

          折疊面板可以更好的收納內容區域,提高頁面利用率??梢院捅砀窠Y合使用,折疊表格部分詳情內容,使得縱向空間更節約。




          08.表格

          表格是數據展示的重要內容。當有大量結構化數據需要展示時或者需要對數據進行排序、搜索分頁時可以用表格進行展現。


          當筆記本過小,表格展示不全時候,可以固定首尾重要信息進行滾動。


          帶排序的表頭,可對數量或者金額進行排序。


          帶分組的表格,建議帶邊框并且用色塊區分表頭和內容。


          單元格可編輯


          批量選中時只會選中當前頁,因為分頁還沒加載出來,為了給用戶正確的引導,可以給上提示性文案,例如“已選中XX項內容”。


          如果當前頁批量選中的數據量不滿足要求,可以改變分頁器,增加當前頁數據量,從而增加選項。


          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼ben_lanlan,報下信息,會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          文章來源:站酷  作者:最多三分糖

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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



          如何做好直播設計的體系化復盤?

          資深UI設計者

          前言

          “直播”作為一個大熱領域,用戶規模早在 2020 年就突破了 5 億大關,在“直播+”的模式下,電商、教育甚至是醫美,都能在直播領域下找到新賽道,并產生持續性獲客。但就是這樣一個核心領域,具體要怎么分析復盤,卻鮮少看到系統化的文章。本文主要是結合我近期參與產品直播項目的思考,總結了自己的一套直播復盤方法論和大家分享。

          為什么要做直播復盤?

          雖然“直播+”模式已成為行業趨勢,但在產品接入直播模塊而產生的付費效益又不明顯時,其存在的意義和價值仍時常被挑戰,因此首要的就是驗證其價值;

          同時,新領域缺乏可復用的方法論,只有不斷探索、優化、沉淀才能促進其健康化生長;

          最后,在產品范圍下的直播領域,定向吸引的還是產品用戶為主,持續挖掘探索直播能為產品開辟的新賽道,為產品帶來拉新,是“直播+”模式對于產品的直接價值體現。

          如何做好直播設計的體系化復盤?

          直播復盤怎么做?

          直播具備快節奏性和強競爭性,在兼顧快速復盤的同時,還需要考慮階段性的整體化的對直播數據進行監控,因此需要將直播復盤分為快速復盤和階段復盤 2 個大方向。

          1. 快速復盤

          在直播結束當天或隔天對昨日數據進行快速復盤,此時重點關注單期直播下的直觀數據表現和用戶反饋。目的是獲得沉淀當天直播的經驗并快速應用至后續直播中,是一個不斷 PDCA 的過程。

          在復盤維度上,可以分為數據側和用戶側:

          數據側中我們重點聚焦本期的數據表現,同時橫向對比其他直播期,去明確本期的數據表現

          1)橫向對比時,需要將直播關注的 3 大核心數據(總人數、最高在線人數、評論人數、在線時長均值)與其他期對比,明確該期直播的“優劣”。

          如何做好直播設計的體系化復盤?

          當期直播核心數據

          2)聚焦本期時,重點關注直播數據的整體在線人數變化趨勢,定位到最高在線點,和直播內容擬合,能夠幫助我們定位直播的“高光點”。

          用戶側中則更關注主播在播、用戶在聽和答的過程,包含:

          • 直播過程中,用戶情緒、反饋異常的節點(如消極發言等),定位用戶可能存在的痛點。
          • 固定同學作為“直播觀眾”時,察覺到的異常問題(如信息銜接不自然等),及時復盤。
          • 在直播間的互動評論中,呼聲最高的內容,可以作為后續直播可以“返場”的內容,納入直播內容需求池中。

          2. 階段復盤

          在累計多場直播后,此時最需要的就是階段性的復盤,從宏觀角度對多期直播進行收斂分析,能夠幫助我們明確直播對于產品的核心價值,并定位核心用戶圈層、吸引點及直播應該要有的“節奏”。

          在階段復盤中,除了數據側、用戶側外,我們還需要關注市場側:

          數據側—不同于快速復盤,數據側我們關注整體宏觀角度上直播對產品的價值,以及直播整體的數據表現,熱點分布等

          1)從直播對產品價值定位來說,在未探索付費的情況下,直播能為產品做的就是吸引新用戶,增加用戶活躍、延長用戶在產品內停留的時長上。

          如何做好直播設計的體系化復盤?

          價值定位時關注的數據范圍

          在明確價值后,就應該明確后續要如何把直播做的更好,這里數據上可以分為 2 個大的方向,一是熱點分析,二是直播節奏分析。

          2)熱點分析上,需要從單期、分類、詞項拆解上看。首先,單期直播就是簡單地對單期直播數據進行排序,找到“好”的直播提煉其特征性;其次,分類分析上關注各類直播數據間的橫向對比,能從分類數據對比上,看出哪一類直播更吸引用戶;最后,通過對每期直播的標題進行詞項拆解,篩除掉無意義的詞項,再乘以對應期直播的人數,對每個出現 2 次及以上的詞項數據取出其對應的單期直播人數均值,即可定位到用戶最關注、最能吸引用戶的核心關鍵詞。

          如何做好直播設計的體系化復盤?

          熱點分析

          3)直播節奏分析上,得益于階段性復盤的龐大數據量,我們可以聚類出多期直播聚類下的直播趨勢線,在趨勢線上,亦關注 3 大核心點 “拉新、增長、流失”。

          a. 用戶進入直播的高峰期(即新增高峰),可用于定位直播亮點,并對應布局以留住用戶

          如何做好直播設計的體系化復盤?

          用戶進入直播節奏分析

          b. 通過直播數據排序后的高于中位數直播、低于中位數直播的 2 種直播數據走勢的對比,我們能夠看出好的直播應有的數據走勢應該是什么樣的。以我這次分析的直播為例,能夠直觀看出,“差”的直播在增長黃金期都“爬”的很慢,而在黃金期后直播數據逐漸平緩,“差”的直播數據就成了定局。因此要做的就是在增長黃金期,去盡量促進增長。

          如何做好直播設計的體系化復盤?

          用戶流入流出關系分析

          c. 那么在增長黃金期,從產品策略來看,要做的是留住用戶?還是盡量去拉新?從數據上,我們有 2 種方式判別,分別是相關性分析和假設分析。在相關性分析中,將新增人數/流失率對標最高在線人數,以數據模型分析其相關性,從相關系數來看哪個指標與最高在線人數相關性最高,即影響最大;在假設分析中,我們可以將“低于中位數”的直播數據中的新增人數/流失率分別對標“高于中位數”直播的數據,其他保持不變,看哪種情況下,最高在線人數是更高,數據是更好的,就可以定位出更應該在哪塊發力。

          用戶側—要明確直播受眾及用戶圈層,并針對這部分受眾的觀看體驗,進行服務體驗走查,更能夠幫我們明確后續業務重心、范圍及宣傳模式。

          在用戶圈層上,我們對觀眾數據清洗,從年齡、性別、地域、渠道等各項維度去定位觀眾的特征。同時,考慮到直播本身是以產品為載體,其用戶圈層基本上與產品本身重合,但會存在一定差異性。因此,此處可以結合 TGI 分析,可以定位到直播用戶圈層相較于產品來說的差異點,從而更針對受眾進行直播內容調整。

          如何做好直播設計的體系化復盤?

          用戶圈層分析

          同時,直播本身因其特殊性質,也可類比至服務體驗設計的思維,因此在用戶側分析時,從直播前-中-后 3 個大環節上分析用戶行為、需求、痛點、快點,從而定位到各個環節直播優化的機會點,推進優化。

          如何做好直播設計的體系化復盤?

          直播-體驗地圖

          市場側—在市場分析時,我們不僅需要關注那些在直播領域做的好的同類競品,同時也要去多分析在受眾群體中,最近的熱門話題是什么,有助于后續在宣發時引出直播核心話題,也能夠帶領我們思考直播的新賽道,以協助產品拓寬其用戶圈層。

          小結

          直播作為互聯網新賽道,直播+的模式可用于產品宣發、獲客、促活等各個方面,挑戰與機遇并存。但正因為是新賽道,也相對缺乏體系化的方法論。本文主要是分享我在工作中沉淀下來的直播復盤方法論,也歡迎大家有什么見解或者想法也可以與我分享。

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼ben_lanlan,報下信息,會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          文章來源:優設  作者:番茄

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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




          CORS和JSONP的區別,如何解決跨域問題?

          前端達人

          在我們了解JSONP 和 CORS 之前我們先明確一下:

          我們為什么要使用cors和jsonp呢?

          實際上,cors和jsonp都是用于解決跨域問題,當兩個頁面的協議、域名、端口號中有一個不一致時就存在了跨域,一旦出現跨域,瀏覽器發送跨域請求后,請求回來的數據都會被瀏覽器所攔截,準備一張圖給大家看看:

           

          核心點:如何實現跨域數據請求?(?????)

          現下實現跨域數據請求,最主要的兩種解決方案分別是 JSONP 和 CORS 。

          JSONP  出現的早,兼容性好(兼容低版本 IE )。是前端程序員為了解決跨域問題,被迫想出來的一種 臨時解決方案,最主要的缺點 是只支持 GET 請求,不支持 POST 請求。
          CORS  出現的較晚,它是 W3C 標準,屬于跨域 Ajax 請求的根本解決方案。支持 GET 和 POST 請 求。缺點 是不兼容某些低版本的瀏覽器。

          什么是JSONP(???)

          JSONP (JSON with Padding) 是 JSON 的一種“使用模式”,可用于解決主流瀏覽器的跨域數據訪問的問題。

          JSONP的實現原理(???) 

          1. 概念:瀏覽器端通過 <script> 標簽的 src 屬性,請求服務器上的數據,同時,服務器返回一個函數的調用。這種請求數據的方式叫做 JSONP

          2. 特點: 

             JSONP 不屬于真正的 Ajax 請求,因為它沒有使用 XMLHttpRequest 這個對象

              JSONP 僅支持 GET 請求,不支持 POST、PUTDELETE 等請求

          什么是CORS(?????)

          1. CORS (跨域資源共享) 由一系列 HTTP 響應頭組成,這些 HTTP 響應頭決定瀏覽器 是否阻止前端 JS 代碼跨域獲取資源

          2. 瀏覽器的同源安全策略默認會阻止網頁“跨域”獲取資源。但如果接口服務器配置了 CORS 相關的 HTTP 響應頭,就可以解除瀏覽器端的跨域訪問限制

           

           

          下面分別向大家演示通過CORS和JSONP實現跨域的案例:

          一、通過CORS中間件解決跨域問題 :

          index.html文件代碼演示:

          
              
          1. <!DOCTYPE html>
          2. <html lang="en">
          3. <head>
          4. <meta charset="UTF-8">
          5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
          6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
          7. <title>Document</title>
          8. <script src="jquery.min.js"></script>
          9. </head>
          10. <body>
          11. <button class="get">get請求</button>
          12. <button class="post">post請求</button>
          13. <script>
          14. $('.get').on('click', function() {
          15. $.ajax({
          16. method: 'get',
          17. url: 'http://127.0.0.1/api/get?name=hua&age=18',
          18. success: function(res) {
          19. console.log(res);
          20. }
          21. })
          22. })
          23. $('.post').on('click', function() {
          24. $.ajax({
          25. method: 'post',
          26. url: 'http://127.0.0.1/api/post',
          27. data: {
          28. name: 'lajitong',
          29. age: '111'
          30. },
          31. success: function(res) {
          32. console.log(res);
          33. }
          34. })
          35. })
          36. </script>
          37. </body>
          38. </html>

          此時會出現跨域問題,我們需要使用 cors 中間件解決跨域問題

          1. cors 是 Express 的一個第三方中間件。通過安裝和配置 cors 中間件,可以很方便地解決跨域問題

          2. 使用步驟

            • 安裝中間件: npm install cors

            • 導入中間件: const cors = require('cors')

            • 配置中間件: 在路由之前調用app.use(cors())

          3. express接口案例代碼

          
              
          1. // 導入 express 模塊
          2. const express = require('express')
          3. // 創建 express 的服務器實例
          4. const app = express()
          5. // 導入中間件
          6. const cors = require('cors')
          7. // 配置中間件
          8. app.use(cors())
          9. // 配置解析表單數據的中間件
          10. app.use(express.urlencoded({ extended: false }))
          11. // 導入路由模塊(被單獨分離后導入)
          12. const router = require('./apiRouter')
          13. // 把路由模塊,注冊到 app 上
          14. app.use('/api', router)
          15. // 調用 app.listen 方法,指定端口號并啟動 web 服務器
          16. app.listen(80, () => {
          17. console.log('http://127.0.0.1')
          18. })

          apiRouter路由文件代碼:

          
              
          1. const express = require('express');
          2. const router = express.Router();
          3. router.get('/get', (req, res) => {
          4. const query = req.query;
          5. res.send({
          6. status: 0,
          7. msg: 'get請求成功',
          8. data: query
          9. })
          10. })
          11. router.post('/post', (req, res) => {
          12. // const body = req.body; //獲取客戶端請求的數據
          13. res.send({
          14. status: 0,
          15. msg: 'post請求成功',
          16. data: req.body
          17. })
          18. })
          19. module.exports = router;

          在終端中運行express接口代碼后打開index.html文件并點擊get及post按鈕得到請求結果:

           二、通過JSONP中間件解決跨域問題 :

          創建 JSONP 接口的注意事項

          1. 如果項目中已經配置了 CORS 跨域資源共享,為了防止沖突,必須在配置 CORS 中間件之前聲明 JSONP 的接口

            否則 JSONP 接口會被處理成開啟了 CORS 的接口

          2. 實現步驟:

                  (1)獲取客戶端發送過來的回調函數的名字

                  (2)得到要通過 JSONP 形式發送給客戶端的數據

                  (3)根據前兩步得到的數據,拼接出一個函數調用的字符串

                  (4)把上一步拼接得到的字符串,響應給客戶端的 <script> 標簽進行解析執行

          案例代碼如下:

          
              
          1. //導入express模塊
          2. const express = require('express');
          3. //創建express服務器實例
          4. const app = express();
          5. //掛載路由
          6. app.get('/jsonp', (req, res) => {
          7. // 通過解構req.query客戶端通過查詢字符串的形式發送到客戶端的參數fn
          8. const { callback } = req.query
          9. //在服務器端定義一個obj對象
          10. const obj = {
          11. uname: 'zjj',
          12. age: '18'
          13. }
          14. //obj對象轉為res.send可處理的字符串形式后從服務器端相應回調函數至客戶端
          15. res.send(`${callback}(${JSON.stringify(obj)})`)
          16. })
          17. app.listen(80, () => {
          18. console.log('http://127.0.0.1');
          19. })

          創建jsonp.html客戶端來接收服務器端響應過來的回調函數,代碼如下:

          url中callback=fn為客戶端發送請求攜帶的參數 既服務器端中的req.query.callback

          
              
          1. <script>
          2. function fn(res) {
          3. console.log(res);
          4. }
          5. </script>
          6. <script src="http://127.0.0.1/jsonp?callback=fn"></script>




          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          轉自:csdn
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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

          移動端、PC端 網頁特效

          前端達人

          移動端網頁特效

          觸屏事件

          移動端瀏覽器兼容性較好,不需要考慮以前 JS 的兼容性問題,可以放心的使用原生 JS 書寫效果,但是移動端也有自己獨特的地方。比如觸屏事件 touch(也稱觸摸事件),Android 和 IOS 都有。

          touch 對象代表一個觸摸點。觸摸點可能是一根手指,也可能是一根觸摸筆。觸屏事件可響應用戶手指(或觸控筆)對屏幕或者觸控板操作。

          常見的觸屏事件:
          在這里插入圖片描述
          觸摸事件對象(TouchEvent)

          TouchEvent 是一類描述手指在觸摸平面(觸摸屏、觸摸板等)的狀態變化的事件。這類事件用于描述一個或多個觸點,使開發者可以檢測觸點的移動,觸點的增加和減少,等等

          touchstart、touchmove、touchend 三個事件都會各自有事件對象。

          觸摸事件對象常見對象列表:
          在這里插入圖片描述
          因為平時都是給元素注冊觸摸事件,所以重點記住 targetTocuhes

          移動端拖動元素JS代碼實現:

          // (1) 觸摸元素 touchstart:  獲取手指初始坐標,同時獲得盒子原來的位置 // (2) 移動手指 touchmove:  計算手指的滑動距離,并且移動盒子 // (3) 離開手指 touchend: var div = document.querySelector('div'); var startX = 0; //獲取手指初始坐標 var startY = 0; var x = 0; //獲得盒子原來的位置 var y = 0; div.addEventListener('touchstart', function(e) { //  獲取手指初始坐標 startX = e.targetTouches[0].pageX; startY = e.targetTouches[0].pageY; x = this.offsetLeft; y = this.offsetTop; }); div.addEventListener('touchmove', function(e) { //  計算手指的移動距離: 手指移動之后的坐標減去手指初始的坐標 var moveX = e.targetTouches[0].pageX - startX; var moveY = e.targetTouches[0].pageY - startY; // 移動我們的盒子 盒子原來的位置 + 手指移動的距離 this.style.left = x + moveX + 'px'; this.style.top = y + moveY + 'px'; e.preventDefault(); // 阻止屏幕滾動的默認行為 }); 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25

          classList屬性

          classList屬性是HTML5新增的一個屬性。返回元素的類名,該屬性用在元素中添加、移除及切換CSS類

          <style> .bg { background-color: black; } </style> <body> <div class="one two"></div> <button> 開關燈</button> <script> // classList 返回元素的類名 var div = document.querySelector('div'); // console.log(div.classList[1]); // 1. 添加類名  是在后面追加類名不會覆蓋以前的類名 注意前面不需要加. div.classList.add('three'); // 2. 刪除類名 div.classList.remove('one'); // 3. 切換類 var btn = document.querySelector('button'); btn.addEventListener('click', function() { document.body.classList.toggle('bg'); }) </script> </body> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24

          常用開發插件

          移動端 要求的是快速開發,所以經常會借助于一些插件來幫完成操作

          JS 插件是 js 文件,它遵循一定規范編寫,方便程序展示效果,擁有特定功能且方便調用。如輪播圖和瀑布流插件

          插件的使用:

          1. 引入 js 插件文件
          2. 按照規定語法使用

          特點: 它一般是為了解決某個問題而專門存在,其功能單一,并且比較小。比如移動端常見插件:iScroll、Swiper、SuperSlider

          PC端網頁特效

          偏移量系列 offset

          offset 翻譯過來就是偏移量, 使用 offset 系列相關屬性可以 動態 的得到該元素的位置(偏移)、大小等。

          • 獲得元素距離帶有定位父元素的位置
          • 獲得元素自身的大小(寬度高度)
          • 注意: 返回的數值都不帶單位

          常用屬性:
          在這里插入圖片描述
          圖示:
          在這里插入圖片描述

          offset與style區別:

          offset style
          可以得到任意樣式表中的樣式值 只能得到行內樣式表中的樣式值
          offset系列獲得的數值是沒有單位的 style.width 獲得的是帶有單位的字符串
          offsetWidth 包含padding+border+width style.width 獲得不包含padding和border 的值
          offsetWidth 等屬性是只讀屬性,只能獲取不能賦值 style.width 是可讀寫屬性,可以獲取也可以賦值
          獲取元素大小位置,用offset更合適 元素更改值,則需要用style改變

          案例——獲取鼠標在盒子內的坐標:

          效果展示:
          在這里插入圖片描述

          實現代碼(JS):

          // 在盒子內點擊, 想要得到鼠標距離盒子左右的距離。 // 首先得到鼠標在頁面中的坐標( e.pageX, e.pageY) // 其次得到盒子在頁面中的距離(box.offsetLeft, box.offsetTop) // 用鼠標距離頁面的坐標減去盒子在頁面中的距離, 得到 鼠標在盒子內的坐標 var box = document.querySelector('.box'); box.addEventListener('mousemove', function(e) { // console.log(e.pageX); // console.log(e.pageY); // console.log(box.offsetLeft); var x = e.pageX - this.offsetLeft; var y = e.pageY - this.offsetTop; this.innerHTML = 'x坐標是' + x + ' y坐標是' + y; }) 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13

          案例——模態拖拽框:

          • 點擊彈出層, 會彈出模態框, 并且顯示灰色半透明的遮擋層。
          • 點擊關閉按鈕,可以關閉模態框,并且同時關閉灰色半透明遮擋層。
          • 鼠標放到模態框最上面一行,可以按住鼠標拖拽模態框在頁面中移動。
          • 鼠標松開,可以停止拖動模態框移動。

          效果展示:
          在這里插入圖片描述

          實現代碼:

          <head lang="en"> <meta charset="UTF-8"> <title></title> <style> .login-header { width: 100%; text-align: center; height: 30px; font-size: 24px; line-height: 30px; } ul,li,ol,dl,dt,dd,div,p,span,h1,h2,h3,h4,h5,h6,a { padding: 0px; margin: 0px; } .login { display: none; width: 512px; height: 280px; position: fixed; border: #ebebeb solid 1px; left: 50%; top: 50%; background: #ffffff; box-shadow: 0px 0px 20px #ddd; z-index: 9999; transform: translate(-50%, -50%); } .login-title { width: 100%; margin: 10px 0px 0px 0px; text-align: center; line-height: 40px; height: 40px; font-size: 18px; position: relative; cursor: move; } .login-input-content { margin-top: 20px; } .login-button { width: 50%; margin: 30px auto 0px auto; line-height: 40px; font-size: 14px; border: #ebebeb 1px solid; text-align: center; } .login-bg { display: none; width: 100%; height: 100%; position: fixed; top: 0px; left: 0px; background: rgba(0, 0, 0, .3); } a { text-decoration: none; color: #000000; } .login-button a { display: block; } .login-input input.list-input { float: left; line-height: 35px; height: 35px; width: 350px; border: #ebebeb 1px solid; text-indent: 5px; } .login-input { overflow: hidden; margin: 0px 0px 20px 0px; } .login-input label { float: left; width: 90px; padding-right: 10px; text-align: right; line-height: 35px; height: 35px; font-size: 14px; } .login-title span { position: absolute; font-size: 12px; right: -20px; top: -30px; background: #ffffff; border: #ebebeb solid 1px; width: 40px; height: 40px; border-radius: 20px; } </style> </head> <body> <div class="login-header"><a id="link" href="javascript:;">點擊,彈出登錄框</a></div> <div id="login" class="login"> <div id="title" class="login-title">登錄會員 <span><a id="closeBtn" href="javascript:void(0);" class="close-login">關閉</a></span> </div> <div class="login-input-content"> <div class="login-input"> <label>用戶名:</label> <input type="text" placeholder="請輸入用戶名" name="info[username]" id="username" class="list-input"> </div> <div class="login-input"> <label>登錄密碼:</label> <input type="password" placeholder="請輸入登錄密碼" name="info[password]" id="password" class="list-input"> </div> </div> <div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">登錄會員</a></div> </div> <!-- 遮蓋層 --> <div id="bg" class="login-bg"></div> <script> // 1. 獲取元素 var login = document.querySelector('.login'); var mask = document.querySelector('.login-bg'); var link = document.querySelector('#link'); var closeBtn = document.querySelector('#closeBtn'); var title = document.querySelector('#title'); // 2. 點擊彈出層這個鏈接 link  讓mask 和login 顯示出來 link.addEventListener('click', function() { mask.style.display = 'block'; login.style.display = 'block'; }) // 3. 點擊 closeBtn 就隱藏 mask 和 login  closeBtn.addEventListener('click', function() { mask.style.display = 'none'; login.style.display = 'none'; }) // 4. 開始拖拽 // (1) 當我們鼠標按下, 就獲得鼠標在盒子內的坐標 title.addEventListener('mousedown', function(e) { var x = e.pageX - login.offsetLeft; var y = e.pageY - login.offsetTop; // (2) 鼠標移動的時候,把鼠標在頁面中的坐標,減去 鼠標在盒子內的坐標就是模態框的left和top值 document.addEventListener('mousemove', move) function move(e) { login.style.left = e.pageX - x + 'px'; login.style.top = e.pageY - y + 'px'; } // (3) 鼠標彈起,就讓鼠標移動事件移除 document.addEventListener('mouseup', function() { document.removeEventListener('mousemove', move); }) }) </script> </body> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84
          • 85
          • 86
          • 87
          • 88
          • 89
          • 90
          • 91
          • 92
          • 93
          • 94
          • 95
          • 96
          • 97
          • 98
          • 99
          • 100
          • 101
          • 102
          • 103
          • 104
          • 105
          • 106
          • 107
          • 108
          • 109
          • 110
          • 111
          • 112
          • 113
          • 114
          • 115
          • 116
          • 117
          • 118
          • 119
          • 120
          • 121
          • 122
          • 123
          • 124
          • 125
          • 126
          • 127
          • 128
          • 129
          • 130
          • 131
          • 132
          • 133
          • 134
          • 135
          • 136
          • 137
          • 138
          • 139
          • 140
          • 141
          • 142
          • 143
          • 144
          • 145
          • 146
          • 147
          • 148
          • 149
          • 150
          • 151
          • 152
          • 153
          • 154
          • 155
          • 156
          • 157
          • 158
          • 159
          • 160
          • 161
          • 162
          • 163
          • 164
          • 165
          • 166
          • 167
          • 168

          可視區系列 client

          client 翻譯過來就是客戶端,使用 client 系列的相關屬性來獲取元素可視區的相關信息。通過 client 系列的相關屬性可以動態的得到該元素的邊框大小、元素大小等。

          常用屬性:
          在這里插入圖片描述
          client和offset最大的區別就是 :不包含邊框
          圖示:
          在這里插入圖片描述

          滾動系列 scroll

          scroll 翻譯過來就是滾動的,使用 scroll 系列的相關屬性可以動態的得到該元素的大小、滾動距離等。

          常用屬性:
          在這里插入圖片描述
          圖示:
          在這里插入圖片描述

          滾動條:

          • 如果瀏覽器的高(或寬)度不足以顯示整個頁面時,會自動出現滾動條。
          • 當滾動條向下滾動時,頁面上面被隱藏掉的高度,稱為頁面被卷去的頭部。
          • 滾動條在滾動時會觸發 onscroll 事件。

          案例——固定右側側邊欄:

          • 原先側邊欄是絕對定位
          • 當頁面滾動到一定位置,側邊欄改為固定定位
          • 頁面繼續滾動,會讓 返回頂部顯示出來

          效果展示:
          在這里插入圖片描述

          實現代碼:

          <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Document</title> <style> .slider-bar { position: absolute; left: 50%; top: 300px; margin-left: 600px; width: 45px; height: 130px; background-color: pink; } .w { width: 1200px; margin: 10px auto; } .header { height: 150px; background-color: purple; } .banner { height: 250px; background-color: skyblue; } .main { height: 1000px; background-color: yellowgreen; } span { display: none; position: absolute; bottom: 0; } </style> </head> <body> <div class="slider-bar"> <span class="goBack">返回頂部</span> </div> <div class="header w">頭部區域</div> <div class="banner w">banner區域</div> <div class="main w">主體部分</div> <script> //1. 獲取元素 var sliderbar = document.querySelector('.slider-bar'); var banner = document.querySelector('.banner'); // banner.offestTop 就是被卷去頭部的大小 一定要寫到滾動的外面 var bannerTop = banner.offsetTop // 當側邊欄固定定位之后應該變化的數值 var sliderbarTop = sliderbar.offsetTop - bannerTop; // 獲取main 主體元素 var main = document.querySelector('.main'); var goBack = document.querySelector('.goBack'); var mainTop = main.offsetTop; // 2. 頁面滾動事件 scroll document.addEventListener('scroll', function() { // window.pageYOffset 頁面被卷去的頭部 // console.log(window.pageYOffset); // 3 .當頁面被卷去的頭部大于等于了 172 此時 側邊欄就要改為固定定位 if (window.pageYOffset >= bannerTop) { sliderbar.style.position = 'fixed'; sliderbar.style.top = sliderbarTop + 'px'; } else { sliderbar.style.position = 'absolute'; sliderbar.style.top = '300px'; } // 4. 當我們頁面滾動到main盒子,就顯示 goback模塊 if (window.pageYOffset >= mainTop) { goBack.style.display = 'block'; } else { goBack.style.display = 'none'; } }) </script> </body> 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20
          • 21
          • 22
          • 23
          • 24
          • 25
          • 26
          • 27
          • 28
          • 29
          • 30
          • 31
          • 32
          • 33
          • 34
          • 35
          • 36
          • 37
          • 38
          • 39
          • 40
          • 41
          • 42
          • 43
          • 44
          • 45
          • 46
          • 47
          • 48
          • 49
          • 50
          • 51
          • 52
          • 53
          • 54
          • 55
          • 56
          • 57
          • 58
          • 59
          • 60
          • 61
          • 62
          • 63
          • 64
          • 65
          • 66
          • 67
          • 68
          • 69
          • 70
          • 71
          • 72
          • 73
          • 74
          • 75
          • 76
          • 77
          • 78
          • 79
          • 80
          • 81
          • 82
          • 83
          • 84

          三大系列作用區別:
          在這里插入圖片描述

          它們主要用法:

          系列 作用 屬性
          offset 用于獲得元素位置 offsetLeft offsetTop
          client 用于獲取元素大小 clientWidth clientHeight
          scroll 用于獲取滾動距離 scrollTop scrollLeft

          注意:頁面滾動的距離通過 window.pageXOffset 獲得

          動畫原理

          核心原理:通過定時器 setInterval() 不斷移動盒子位置

          實現步驟:

          1. 獲得盒子當前位置
          2. 讓盒子在當前位置加上1個移動距離
          3. 利用定時器不斷重復這個操作
          4. 加一個結束定時器的條件
          5. 注意此元素需要添加定位,才能使用 element.style.left

          簡單動畫函數封裝:

          // 簡單動畫函數封裝obj目標對象 target 目標位置 function animate(obj, target) { var timer = setInterval(function() { if (obj.offsetLeft >= target) { // 停止動畫 本質是停止定時器 clearInterval(timer); } //每次均勻向右移動1px obj.style.left = obj.offsetLeft + 1 + 'px'; }, 30); } 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12

          緩動效果原理:

          緩動動畫就是讓元素運動速度有所變化,最常見的是讓速度慢慢停下來

          1. 讓盒子每次移動的距離慢慢變小,速度就會慢慢落下來。
          2. 核心算法: (目標值 - 現在的位置 ) / 10 做為每次移動的距離步長
          3. 停止的條件是: 讓當前盒子位置等于目標位置就停止定時器
          4. 注意步長值需要取整
          // 緩動動畫函數封裝obj目標對象 target 目標位置 // 思路: // 1. 讓盒子每次移動的距離慢慢變小, 速度就會慢慢落下來。 // 2. 核心算法:(目標值 - 現在的位置) / 10 做為每次移動的距離 步長 // 3. 停止的條件是: 讓當前盒子位置等于目標位置就停止定時器 function animate(obj, target) { // 先清除以前的定時器,只保留當前的一個定時器執行 clearInterval(obj.timer); obj.timer = setInterval(function() { // 步長值寫到定時器的里面 var step = (target - obj.offsetLeft) / 10; if (obj.offsetLeft == target) { // 停止動畫 本質是停止定時器 clearInterval(obj.timer); } // 把每次加1 這個步長值改為一個慢慢變小的值  步長公式:(目標值 - 現在的位置) / 10 obj.style.left = obj.offsetLeft + step + 'px'; }, 15); } 
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14
          • 15
          • 16
          • 17
          • 18
          • 19
          • 20

          多個目標值之間移動:

          當開始移動時候,判斷步長是正值還是負值

          • 如果是正值,則步長 往大了取整
          • 如果是負值,則步長 向小了取整

          動畫函數封裝到單獨JS文件: animate.js

          function animate(obj, target, callback) { // 先清除以前的定時器,只保留當前的一個定時器執行 clearInterval(obj.timer); obj.timer = setInterval(function() { // 步長值寫到定時器的里面 // 把步長值改為整數 不要出現小數的問題 // var step = Math.ceil((target - obj.offsetLeft) / 10); var step = (target - obj.offsetLeft) / 10; step = step > 0 ? Math.ceil(step) : Math.floor(step); if (obj.offsetLeft == target) { // 停止動畫 本質是停止定時器 clearInterval(obj.timer); // 回調函數寫到定時器結束里面 // if (callback) { //     // 調用函數 //     callback(); // } callback && callback(); } // 把每次加1 這個步長值改為一個慢慢變小的值  步長公式:(目標值 - 現在的位置) / 10 obj.style.left = obj.offsetLeft + step + 'px'; }, 15); }
          

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.

          轉自:csdn 免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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

          展開全文后需要支持收起嗎?從運用場景分析交互邏輯

          seo達人



          圖片

          展開和收起屬于比較細節的問題,按照慣性思維,內容多了我就折疊一部分,用戶需要看更多內容就點擊「展開」,內容展開之后,相應的還應該支持內容的「收起」。

          整個流程這樣看起來沒什么毛病,但是卻缺少一個重要的前提,哪些場景或者什么情況下才需要展開或收起呢?

          如果只是單純給出一個流程,顯然缺乏對產品邏輯和用戶體驗上的思考??赡芎芏嘣O計師之前沒怎么注意過這個地方的交互邏輯,或者深入思考需要注意的問題,這次借著答疑的機會咱們一起來深入探討下。

           

          1、拋開展開和收起

          雖然提出的問題是分析展開和收起的運用場景,但是我覺得不應該一上來就陷入到具體的細節里。

          這個問題相對來說屬于比較小的點,直接鉆到細節里會讓我們只盯著這一小部分,缺少對全局的思考,因小失大

          盯著已有的設計進行推導,這樣多少帶有個人主觀的臆想。先不要盯著具體的展開和收起功能來想場景,反過來想,在設計過程中有哪些地方需要這樣的交互邏輯,為什么需要呢?

          無論面對什么樣的設計需求,這樣的思考過程會一直伴隨著我們。

           

          2、先場景后行為

          先回到場景上,考慮哪些場景會觸發「展開和收起」行為,再具體問題具體分析。

          場景一:當某段內容字數太多,占據了大面積的空間,如果用戶不想看這些長篇大論,想看下一個內容,要滑動屏幕很久才能略過這些內容,顯然我們不想給用戶帶來這樣的操作負擔,這時候就可以考慮添加收起功能,把多余的內容收起來。

          這里的收起需要注意兩點:

          • 內容被收起不代表被收起的內容不重要;
          • 收起相對節約屏幕空間,用戶更方便上下滑動查看內容。

          場景二:頁面上仍然有很多內容,但是這些內容有主次之分,我們想讓用戶最先看到前面的內容,后面的內容可以考慮收起來突出重點并節省空間。

          這里的收起就和場景一有差異,可能被收起的內容相對沒這么重要,只露出重點/熱點內容或權益來吸引用戶,相對次要的內容被收起,這里的收起會涉及到內容重要程度的排序,這種排序就可以體現在排行榜設計中。

           

          3、展開然后收起

          展開和收起屬于一組行為,看到展開我們必然會聯想到收起。展開是為了看到完整的內容,收起則是內容看完的標志,點擊收起可以繼續下一個內容。

          在知乎問答中,我們首先看到的是標題的問題,這些問題往往言簡意賅,通常光看標題我們就能知道這個問題想表達什么意思。

          圖片

          ▲ 標題下面的問題簡介是對標題的進一步解釋和補充,這里的簡介作為說明性文字,就支持展開和收起。當簡介內容太多時,就要考慮折疊一部分簡介,這樣能保證在首屏上能同時看到問題和答案。

          另外當內容很多,以信息流的形式呈現,并且需要上下滑動來瀏覽時,就可以考慮使用現展開后收起。

          比如在微信朋友圈,如果文字內容較多,就會被收起一部分,想看完整的內容則需要點擊「全文」選項,看完后點擊「收起」,內容就會被折疊起來,方便我們繼續滑動瀏覽其他朋友圈。

           

          4、展開后不收起

          點完展開看到了全部內容,卻沒有收起選項,但是這樣并不影響我們的觀看體驗,而且展開這個動作給用戶和頁面帶來的反應都很小,不會讓用戶感到不適。之所以選擇「展開」,一個重要的原因是因為我們有想看完整內容的強烈需求。在這種意愿的號召下,我們會毫不猶豫地選擇展開功能。圖片

          ▲ 在豆瓣電影介紹頁中,在劇情簡介區域會有「展開」提示,如果我們選擇展開,說明我們有觀看完整簡介的意愿,并且是主動選擇展開,不添加「收起」選項正好避免了給我們增加操作上的負擔。

          另外,當內容相對沒那么多,能在一屏上顯示,不需要用戶上下滑動太多時,可以考慮省去收起,比如在QQ群介紹、抖音個人頁的簡介等。

           

          最后

          以上是我對展開和收起的運用場景的一些小思考,主要從場景角度來考慮交互邏輯。

          授人以魚不如授人以漁,關于展開和收起的場景還有很多,希望大家能掌握這樣的思考邏輯,去發掘更深層的設計內容,當然有問題咱們可以隨時溝通~

           

          原文地址:Clip設計夾(公眾號)

          作者:Clippp

          轉載請注明:學UI網》展開全文后需要支持收起嗎?從運用場景分析交互邏輯

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          截屏2021-05-13 上午11.41.03.png

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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




          2021 必備的超贊神器,用上它,效率都要提升三倍??!

          seo達人


          圖片
          上圖就是這個神器制作出來的一些效果,之前看Dribble上面有很多類似的設計,現在終于知道它們大部分來源于這個神器。
          下面我也找了一些案例,大家一起來看看。
          圖片
          圖片
          圖片
          這樣看,效果還是真的不錯,它支持顏色修改、樣式修改,目前一共有11種幾何樣式。
          圖片
          好了,現在下面正式介紹這個傳說中的神器,我相信大家一定會喜歡上的。
          圖片
          上圖就是這個神器的基本外貌,一共11種基礎類型,當點擊其中一個進去后,可以進行編輯。
          這里我點擊上圖中的第二個模式(MIXTAPE)進去。
          圖片
          如果大家英文不好,可以將整個頁面翻譯成中文,Google自帶的翻譯。
          進入這個頁面,大家可以根據自己喜歡的風格調整樣式,同時還可以修改顏色。
          圖片

          比如我可以選擇8X12列和行的幾何布局。

          圖片
          對顏色、列和行、開啟陰影調整,得到如上效果。
          圖片

          最終可以導出一張高清大圖(3240X4860),尺寸是完全夠用的。

          圖片

          隨便調整下又是一張不錯的幾何背景,還可以作為作品集封面。好了,關鍵時刻來了,神器的網址已經打包好,大家可以拿去使用。

          領取方式如下:添加小編微信,備注:神器699,小編會將下載地址發給你(小編不是機器人,回復會慢一些,大家稍等)。

           

          原文地址:功夫UX (公眾號)
          作者: 功夫UX
          轉載請注明:學UI網》2021 必備的超贊神器,用上它,效率都要提升三倍??!

          藍藍設計建立了UI設計分享群,每天會分享國內外的一些優秀設計,如果有興趣的話,可以進入一起成長學習,請掃碼藍小助,報下信息,藍小助會請您入群。歡迎您加入噢~~希望得到建議咨詢、商務合作,也請與我們聯系。

          截屏2021-05-13 上午11.41.03.png

          分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。

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


          日歷

          鏈接

          個人資料

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

          存檔

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