<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+html版本與python版本】

          前端達人

          文章來源:人人都是產品經理   作者:新榜

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

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

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

          一、春聯一

          1.前言

          需要代碼文末公眾號找我 回復【春聯】即可獲取
          在這里插入圖片描述

          效果展示

          在這里插入圖片描述

          3.代碼展示

          index.html

          <!DOCTYPE html> <html lang="en" > <head> <meta charset="UTF-8"> <title>css3春聯切換</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <div class="rotating-text"> <p>春聯Show</p> <p> <span class="word alizarin">上聯:這個需求很簡單</span> <span class="word wisteria">下聯:怎么實現我不管</span> <span class="word peter-river">橫批:明天上線!</span> </p> </div> <script src="js/script.js"></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

          style.css

          @import url(https://fonts.googleapis.com/css?family=Lato:600); body { display: flex; justify-content: center; align-items: center; height: 100vh; background: #222; } .rotating-text { font-family: Lato, sans-serif; font-weight: 600; font-size: 36px; color: white; transform: translateX(-80px); } .rotating-text p { display: inline-flex; margin: 0; vertical-align: top; } .rotating-text p .word { position: absolute; display: flex; opacity: 0; } .rotating-text p .word .letter { transform-origin: center center 25px; } .rotating-text p .word .letter.out { transform: rotateX(90deg); transition: 0.32s cubic-bezier(0.6, 0, 0.7, 0.2); } .rotating-text p .word .letter.in { transition: 0.38s ease; } .rotating-text p .word .letter.behind { transform: rotateX(-90deg); } .alizarin { color: #e74c3c; } .wisteria { color: #8e44ad; } .peter-river { color: #3498db; } .emerald { color: #2ecc71; } .sun-flower { color: #f1c40f; }  
          
          • 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

          script.js

          var words = document.querySelectorAll(".word"); words.forEach(function (word) { var letters = word.textContent.split(""); word.textContent = ""; letters.forEach(function (letter) { var span = document.createElement("span"); span.textContent = letter; span.className = "letter"; word.append(span); }); }); var currentWordIndex = 0; var maxWordIndex = words.length - 1; words[currentWordIndex].style.opacity = "1"; var rotateText = function () { var currentWord = words[currentWordIndex]; var nextWord = currentWordIndex === maxWordIndex ? words[0] : words[currentWordIndex + 1]; // rotate out letters of current word Array.from(currentWord.children).forEach(function (letter, i) { setTimeout(function () { letter.className = "letter out"; }, i * 80); }); // reveal and rotate in letters of next word nextWord.style.opacity = "1"; Array.from(nextWord.children).forEach(function (letter, i) { letter.className = "letter behind"; setTimeout(function () { letter.className = "letter in"; }, 340 + i * 80); }); currentWordIndex = currentWordIndex === maxWordIndex ? 0 : currentWordIndex + 1; }; rotateText(); setInterval(rotateText, 4000);  
          
          • 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

          二、春聯二

          1.環境準備

          1.當缺少庫時會有相應提示 黑窗口執行下方命令+包名即可下載安裝
          2.博主此處用的idea 直接Alt+Enter直接下載就成了
          3.idea配置python環境也可以參考此文:Python(含PyCharm及配置)下載安裝以及簡單使用(Idea)

          2.效果展示

          在這里插入圖片描述
          在這里插入圖片描述

          3.代碼

          import io from PIL import Image #import numpy as np import requests def get_word(ch, quality): """獲取單個漢字(字符)的圖片
              ch          - 單個漢字或英文字母(僅支持大寫)
              quality     - 單字分辨率,H-640像素,M-480像素,L-320像素
              """ fp = io.BytesIO(requests.post(url='http://xufive.sdysit.com/tk', data={'ch': ch}).content) im = Image.open(fp) w, h = im.size if quality == 'M': w, h = int(w * 0.75), int(0.75 * h) elif quality == 'L': w, h = int(w * 0.5), int(0.5 * h) return im.resize((w, h)) def get_bg(quality): """獲取春聯背景的圖片""" return get_word('bg', quality) def write_couplets(text, HorV='V', quality='L', out_file=None): """生成春聯
          
              text        - 春聯內容,以空格斷行
              HorV        - H-橫排,V-豎排
              quality     - 單字分辨率,H-640像素,M-480像素,L-320像素
              out_file    - 輸出文件名
              """ usize = {'H': (640, 23), 'M': (480, 18), 'L': (320, 12)} bg_im = get_bg(quality) text_list = [list(item) for item in text.split()] rows = len(text_list) cols = max([len(item) for item in text_list]) if HorV == 'V': ow, oh = 40 + rows * usize[quality][0] + (rows - 1) * 10, 40 + cols * usize[quality][0] else: ow, oh = 40 + cols * usize[quality][0], 40 + rows * usize[quality][0] + (rows - 1) * 10 out_im = Image.new('RGBA', (ow, oh), '#f0f0f0') for row in range(rows): if HorV == 'V': row_im = Image.new('RGBA', (usize[quality][0], cols * usize[quality][0]), 'white') offset = (ow - (usize[quality][0] + 10) * (row + 1) - 10, 20) else: row_im = Image.new('RGBA', (cols * usize[quality][0], usize[quality][0]), 'white') offset = (20, 20 + (usize[quality][0] + 10) * row) for col, ch in enumerate(text_list[row]): if HorV == 'V': pos = (0, col * usize[quality][0]) else: pos = (col * usize[quality][0], 0) ch_im = get_word(ch, quality) row_im.paste(bg_im, pos) row_im.paste(ch_im, (pos[0] + usize[quality][1], pos[1] + usize[quality][1]), mask=ch_im) out_im.paste(row_im, offset) if out_file: out_im.convert('RGB').save(out_file) out_im.show() text = '思前想后幾行代碼筑萬載春秋 扶內保外一千精英帶五千干將' #對聯內容 write_couplets(text, HorV='V', quality='M', out_file='春聯.jpg') #生成普天同慶.jpg對聯圖片  
                      
          • 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
          白哥Java
          微信公眾號
          獲取Java面試資料/簡歷模板/項目資料
          3.代碼

          import io from PIL import Image #import numpy as np import requests def get_word(ch, quality): """獲取單個漢字(字符)的圖片 ch - 單個漢字或英文字母(僅支持大寫) quality - 單字分辨率,H-640像素,M-480像素,L-320像素 """ fp = io.BytesIO(requests.post(url='http://xufive.sdysit.com/tk', data={'ch': ch}).content) im = Image.open(fp) w, h = im.size if quality == 'M': w, h = int(w * 0.75), int(0.75 * h) elif quality == 'L': w, h = int(w * 0.5), int(0.5 * h) return im.resize((w, h)) def get_bg(quality): """獲取春聯背景的圖片""" return get_word('bg', quality) def write_couplets(text, HorV='V', quality='L', out_file=None): """生成春聯 text - 春聯內容,以空格斷行 HorV - H-橫排,V-豎排 quality - 單字分辨率,H-640像素,M-480像素,L-320像素 out_file - 輸出文件名 """ usize = {'H': (640, 23), 'M': (480, 18), 'L': (320, 12)} bg_im = get_bg(quality) text_list = [list(item) for item in text.split()] rows = len(text_list) cols = max([len(item) for item in text_list]) if HorV == 'V': ow, oh = 40 + rows * usize[quality][0] + (rows - 1) * 10, 40 + cols * usize[quality][0] else: ow, oh = 40 + cols * usize[quality][0], 40 + rows * usize[quality][0] + (rows - 1) * 10 out_im = Image.new('RGBA', (ow, oh), '#f0f0f0') for row in range(rows): if HorV == 'V': row_im = Image.new('RGBA', (usize[quality][0], cols * usize[quality][0]), 'white') offset = (ow - (usize[quality][0] + 10) * (row + 1) - 10, 20) else: row_im = Image.new('RGBA', (cols * usize[quality][0], usize[quality][0]), 'white') offset = (20, 20 + (usize[quality][0] + 10) * row) for col, ch in enumerate(text_list[row]): if HorV == 'V': pos = (0, col * usize[quality][0]) else: pos = (col * usize[quality][0], 0) ch_im = get_word(ch, quality) row_im.paste(bg_im, pos) row_im.paste(ch_im, (pos[0] + usize[quality][1], pos[1] + usize[quality][1]), mask=ch_im) out_im.paste(row_im, offset) if out_file: out_im.convert('RGB').save(out_file) out_im.show() text = '思前想后幾行代碼筑萬載春秋 扶內保外一千精英帶五千干將' #對聯內容 write_couplets(text, HorV='V', quality='M', out_file='春聯.jpg') #生成普天同慶.jpg對聯圖片
           
          


          11

          222

          文章來源:csdn  作者: 分享此文一切功德,皆悉回向給文章原作者及眾讀者.
          免責聲明:藍藍設計尊重原作者,文章的版權歸原作者。如涉及版權問題,請及時與我們取得聯系,我們立即更正或刪除。
          藍藍設計( www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          JavaScript——異步操作以及Promise 的使用

          前端達人

          什么是異步?

          異步與同步是相反的

          簡單來理解就是:同步按你的代碼順序執行,異步不按照代碼順序執行,異步的執行效率更高。

          什么時候用異步編程

          在前端編程中(甚至后端有時也是這樣),我們在處理一些簡短、快速的操作時,例如計算 1 + 1 的結果,往往在主線程中就可以完成。主線程作為一個線程,不能夠同時接受多方面的請求。所以,當一個事件沒有結束時,界面將無法處理其他請求。

          現在有一個按鈕,如果我們設置它的 onclick 事件為一個死循環,那么當這個按鈕按下,整個網頁將失去響應。

          為了解決類似這種問題,JavaScript 中的異步操作函數往往通過回調函數來實現異步任務的結果處理。

          回調函數

          回調函數就是一個函數,它是在我們啟動一個異步任務的時候就告訴它:等你完成了這個任務之后要干什么。這樣一來主線程幾乎不用關心異步任務的狀態了,他自己會善始善終。

          例如:

          
          
          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>回調</title>
          8. </head>
          9. <body>
          10. <button>點擊</button>
          11. <p></p>
          12. <script>
          13. var btn = document.querySelector('button');
          14. function fn1(){
          15. btn.onclick = function(){
          16. document.querySelector('p').innerHTML = '我出現了!'
          17. }
          18. }
          19. setTimeout(fn1,1000)
          20. </script>
          21. </body>
          22. </html>

           

           它的第一個參數是個回調函數,第二個參數是毫秒數,這個函數執行之后會產生一個子線程,子線程會等待 1 秒,然后執行回調函數 "fn1",在命令行輸出 "我出現了!"。

          Promise 的使用

          語法格式:

          
          
          1. new Promise(function (resolve, reject) {
          2. console.log("Run");
          3. });

          resolve和reject是參數 

          再看這個例子:

          
          
          1. new Promise(function (resolve, reject) {
          2. var a = 0;
          3. var b = 1;
          4. if (b == 0) reject("Divide zero");
          5. else resolve(a / b);
          6. }).then(function (value) {
          7. console.log("a / b = " + value);
          8. }).catch(function (err) {
          9. console.log(err);
          10. }).finally(function () {
          11. console.log("End");
          12. });

          這段打印結果為:

          .then() .catch() 和 .finally() 三個方法

          這三個方法的參數都是一個函數,

          .then() 可以將參數中的函數添加到當前 Promise 的正常執行序列,

          .catch() 則是設定 Promise 的異常處理序列,

          .finally() 是在 Promise 執行的最后一定會執行的序列。 .then() 傳入的函數會按順序依次執行,有任何異常都會直接跳到 catch 序列:

          
          
          1. new Promise(function (resolve, reject) {
          2. console.log(1111);
          3. resolve(2222);
          4. }).then(function (value) {
          5. console.log(value);
          6. return 3333;
          7. }).then(function (value) {
          8. console.log(value);
          9. throw "An error";
          10. }).catch(function (err) {
          11. console.log(err);
          12. });

          打印結果為:

          1111
          2222
          3333
          An error

          resolve() 中可以放置一個參數用于向下一個 then 傳遞一個值,then 中的函數也可以返回一個值傳遞給 then。但是,如果 then 中返回的是一個 Promise 對象,那么下一個 then 將相當于對這個返回的 Promise 進行操作,這一點從剛才的計時器的例子中可以看出來。

          reject() 參數中一般會傳遞一個異常給之后的 catch 函數用于處理異常。

          但是請注意以下兩點:

          • resolve 和 reject 的作用域只有起始函數,不包括 then 以及其他序列;
          • resolve 和 reject 并不能夠使起始函數停止運行,別忘了 return。




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

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

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

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

          【舉栗說明】JavaScript作用域,一次性給你總結!

          前端達人

          圖片

          本文重點

          • 函數案例

          • 函數作為參數使用

          • arguments

          • 作用域:寫代碼要注意變量的在哪聲明和使用的問題

          • 預解析:什么叫預解析, 什么東西發生了什么事

          01 作用域:使用范圍

          全局變量:

          • 聲明的變量是使用var聲明的,那么這個變量就是全局變量,

          • 全局變量可以在頁面的任何位置使用

          • 除了函數以外,其他的任何位置定義的變量都是全局變量

          • 如果頁面不關閉,那么就不會釋放,就會占空間,消耗內存

          • 全局作用域:全局變量的使用范圍

          局部變量:

          • 在函數內部定義的變量,是局部變量,外面不能使用

          • 局部作用域:局部變量的使用范圍

          注意:

          塊級作用域:一對大括號就可以看成是一塊,在這塊區域中定義的變量,只能在這個區域中使用,但是在js中在這個塊級作用域中定義的變量,外面也能使用;

          說明:js沒有塊級作用域,只有函數除外

          隱式全局變量:聲明的變量沒有var,就叫隱式全局變量

          全局變量是不能被刪除的,隱式全局變量是可以被刪除的

          定義變量使用var是不會被刪除的,沒有var是可以刪除的

          function f1() {  number=1000;//是隱式全局變量 }f1();console.log(number);   var num1=10;  num2=20;  delete num1;//把num1刪除了  delete num2;//把num2刪除了  console.log(typeof num1);  console.log(num1+10);  console.log(typeof num2);  num=100; console.log(num);  function f1() {  var num=100;  num+=10; }f1();//這個函數結束之后 { var num=10;  console.log(num);//10 }console.log(num);  if(true){  var num=10; }console.log(num); for(var i=0;i<5;i++){  var number=20; }console.log(number);   var i=0;  while (i<5){  var num=100;  i++;  } console.log(num);  function f1() {  var num=10; }f1(); console.log(num);  var num=10; console.log(num);//10  

          作用域鏈

           var num=10;  function f1() {  var num=20;  function f2() {  var num=30;  function f3() {  var num=50;  console.log(num);  } f3();  } f2();  } f1(); 

          03 函數案例

          求2個數中的最大值

           function getMax(num1, num2) {  return num1 > num2 ? num1 : num2;  } console.log(getMax(10,20));  //console.log(getMax);//函數的代碼 function getMax(num1, num2) {  return num1 > num2 ? num1 : num2;  } var num1=10;  var num2=20;  //函數外面的num1和函數的形參num1不是同一個變量 var result=getMax(num1,num2);  console.log(result);  console.log(getMax);//函數的代碼 

          求3個數中的最大值

           function getThreeMax(x, y, z) {  return x > y ? (x > z ? x : z) : (y > z ? y : z);  } console.log(getThreeMax(10,2,24)); 

          判斷一個數是否是素數(質數),只能被1和自身整除,質數是從2開始

          用這個數字和這個數字前面的所有的數字整除一次(沒有1的,沒有自身的)

           function isPrimeNumber(num) {  for (var i = 2; i < num; i++) {  if (num % i == 0) {  //說明有一個數字整除了,就沒有必要向后繼續整除了, //此時就已經驗證出不是質數 return false;  } } return true;  }//  console.log(isPrimeNumber(7) ? "yyyyyes" : "nnnnnno") var aa = isPrimeNumber(17);  if (aa) {  console.log("yes");  } else {  console.log("no");  }  function isPrimeNumber(num) {  for(var i=2;i<num;i++){  if(num%i==0){  //說明有一個數字整除了,就沒有必要向后繼續整除了,此時就已經驗證出不是質數 return false;  } } return true;  } console.log(isPrimeNumber(8)?"是質數":"不是質數");   var result=isPrimeNumber(2);  if(result){  console.log("這個數字是質數");  }else{  console.log("這個數字不是質數");  }  function aaa(x,y){  return x-y;  } console.log(aaa(99,88)) 

          通過函數實現數組反轉

           function reverseArray(arr) {  for (var i = 0; i < arr.length / 2; i++) {  var temp = arr[i];  arr[i] = arr[arr.length - 1 - i];  arr[arr.length - 1 - i] = temp;  } return arr;  } console.log(reverseArray([1, 2, 3, 4, 5])); 

          通過函數實現冒泡排序

           function sortArray(arr) {  //控制比較的輪數 for (var i = 0; i < arr.length - 1; i++) {  //控制每一輪的比較次數 for (var j = 0; j < arr.length - 1 - i; j++) {  if (arr[j] > arr[j + 1]) {  var temp = arr[j];  arr[j] = arr[j + 1];  arr[j + 1] = temp;  }//end if }//end for }//end for return arr; } console.log(sortArray([0, 19, 34, 10, 100, 2])); 

          求一個數字的階乘

          function getJieCheng(num) {  var result = 1;  for (var i = 1; i <= num; i++) {  result *= i;  } return result; }console.log(getJieCheng(5));//1*2*3*4*5 

          求斐波那契數列

           function getFib(num){  var num1=1;  var num2=1;  var num3=0;  for(var i=3;i<=nnum;i++){  sum=num1+num2;  num1=num2;  num2=sum;  } return sum;  } console.log(getFib(12))  

          02 函數作為參數使用

          函數是有數據類型,數據類型:是function類型的

          函數可以作為參數使用,如果一個函數作為參數,那么我們說這個參數(函數)可以叫回調函數 只要是看到一個函數作為參數使用了,那就是回調函數

          function sayHi(fn) {   console.log("GOOD");  fn();//fn此時應該是一個函數}function suSay() {  console.log("HELLO"); }sayHi(suSay); function f1(x,y) {  console.log(x+y); }f1(10,20); function f2(x,y) {  console.log(x+y); }f2("HLS","MISS"); function f3(x) {  console.log(x); }f3(true);

          04 arguments

          計算n個數字的和

          定義一個函數,如果不確定用戶是否傳入了參數,或者說不知道用戶傳了幾個參數,沒辦法計算,但是如果在函數中知道了參數的個數,等于也知道了每個參數的值.

          //定義function f1() {  //獲取的是函數在調用的時候,傳入了幾個參數 //console.log(arguments.length);  //使用arguments對象可以獲取傳入的每個參數的值 console.log(arguments); } f1(10,20,30,40,100,200);//調用 
           function f1({  //arguments----->數組使用------偽數組--- var sum=0;  for(var i=0;i<arguments.length;i++){  sum+=arguments[i];  } return sum;  } console.log(f1(10,20,30)); 

          05 預解析:提前解析代碼

          預解析:就是在解析代碼之前,預解析做什么事?

          把變量的聲明提前了----提前到當前所在的作用域的最上面

          函數的聲明也會被提前—提前到當前所在的作用域的最上面

          函數調用的時候, 把會函數的聲明提升到作用域的上面

          函數的聲明提升到作用域

           f1();//調用  var num=20;//這個變量的聲明會提升到變量使用之前  function f1() {  console.log(num);  //var num=10;  } function f1() {  console.log("小蘇好猥瑣");  } f1();  function f1() {  console.log("小蘇沒有助教猥瑣");  } f1(); 

          把變量的聲明提前

           var num;  console.log(num);  num=10;  function f1() {  console.log("哈哈,助教好猥瑣哦");  }   //f1();//報錯 

          注意:預解析中,變量的提升,只會在當前的作用域中提升,提前到當前的作用域的最上面

            function f1({  console.log(num);//undefined  var num = 10;  } f1();   console.log(num);//報錯  

          函數中的變量只會提前到函數的作用域中的最前面,不會出去

          預解析會分段(多對的script標簽中函數重名,預解析的時候不會沖突)

           function f1({  console.log(num);//undefined  var num=10; } f1(); console.log(num);// function f1() { console.log("哈哈"); }

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

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

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

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

          注冊登錄功能的完善

          前端達人

          在前面項目的基礎上繼續,因為我們的項目進來頁面主題就是用戶數據,所以我們想讓它一進來就是高亮狀態,那么我們可以這樣做,同時我們再加上一個菜單:

          <template> <div> <el-menu
                                  style="width: 200px; min-height: calc(100vh - 50px)" default-active="user" :default-openeds="[1]" class="el-menu-vertical-demo"> <!--這是兩個函數,我們可以先不寫@open="handleOpen"--> <!--@close="handleClose"--> <el-sub-menu index="1"> <template #title>系統管理</template> <el-menu-item index="user" :route-="{path:'/'}">用戶管理</el-menu-item> </el-sub-menu> <el-menu-item index="data" :route-="{path:'/'}">數據管理</el-menu-item> </el-menu> </div> </template> <script> export default { name: "Aside" } </script> <style scoped> </style>  
          
          • 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

          訪問效果如下:
          在這里插入圖片描述
          可以看到一進來因為頁面主體是用戶管理界面,所以“用戶管理”菜單欄是默認高亮的,然后還多了一個數據管理的菜單欄。
          菜單之間怎么跳轉一會兒再講,我們現在先寫注冊和登錄。
          在寫注冊和登錄之前,我們先講一下路由,可以看到我們這個路由文件下的文件中,默認的“/”訪問的是Home文件:
          在這里插入圖片描述
          Home頁面寫的就是我們這個用戶表的增刪改查,然后Home頁面呢是在我們的App.vue中給它嵌入進去了的,<router-view>就是展示的Home,還有Header啊Aside等
          在這里插入圖片描述
          首先我們嘗試一下可不可以直接在路由文件下寫上一個Login路由,同時我們在views頁面下創建一個Login.vue,看看能不能成功:
          在這里插入圖片描述
          注意引入路由的寫法要特別注意,不能直接像下面這樣寫:
          在這里插入圖片描述

          而應該用引入的方式;
          在這里插入圖片描述
          現在我們重啟訪問/login:
          在這里插入圖片描述
          成功;
          但是同時我們也看到了問題,我們明明是登錄界面,為什么進到了后臺主頁了,而我們想要的登錄界面應該是一個非常獨立的界面,所以我們的這個路由是有問題的。因為我們之前是直接使用App.vue作為項目的框架,其實這個App.vue在我們的main.js里面是引入進來了的:
          在這里插入圖片描述
          引進來之后呢直接作為createApp的根節點來使用,所以這個App.vue這個界面呢,不適合用來作為我們的這個后臺骨架來使用:
          在這里插入圖片描述
          它應該是一個全局的根節點,所以我們需要把App.vue里面的東西把它給挪走,挪到另一個界面,我們要把App.vue呢給它空出來,讓App.vue可以直接訪問我們所有的界面。
          怎么做呢?
          我們在src目錄下新建一個layout文件夾,這個文件夾呢就用來做我們項目的骨架部分,再在這個文件下建一個Layout組件:
          在這里插入圖片描述
          然后把之前在App.vue的東西copy過來:
          在這里插入圖片描述
          然后Header啊Aside啊那些組件我們需要在這個組件里面進行引入,然后App里面的那些原來引入的就刪掉就行了:
          在這里插入圖片描述
          然后現在我們就完成了遷移,現在我們要去配置一下我們的路由,實現我們后臺的一個訪問。
          路由怎么配置呢?非常簡單。
          我們來講解一下剛才這個什么意思,App.vue里面我們只寫了一個router-view,而這個router-view呢就作為我們這個全局的一個根節點訪問,
          在這里插入圖片描述這個router-view里面既可以是登錄界面也可以是注冊界面也可以是后臺主體,就是根據它是路由進行一個展示。當我們訪問到我們的后臺主體的時候,會進行一個二次的嵌套路由,那這個嵌套路由怎么寫呢?我們先配置登錄頁面的路由和后臺管理布局的路由:
          在這里插入圖片描述

          此時訪問/和訪問/login都能到達對應的頁面:
          在這里插入圖片描述

          在這里插入圖片描述
          但是訪問/時,Home主體頁面并沒有出來,只出來了/對應的頁面骨架的路由,怎么讓這個Home主體頁面出來呢,這就涉及到了嵌套路由,像下面這樣寫,children屬性是一個數組屬性,意味著其可以嵌套多個路由:
          在這里插入圖片描述
          訪問/下的home路由,可以看到如下頁面:
          在這里插入圖片描述

          vue-router給我們提供了重定向屬性,可以讓我們在訪問某個路由頁面時自動重定向到一個我們指定的路由頁面:
          在這里插入圖片描述
          現在我們直接訪問/試試,可以看到依然是訪問的home頁面:
          在這里插入圖片描述
          現在路由問題解決之后我們就可以去寫我們的登錄頁面了。

          <template> <!--將整個瀏覽器頁面放在一個大div里
              width: 100%表示這個讓div撐滿全屏
              height: 100vh同上,一個撐滿高度一個撐滿寬度--> <div style="width: 100%; height: 100vh;background: darkslateblue; overflow: hidden"> <!--margin: 參數1 參數2; 參數1表示上下距離,參數2表示左右距離,auto表示自動匹配
                  如果頁面產生了空白,就在外層最大的div上加一個overflow,設置為hidden即可--> <div style="width: 400px; margin: 150px auto"> <!--font-size表示字體大小,text-align表示字體居中--> <div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0"> 歡迎登錄 </div> <!--然后去element上copy一個表單--> <el-form ref="form" :model="form" size="normal"> <el-form-item> <el-input prefix-icon="el-icon-user-solid" v-model="form.username"></el-input> </el-form-item> </el-form> <el-form ref="form" :model="form" size="normal"> <el-form-item> <el-input prefix-icon="el-icon-lock" v-model="form.password" show-password></el-input> </el-form-item> </el-form> <el-form ref="form" :model="form" size="normal"> <el-button style="width: 100%" type="primary" @click="login">登錄</el-button> </el-form> </div> </div> </template> <script> import request from "../utils/request"; export default { name: "Login", data(){ return{ form:{} } }, methods: { login() { request.post("/api/user/login",this.form).then(res => { if(res.code === "0"){ this.$messageBox({ type: "success", message: "登錄成功" }) //    登錄成功之后進行頁面跳轉,跳轉到主頁 this.$router.push("/") }else{ this.$messageBox({ type: "error", message: res.msg }) } }) } } } </script> <style scoped> </style>  
          
          • 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

          然后現在去寫我們后端的接口:

           //用戶登錄 @PostMapping("/login") public Result login(@RequestBody User user){ User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername()).eq(User::getPassword,user.getPassword())); if(res != null){ //登錄成功 return Result.success(); }else{ //登錄失敗 return Result.error("-1","用戶名或密碼錯誤"); } }  
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10

          現在數據庫中的數據有:
          在這里插入圖片描述
          我們試著訪問登錄:
          在這里插入圖片描述
          可以看到登錄成功:
          在這里插入圖片描述
          然后我們再去我們的網頁頭部右側的用戶信息欄寫一下退出系統的操作:
          在這里插入圖片描述
          點擊則路由跳轉到登錄頁面。
          然后還有注冊頁面,也一起寫了,注冊頁面其實邏輯和登錄界面差不多,我們copy一個登錄組件進行更改即可。
          在這里插入圖片描述
          然后進行更改就行了,注冊不過就比登錄多了一個確認密碼的操作。

          <template> <!--將整個瀏覽器頁面放在一個大div里
              width: 100%表示這個讓div撐滿全屏
              height: 100vh同上,一個撐滿高度一個撐滿寬度--> <div style="width: 100%; height: 100vh;background: darkslateblue; overflow: hidden"> <!--margin: 參數1 參數2; 參數1表示上下距離,參數2表示左右距離,auto表示自動匹配
                  如果頁面產生了空白,就在外層最大的div上加一個overflow,設置為hidden即可--> <div style="width: 400px; margin: 150px auto"> <!--font-size表示字體大小,text-align表示字體居中--> <div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0"> 歡迎登錄 </div> <!--然后去element上copy一個表單--> <el-form ref="form" :model="form" size="normal" :rules="rules"> <el-form-item prop="username"> <el-input prefix-icon="el-icon-user-solid" v-model="form.username"></el-input> </el-form-item> <el-form-item prop="password"> <el-input prefix-icon="el-icon-lock" v-model="form.password" show-password></el-input> </el-form-item> </el-form> <el-form ref="form" :model="form" size="normal"> <el-button style="width: 100%" type="primary" @click="login">登錄</el-button> </el-form> </div> </div> </template> <script> import request from "../utils/request"; export default { name: "Login", data(){ return{ form:{}, rules:{ username:[ {required: true,message:"請輸入用戶名",trigger:'blur'}, ], password:[ {required: true,message:"請輸入密碼",trigger:'blur'}, ] } } }, methods: { login() { //發送請求之前先加這個判斷,不為空且滿足規則時才發送請求 this.$refs['form'].validate((valid) => { if (valid) { request.post("/api/user/login",this.form).then(res => { if(res.code === "0"){ this.$messageBox({ type: "success", message: "登錄成功" }) //    登錄成功之后進行頁面跳轉,跳轉到主頁 this.$router.push("/") }else{ this.$messageBox({ type: "error", message: res.msg }) } }) } }) } } } </script> <style scoped> </style>  
          
          • 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

          其中我們還要注意在請求數據之前要先判斷表單內部是否數據符合要求,否則不予請求,同樣在Login頁面內也要加入該判斷:

          <template> <!--將整個瀏覽器頁面放在一個大div里
              width: 100%表示這個讓div撐滿全屏
              height: 100vh同上,一個撐滿高度一個撐滿寬度--> <div style="width: 100%; height: 100vh;background: darkslateblue; overflow: hidden"> <!--margin: 參數1 參數2; 參數1表示上下距離,參數2表示左右距離,auto表示自動匹配
                  如果頁面產生了空白,就在外層最大的div上加一個overflow,設置為hidden即可--> <div style="width: 400px; margin: 150px auto"> <!--font-size表示字體大小,text-align表示字體居中--> <div style="color: #cccccc; font-size: 30px; text-align: center; padding: 30px 0"> 歡迎登錄 </div> <!--然后去element上copy一個表單--> <el-form ref="form" :model="form" size="normal" :rules="rules"> <el-form-item prop="username"> <el-input prefix-icon="el-icon-user-solid" v-model="form.username"></el-input> </el-form-item> <el-form-item prop="password"> <el-input prefix-icon="el-icon-lock" v-model="form.password" show-password></el-input> </el-form-item> </el-form> <el-form ref="form" :model="form" size="normal"> <el-button style="width: 100%" type="primary" @click="login">登錄</el-button> </el-form> </div> </div> </template> <script> import request from "../utils/request"; export default { name: "Login", data(){ return{ form:{}, rules:{ username:[ {required: true,message:"請輸入用戶名",trigger:'blur'}, ], password:[ {required: true,message:"請輸入密碼",trigger:'blur'}, ] } } }, methods: { login() { //發送請求之前先加這個判斷,不為空且滿足規則時才發送請求 this.$refs['form'].validate((valid) => { if (valid) { request.post("/api/user/login",this.form).then(res => { if(res.code === "0"){ this.$messageBox({ type: "success", message: "登錄成功" }) //    登錄成功之后進行頁面跳轉,跳轉到主頁 this.$router.push("/") }else{ this.$messageBox({ type: "error", message: res.msg }) } }) } }) } } } </script> <style scoped> </style>  
          
          • 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

          然后現在去后端寫register的接口:

          //用戶注冊 @PostMapping("/register") public Result register(@RequestBody User user){ User res = userMapper.selectOne(Wrappers.<User>lambdaQuery().eq(User::getUsername,user.getUsername())); if(res != null){ //說明用戶名重復 return Result.success(); } //該用戶不存在,予以注冊 if(user.getPassword() == null){ user.setPassword("123456"); } userMapper.insert(user); return Result.success(); }  
          
          • 1
          • 2
          • 3
          • 4
          • 5
          • 6
          • 7
          • 8
          • 9
          • 10
          • 11
          • 12
          • 13
          • 14

          就此我們的注冊頁面也寫完啦。

          1





























































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

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

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

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

          掌握用Vue腳手架搭建一個完整項目!

          前端達人

          1.在搭建項目之前,先安裝淘寶鏡像和命令行工具,可能需要等待一段時間(電腦安裝過一遍之后,以后建項目時就不需要再安裝):

                  a.Win+R打開命令提示行cmd;

                  b.進入命令行cmd,設置淘寶鏡像;

          npm config set registry https://registry.npm.taobao.org

                  c.安裝可生成腳手架代碼的命令行工具;

          npm i -g @vue/cli

                  當命令行窗口顯示 [ + @vue/cli@版本號 ] 時說明安裝成功。

          2.開始創建項目

                  a.先決定要把項目文件夾保存在哪個位置;此處以test文件夾為例;

                  b.進入test文件夾后,shift+鼠標右鍵打開power shell窗口;

          c.運行 vue create 自定義項目名;此處以項目名為test為例,出現提示后按以下過程進行選擇:

                  1)? Please pick a preset:

                  2)? Check the features needed for your project:

                  3)? Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n)  N

                  4)? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default): (Use arrow keys)

                  5)? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)

                  6)? Save this as a preset for future projects? (y/N)  N

                  最后命令行窗口顯示Successfully created project xzvue說明項目創建成功。

                  此時我們便可在test文件夾中看到整個項目。

          3.使用vscode打開并運行腳手架項目

          (1)右鍵單擊package.json文件,選擇"在集成終端中打開";

          (2)在終端窗口中輸入:npm run serve,等待后出現App running at : - Local :http://localhost:8080/,如下:

          (3)按住Ctrl,點local:右側的連接,即可自動打開瀏覽器。 

                  需要的時候就可以在集成終端中輸入npm i、npm i vant -S 等命令下載node_modules包、安裝vant等等。

                  注意vue采用的是熱編譯,修改后無需停止或重啟項目,只要一修改,就會立刻自動重新編譯,重新運行,自動在界面上顯示新內容。



          藍藍設計建立了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界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 平面設計服務

          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、PUT、DELETE 等請求

          什么是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界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、 網站建設 、平面設計服務

          vue 數據雙向綁定原理

          前端達人





          首先我們為每個vue屬性用Object.defineProperty()實現數據劫持,為每個屬性分配一個訂閱者集合的管理數組dep;然后在編譯的時候在該屬性的數組dep中添加訂閱者,v-model會添加一個訂閱者,{{}}也會,v-bind也會,只要用到該屬性的指令理論上都會,接著為input會添加監聽事件,修改值就會為該屬性賦值,觸發該屬性的set方法,在set方法內通知訂閱者數組dep,訂閱者數組循環調用各訂閱者的update方法更新視圖。



          一小段手寫實現代碼

          僅供參考

          class Vue {
          constructor(option){
          this.$data = option.data
          Observe(this.$data)
          Object.keys(this.$data).forEach((key)=>{
          Object.defineProperty(this,key,{
          enumerble: true,
          configurable: true,
          get(){
          return this.$data[key]
          },
          set(newVal){
          this.$data[key] = newVal
          },
          })
          })
          }
          }

          function Observe (obj){
          if(!obj || typeof obj !== 'object') return
          Object.keys(obj).forEach((key)=>{
          let value = obj[key]
          Observe(value)
          Object.defineProperty(obj,key,{
          enumerble: true,
          configurable: true,
          get(){
          console.log('有人獲取了 ${key} 的值')
          return value
          },
          set(newVal){
          value = newVal
          Observe(value)
          },
          })
          })
          }

          1

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

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

          使用 Nodemailer 發送郵件 郵件提醒通知功能實現

          前端達人

          Nodemailer 是一個基于Node的郵件服務模塊。

          使用 Nodemailer 完成一個發郵件功能非常簡單,只需3步:

          1. 引入模塊
          2. 創建 transport
          3. 發送郵件

          引入模塊

          首先安裝 Nodemailer

          npm install nodemailer 

          引入

          var mailer = require('nodemailer'); 

          創建transport

          創建 transport 使用 Nodemailer 的createTransport方法,需要配置一下郵件服務。

          首先,要在郵箱設置里開啟 SMTP 服務。

          然后,設置一個客戶端授權密碼。

          最后,寫一個配置文件(conf/mail.js)。以126郵箱為例:

          module.exports = { host: 'smtp.126.com', auth: { user: 'user@126.com', pass: '******' } } 

          host字段配置剛才開啟的服務地址。
          auth里的user字段配置郵箱賬號,pass字段配置剛才設置的授權密碼。

          這樣創建一個 transport:

          var mailConf = require('conf/mail'); var transport = mailer.createTransport(mailConf); 

          發送郵件

          發郵件使用 Nodemailer 的sendMail方法,需要配置一下郵件內容。

          這里配置了發件人,收件人,標題和正文:

          var mailOptions = { from: mailConf.auth.user, to: 'receiver@xxx.com', subject: 'Hi, there', text: 'Mail from Node!' } 

          可以像官方文檔一樣定義一個回調函數:

          function mailCallback(error, info){ if(error){ return console.log(error); } console.log('Message sent: ' + info.response); } 

          然后,就可以發送郵件了:

          transport.sendMail(mailOptions, mailCallback); 

          總結

          這樣就完成了最基本的發郵件功能。

          Nodemailer 文檔非常詳細,可以探索實現更多功能。


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

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

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

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


          日歷

          鏈接

          個人資料

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

          存檔

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