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

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

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

          首頁

          前端性能優化

          seo達人

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

          減少頁面加載時間的方法:
          1.壓縮html css js等文件
          2.減少DNS解析
          3.減少DOM元素,對于相關操作可以緩存節點
          4.改變頁面元素樣式時盡量操作className,而不是頻繁使用xxx.style.(其實還有很多這種DOM修改操作的細節比如opacity替代visibility ,多個DOM統一操作(雖然V8會有緩存優化) ,先將DOM離線,即display:none;修改后顯示 ,不要把DOM放在已給循環中作為循環變量 ,不要使用table )
          5.避免不必要的重定向
          6.合并js css及圖片,減少請求數量
          7.使用CDN
          8.合理利用緩存
          9…

          關于CDN?
          https://zhuanlan.zhihu.com/p/39028766

          CDN中文名“內容分發網路”,作用是減少傳播時延,找最近的節點。CDN本質就一個是緩存,只是這個緩存離你特別近,不管是作為用戶還是開發人員都能從中享受一點福利。
          CDN的優點
          1.訪問加速
          2.減輕服務器負載
          3.抗住攻擊
          CDN的缺點
          1.只能對靜態資源加速
          2.內容更新時需要分發到其他節點
          3.代價高昂
          與傳統網站訪問方式的不同
          傳統的網站會直接解析域名獲得IP地址然后發送請求
          使用了CDN的網站則增加了緩存層,解析域名→獲取對應CNAME域名→對獲取的域名進行解析得到緩存服務器的IP地址,將用戶的訪問請求引導到最優的緩存節點而不是源站。

          總結:通過權威DNS服務器來實現最優節點的選擇,通過緩存來減少源站的壓力。主要應用于靜態網頁、大文件的下載等等。
          應用與踩坑

          緩存設置
          max-age在Cache-Control中經常用于緩存的控制,可是max-age設置的緩存會應用于一個請求經過的每一級,如果我們希望CDN不緩存那么久,要怎么辦呢?那就是s-maxage,它用于設置代理服務器的緩存時間,會覆蓋max-age的設置,這樣我們可以把max-age用于本地緩存,把s-maxage用于CDN緩存時間,避免臟數據的產生。

          緩存命中率
          對于一個緩存而言,還有一點非常重要,就是你的緩存到底有沒有用,衡量這個東西的就是緩存命中率。如果只是靜態資源,在刷新緩存之后,可能導致命中率下降,因此CDN的資源不適合經常刷新,換句話說,如果一個請求結果會經常進行變更,那么CDN基本就沒有什么存在的意義了。

          判斷是否命中緩存
          還要考慮的一件事是:這個資源是否命中了CDN,是否是因為CDN導致的問題。

          在各大廠商的CDN返回的數據中都會有一個X-Cache,上面內容是Hit或者Miss,還會加上諸如Memory或者Disk的縮寫表示內存還是磁盤,如果出現Upstream或者Miss則表示沒有命中。

          資源預熱
          緩存設計中,預熱是很重要的環節,在最初剛開始啟動CDN的時候,CDN上并沒有緩存數據,此刻大量的請求全部打向源站,肯定會把源站打掛,預熱就是實現緩存熱門數據,這樣在業務上線時,CDN上已經有所需的數據了

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

          vue父子組件互相傳值

          seo達人

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

          一、父組件給子組件傳值

          1、父組件調用子組件的時候,綁定動態屬性

          /*傳值可以是值“title”、是方法“run”、是組件“this”*/
          <v-header :title="title" :run="run" :home="this"></v-header>
          1
          2
          2、在子組件里面通過props接受父組件傳過來的數據

          <script>
              export default{
          props:['title','run','home']
          }
          </script>

          二、父組件主動獲取子組件的數據和方法

          1、調用子組件的時候定義一個ref

          <v-header ref="header"></v-header>
          1
          2、在父組件里面通過以下方式獲取屬性和方法

          this.$refs.header.屬性
          this.$refs.header.方法

          三、子組件主動獲取父組件的數據和方法

          this.$parent.數據
          this.$parent.方法

          四、非父子組建傳值

          1、新建一個js文件 然后引入vue 實例化vue最后暴露這個實例

          VueEvent.js

          import Vue from 'vue';
          var VueEvent = new Vue();
          export default VueEvent;

          2、在要廣播的地方引入剛才定義的實例,并進行廣播

          home.vue

          <script>
          import VueEvent from './VueEvent.js';
              export default{
                  methods:{
                      emitNews(){
                          /*廣播數據*/
                          VueEvent.$emit('to-news',this.數據)
                      }
                  }
          }
          </script>

          3、在要接收數據的地方接受廣播

          news.vue

          <script>
          import VueEvent from './VueEvent.js';
              export default{
                  /*在生命周期函數里寫,編譯的時候就調用*/
                  mounted(){
                      /*接受廣播*/
                      VueEvent.$on('to-news',function(data){
                          console.log(data);
                      })
                  }
          }
          </script>


          Bitmap三級緩存 和二次采樣

          seo達人

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

          一.為什么Bitmap三級緩存?
          沒有緩存的弊端 :費流量, 加載速度慢
          加入緩存的優點: 省流量,支持離線瀏覽
          二.原理

          從內存獲取圖片, 如果存在, 則顯示; 如果不存在, 則從SD卡中獲取圖片
          從SD卡中獲取圖片, 如果文件中存在, 顯示, 并且添加到內存中; 否則開啟網絡下載圖片
          從網絡下載圖片, 如果下載成功, 則添加到緩存中, 存入SD卡, 顯示圖片
          三.代碼
          (1)添加讀寫SD卡的權限和網絡權限



          // //Lrucache存儲工具類
          public class LruUtils {
          private LruCache<String,Bitmap> lruCache;
          private long max=Runtime.getRuntime().maxMemory();
          public LruUtils(){
          lruCache=new LruCache<String,Bitmap>((int)max/8){

                  @Override
                  protected int sizeOf(String key, Bitmap value) {
                      return value.getByteCount();
                  }
              };
          }
          public Bitmap getBitmap(String key){
              return lruCache.get(key);
          }
          public void setBitmap(String key,Bitmap bitmap){
              lruCache.put(key,bitmap);
          }
          1
          2
          3
          4
          5
          6
          7
          8
          9
          10
          11
          12
          }
          //SD卡工具類
          public class SDUtils {

          public static void setBitmap(String name, Bitmap bitmap) {

              if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                  File file = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                  File file1 = new File(file, name);

                  try {

                      bitmap.compress(Bitmap.CompressFormat.JPEG, 100, new FileOutputStream(file1));
                  } catch (FileNotFoundException e) {
                      e.printStackTrace();
                  }
              }
          }
          public static Bitmap getBitmap(String name){

              if(Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)){
                  File file=Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
                  File file1=new File(file,name);

                  return BitmapFactory.decodeFile(file1.getAbsolutePath());

              }
              return null;
          }

          }
          //網絡

          import android.app.AlertDialog;
          import android.graphics.Bitmap;
          import android.graphics.BitmapFactory;
          import android.os.AsyncTask;

          import java.io.InputStream;
          import java.net.HttpURLConnection;
          import java.net.URL;
          import java.util.concurrent.ExecutionException;

          public class NewUtils {
          public static Bitmap getBitmap(String url) throws ExecutionException, InterruptedException {
          return new MyTask().execute(url).get();
          }
          static class MyTask extends AsyncTask<String,Void,Bitmap>{
          @Override
          protected Bitmap doInBackground(String… strings) {
          String imageUrl = strings[0];
          HttpURLConnection conn = null;
          try {
          URL url = new URL(imageUrl);
          conn = (HttpURLConnection) url.openConnection();
          conn.setReadTimeout(5000);
          conn.setConnectTimeout(5000);
          conn.setRequestMethod(“GET”);
          if (conn.getResponseCode() == 200) {
          InputStream is = conn.getInputStream();
          Bitmap bitmap = BitmapFactory.decodeStream(is);
          return bitmap;
          }
          } catch (Exception e) {
          e.printStackTrace();
          } finally {
          if (conn != null) {
          conn.disconnect();
          }
          }
          return null;
          }
          }

          }
          //使用三個工具類完成Bitmap的三級緩存
          package com.example.administrator.myapplication;

          import android.graphics.Bitmap;
          import android.support.v7.app.AppCompatActivity;
          import android.os.Bundle;
          import android.view.View;
          import android.widget.Button;
          import android.widget.ImageView;
          import android.widget.Toast;

          import java.util.concurrent.ExecutionException;

          public class MainActivity extends AppCompatActivity {
          private ImageView imageView;
          Button button;
          private LruUtils lruUtils= new LruUtils();
          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main);
          button=findViewById(R.id.button);
          imageView=findViewById(R.id.imageview);
          button.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
          Bitmap bitmap=lruUtils.getBitmap(“czn”);
          if (bitmap!=null){
          imageView.setImageBitmap(bitmap);
          Toast.makeText(MainActivity.this, “圖片存內存”, Toast.LENGTH_SHORT).show();
          }else{
          bitmap=SDUtils.getBitmap(“czn.jpg”);
          if (bitmap!=null){
          imageView.setImageBitmap(bitmap);
          Toast.makeText(MainActivity.this, “圖片存SD卡”, Toast.LENGTH_SHORT).show();
          lruUtils.setBitmap(“czn”,bitmap);
          }else{
          try {
          bitmap=NewUtils.getBitmap(“http://pic1.win4000.com/wallpaper/e/50d80458e1373.jpg”);
          if (bitmap!=null){
          imageView.setImageBitmap(bitmap);
          Toast.makeText(MainActivity.this, “圖片存網絡”, Toast.LENGTH_SHORT).show();
          SDUtils.setBitmap(“czn.jpg”,bitmap);
          lruUtils.setBitmap(“czn”,bitmap);
          }else{
          Toast.makeText(MainActivity.this, “沒有找到”, Toast.LENGTH_SHORT).show();
          }

                              } catch (ExecutionException e) {
                                  e.printStackTrace();
                              } catch (InterruptedException e) {
                                  e.printStackTrace();
                              }

                          }
                      }
                  }
              });
          }

          }
          Bitmap二次采樣


          import android.graphics.Bitmap;
          import android.graphics.BitmapFactory;
          import android.os.AsyncTask;
          import android.support.v7.app.AppCompatActivity;
          import android.os.Bundle;
          import android.view.View;
          import android.widget.Button;
          import android.widget.ImageView;

          import java.io.ByteArrayOutputStream;
          import java.io.IOException;
          import java.io.InputStream;
          import java.net.HttpURLConnection;
          import java.net.MalformedURLException;
          import java.net.URL;
          import java.util.concurrent.ExecutionException;

          public class Main2Activity extends AppCompatActivity {
          Button bt;
          ImageView imageView;
          @Override
          protected void onCreate(Bundle savedInstanceState) {
          super.onCreate(savedInstanceState);
          setContentView(R.layout.activity_main2);
          bt=findViewById(R.id.bt);
          imageView=findViewById(R.id.mimage);
          bt.setOnClickListener(new View.OnClickListener() {
          @Override
          public void onClick(View v) {
          try {
          Bitmap bitmap = new MyTask().execute(“https://cdn.duitang.com/uploads/item/201211/24/20121124230042_Bfhim.jpeg”).get();
          imageView.setImageBitmap(bitmap);
          } catch (InterruptedException e) {
          e.printStackTrace();
          } catch (ExecutionException e) {
          e.printStackTrace();
          }

                  }

              });
          }
          class MyTask extends AsyncTask<String,Object,Bitmap>{

              @Override
              protected Bitmap doInBackground(String... strings) {
                  try {
                      URL url = new URL(strings[0]);
                      HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
                      if(urlConnection.getResponseCode()==200){
                          InputStream inputStream = urlConnection.getInputStream();
                          //將inputStream流存儲起來
                          ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
                          byte[] bytes = new byte[1024];
                          int len=0;
                          while((len=inputStream.read(bytes))!=-1){
                              byteArrayOutputStream.write(bytes,0,len);
                          }
                          //桶:網絡的圖片都放在數組里面了
                          byte[] data = byteArrayOutputStream.toByteArray();
                          //TODO 1:第一次采樣:只采邊框 計算壓縮比例
                          BitmapFactory.Options options = new BitmapFactory.Options();
                          options.inJustDecodeBounds=true;//設置只采邊框
                          BitmapFactory.decodeByteArray(data,0,data.length,options);//采樣
                          int outWidth = options.outWidth;//獲得原圖的寬
                          int outHeight = options.outHeight;//獲得原圖的高
                          //計算縮放比例
                          int size=1;
                          while(outWidth/size>100||outHeight/size>100){
                              size*=2;
                          }
                          //TODO 2:第二次采樣:按照比例才像素
                          options.inJustDecodeBounds=false;//設置只采邊框為fasle
                          options.inSampleSize=size;//設置縮放比例
                          Bitmap bitmap= BitmapFactory.decodeByteArray(data,0,data.length,options);//采樣
                          return  bitmap;
                      }

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

          Fragment的創建及使用

          seo達人

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

          Fragment,在Android中指的是碎片,也就是在不切換Activity時進行頁面的切換,這是Android中的一個重點的內容,很多的應用程序中都有這樣的功能,所以,接下來讓我們具體的學習一下Fragment的使用
          首先,要將一個Fragment給創建出來。
          新建一個類,讓這個類繼承Fragment,并重寫onCreatView()方法,之后,使用onCreatView中的inflater將一個布局文件轉換為視圖,并返回這個視圖


          之后在MainActivity中獲得一個Fragment的管理者

          之后我們通過這個管理者的beginTransaction()的方法獲取事務管理者

          然后,我們將之前寫好的Fragment類給進行實例化

          之后,我們使用事務管理者的replace()方法來給我們需要的控件上將我們的Fragment給顯示出來

          之后,使用事務管理者提交事務,這樣我們的Fragment就完美的顯示出來了

          碎片可以在不影響Activity時進行一個頁面的切換,所以,我們需要把我們需要顯示的所有的Fragment都放到FrameLayout布局上
          這樣就可以實現Fragment的切換了
          同時,在進行Fragment可以給Fragment添加一個回退棧的功能,使得每次按返回鍵是返回的上一個Fragment,而不是直接退出整個程序了


          下面我們講一下Fragment的生命周期
          Fragment的生命周期分為11個部分,分別為:
          onAttach()
          onCreatView()
          onCreat()
          onActivityCreated()
          onStart()
          onResume()
          onPause()
          onStop()
          onDestoryView()
          onDestory()
          onDetach()
          Fragment的生命周期和Activity的生命周期一樣重要,都是面試時的重點,一定要背下來

          其次還要學習關于Fragment的傳值
          Fragment的傳值分為兩種方法,分別是Handler傳值和接口回調方法,接下來就來學習一下兩種不同的傳值方式
          首先是Handler的傳值 ,
          第一步是在我們需要拿到值的Fragment中建立一個靜態的Handler,之后重寫handleMessage()方法

          第二步,在傳值的Fragment的調用Handler進行傳值

          這樣就可以實現了Fragment的Handler之間的傳值

          然后我們接著說關于接口回調的傳值
          首先定義一個外部接口

          之后呢,在傳值的Fragment里傳遞數據

          然后,我們在接收的Fragment里實現接口并重寫方法即可傳遞數據

          這就是接口回調傳遞數據的方法
          好了,關于Fragment的使用簡單說到這里
          --------------------- 
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、網站建設 、平面設計服務。

          for循環包裹setTimeout計時器

          seo達人

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

          for(var i = 0; i < 5; i++) {
          console.log(i)
          }

          這樣for循環可打印出 0 - 4的結果

          for(var i = 0; i < 5; i++) {
              setTimeout(function() {
          console.log(i)
              }, i * 1000)
          }

          但這樣只能間隔一秒打印出5個5

          原因在于 setTimeout是異步,等for循環全部完成 i 后才會執行

          解決方法可以將 for循環中的var 變成 let

          let只作用于for循環內,這樣每次付給setTimeout的值都是當前值

          或者在setTimeout外再包一層function

          for(var i = 0; i < 5; i++) {
              (function(i) {setTimeout(function() {
          console.log(i)
              }, i * 1000)})(i)

          }

          將 i 作為參數傳到setTimeout中運行 這樣就可以得到每隔1秒加1的log結果了
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、網站建設 、平面設計服務。

          WEB前端之HTML 規范

          seo達人

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


          摘要
          優秀的項目源碼,即使是多人開發,看代碼也如出一人之手。統一的編碼規范,可使代碼更易于閱讀,易于理解,易于維護

          HTML 規范
          縮進
          統一兩個空格縮進

          命名規范
          class 應以功能或內容命名,不以表現形式命名;
          class 與 id 單詞字母小寫,多個單詞組成時,采用中劃線-分隔;
          使用唯一的 id 作為 Javascript hook, 同時避免創建無樣式信息的 class;
          DOCTYPE 聲明
          HTML 文件必須加上 DOCTYPE 聲明,并統一使用 HTML5 的文檔聲明:

          <!DOCTYPE html>


          meta 標簽
          統一使用 “UTF-8” 編碼
          <meta charset="utf-8">


          SEO 優化
          <!-- 頁面關鍵詞 -->
          <meta name ="keywords" content =""/>
          <!-- 頁面描述 -->
          <meta name ="description" content ="">
          <!-- 網頁作者 -->
          <meta name ="author" content ="">


          優先使用 IE 版本和 Chrome
          <meta http-equiv ="X-UA-Compatible" content ="IE = edge,chrome = 1">


          為移動設備添加視口
          <!-- device-width 是指這個設備最理想的 viewport 寬度 -->
          <!-- initial-scale=1.0 是指初始化的時候縮放大小是1,也就是不縮放 -->
          <!-- user-scalable=0 是指禁止用戶進行縮放 -->
          <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">


          禁止自動識別頁面中有可能是電話格式的數字
          <meta name="format-detection" content="telephone=no">


          團隊約定:

          pc 端:

          <meta charset="utf-8">
          <meta name="keywords" content="your keywords">
          <meta name="description" content="your description">
          <meta name="author" content="author,email address">
          <meta http-equiv="X-UA-Compatible" content="IE=Edge,chrome=1">
          web前端開發資源Q-q-u-n: 767273102 ,內有免費開發工具,零基礎,進階視頻教程,希望新手少走彎路 

          移動端:

          <meta charset="utf-8">
          <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
          <meta name="format-detection" content="telephone=no">


          標簽
          html 標簽分為以下幾類:

          自閉合標簽(self-closing),無需閉合。例如:area、base、br、col、command、embed、hr、img、input、keygen、link、meta、param、source、track、wbr 等 )
          閉合標簽(closing tag),需閉合 。例如:textarea、title、h、div、span 等
          團隊約定:

          所有具有開始標簽和結束標簽的元素都必須要寫上起止標簽,某些允許省略開始標簽或和束標簽的元素亦都要寫上
          自閉合標簽不要加上結束標簽
          自定義標簽的名字必須包含一個破折號(-),<x-tags>、<my-element>和<my-awesome-app>都是正確的名字,而<tabs>和<foo_bar>是不正確的。這樣的限制使得 HTML 解析器可以分辨那些是標準元素,哪些是自定義元素
          自定義標簽必須寫上開始標簽和閉合標簽
          盡量減少標簽數量
          元素屬性
          元素屬性值使用雙引號語法
          推薦:

          <input type="text">


          不推薦:

          <input type=text>
          <input type='text'>


          代碼嵌套
          塊元素可以包含內聯元素或某些塊元素,但內聯元素卻不能包含塊元素,它只能包含其它的內聯元素
          標題和段落中不能包含塊,如:h1、h2、h3、h4、h5、h6、p、dt
          塊與內聯不能并列,塊級元素與塊級元素并列、內嵌元素與內嵌元素并列
          有些標簽是固定的嵌套規則,比如 ul 包含 li、ol 包含 li、dl 包含 dt 和 dd 等等。
          靈活使用偽類
          不要讓非內容信息污染了你的 HTML,打亂了 HTML 結構。可以使用:before、:after 等偽類元素

          推薦:

          HTML 代碼

          <!-- That is clean markup! -->
          <span class="text-box">
            See the square next to me?
          </span>


          CSS 代碼:

          /* We use a :before pseudo element to solve the design problem of placing a colored square in front of the text content */
          .text-box:before {
            content: '';
            display: inline-block;
            width: 1rem;
            height: 1rem;
            background-color: red;
          }

          1

          不推薦:

          HTML 代碼:

          <!-- We should not introduce an additional element just to solve a design problem  -->
          <span class="text-box">
            <span class="square"></span>
            See the square next to me?
          </span>


          CSS 代碼:

          .text-box > .square {
            display: inline-block;
            width: 1rem;
            height: 1rem;
            background-color: red;
          }
          web前端開發資源Q-q-u-n: 767273102 ,內有免費開發工具,零基礎,進階視頻教程,希望新手少走彎路 

          特殊符號必須使用轉義符
          符號 描述 轉義符
          空格 &nbsp;
          < 小于 &lt;
          > 大于 &gt;
          & &amp;
          " 引號 &quot;
          純數字輸入框
          使用 type=“tel” 而不是 type=“number”

          <input type="tel">


          類型屬性
          不需要為 CSS、JS 指定類型屬性,HTML5 中默認已包含。

          推薦:

          <link rel="stylesheet" href="" >
          <script src=""></script>


          不推薦:

          <link rel="stylesheet" type="text/css" href="" >
          <script type="text/javascript" src="" ></script>


          注釋規范
          單行注釋

          一般用于簡單的描述,如某些狀態描述、屬性描述等
          注釋內容前后各一個空格字符,注釋位于要注釋代碼的上面,單獨占一行
          推薦:

          <!-- Comment Text -->
          <div>...</div>


          不推薦:

          <div>...</div><!-- Comment Text -->

          <div><!-- Comment Text -->
              ...
          </div>


          6
          模塊注釋

          注釋內容前后各一個空格字符
          <!-- S Comment Text -->表示模塊開始
          <!-- E Comment Text -->表示模塊結束,模塊與模塊之間相隔一行
          模塊注釋內部嵌套模塊注釋,<!-- /Comment Text -->
          推薦:

          <!-- S Comment Text A -->
          <div class="mod_a">

              <div class="mod_b">
                  ...
              </div>
              <!-- /mod_b -->

              <div class="mod_c">
              ...
              </div>
              <!-- /mod_c -->

          </div>
          <!-- E Comment Text A -->

          <!-- S Comment Text D -->
          <div class="mod_d">
              ...
          </div>
          <!-- E Comment Text D -->
          web前端開發資源Q-q-u-n: 767273102 ,內有免費開發工具,零基礎,進階視頻教程,希望新手少走彎路 

          22
          語義化
          沒有 CSS 的 HTML 是一個語義系統而不是 UI 系統
          通常情況下,每個標簽都是有語義的
          語義化的 HTML 結構,有助于機器(搜索引擎)理解,另一方面多人協作時,能迅速了解開發者意圖
          建議頁面中多使用語義化標簽,而不是整個頁面以 div 構成
          常見標簽語義:
          標簽 語義
          <p> 段落
          <hn> 標題(h1~h6)
          <ul> 無序列表
          <ol> 有序列表
          <nav> 標記導航,僅對文檔中重要的鏈接群使用
          <main> 頁面主要內容,一個頁面只能使用一次。如果是 web 應用,則包圍其主要功能
          <article> 定義外部的內容,其中的內容獨立于文檔的其余部分
          <section> 定義文檔中的節(section、區段)。比如章節、頁眉、頁腳或文檔中的其他部分。
          <aside> 定義其所處內容之外的內容。如側欄、文章的一組鏈接、廣告、友情鏈接、相關產品列表
          <header> 頁眉通常包括網站標志、主導航、全站鏈接以及搜索框
          <footer> 頁腳,只有當父級是 body 時,才是整個頁面的頁腳
          <figure> 規定獨立的流內容(圖像、圖表、照片、代碼等等)(默認有 40px 左右 margin)
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、網站建設 、平面設計服務。

          selenium處理網頁下拉加載數據爬取并存入excel

          seo達人

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

          前言
          之前有個同學詢問我是否能夠爬取知乎的全部回答,當初只會Scrapy無法實現下拉的數據全部加載。后來在意外中接觸了selenium的自動化測試,看出了selenium的模擬能力的強大,而昨天有個同學問我能否爬取中國工商銀行遠程銀行的精彩回答,我說可以試試。

          思路
          selenium模擬下拉直至底部
          然后通過selenium獲取數據集合
          通過pandas寫入excel
          selenium模擬下拉直至底部
          此處全靠一位大佬的博客點撥,實在不好意思的是,selenium就看了下常用的api,實在不懂如何判斷是否加載完畢,而該博客代碼的原理也好理解,通過不斷下拉判斷與上一次高度進行對比,知道前端頁面的滾動高度屬性就懂了,當然思想最重要。
          見代碼:

          #將滾動條移動到頁面的底部
          all_window_height =  []  # 創建一個列表,用于記錄每一次拖動滾動條后頁面的最大高度
          all_window_height.append(self.driver.execute_script("return document.body.scrollHeight;")) #當前頁面的最大高度加入列表
          while True:
          self.driver.execute_script("scroll(0,100000)") # 執行拖動滾動條操作
          time.sleep(3)
          check_height = self.driver.execute_script("return document.body.scrollHeight;")
          if check_height == all_window_height[-1]:  #判斷拖動滾動條后的最大高度與上一次的最大高度的大小,相等表明到了最底部
          print("我已下拉完畢")
          break
          else:
          all_window_height.append(check_height) #如果不想等,將當前頁面最大高度加入列表。
          print("我正在下拉")

          然后通過selenium獲取數據集合
          通過find_elements_by_css_selector方法獲取元素對象列表,然后通過遍歷列表獲取單個對象,通過對象的text屬性獲取數據。
          代碼與"通過pandas寫入excel"代碼想結合。

          通過pandas寫入excel
          example.xlsx

          批量將數據依次寫入excel,此處個人知道有兩種寫法,推薦后者。
          寫法一:

          problem = cls.driver.find_elements_by_css_selector("li h2.item-title a")
          data = pd.read_excel('example.xlsx', sheet_name = 'Sheet1')
          problemtext = []
          for i in problem:
          problemtext .append(i.text)
          replytext = []
          reply = cls.driver.find_elements_by_css_selector("div.item-right p")
          for j in reply:
              replytext.append(j.text)
              data.loc[row,'答案'] = j.text
          data['問題'] = problemtext
          data['答案'] = replytext

          DataFrame(data).to_excel('test.xlsx', sheet_name='Sheet1')

          寫法二:

          problem = cls.driver.find_elements_by_css_selector("li h2.item-title a")
          data = pd.read_excel('example.xlsx', sheet_name = 'Sheet1')
          row = 1
          for i in problem:
              data.loc[row,'問題'] = i.text
              row += 1
          row = 1
          reply = cls.driver.find_elements_by_css_selector("div.item-right p")
          for j in reply:
              data.loc[row,'答案'] = j.text
              row += 1

          DataFrame(data).to_excel('test.xlsx', sheet_name='Sheet1')

          完整代碼
          import pandas as pd
          from pandas import DataFrame
          import unittest
          import time
          from selenium import webdriver
          from selenium.webdriver.support.ui import Select
          from selenium.webdriver.support.select import Select
          from selenium.webdriver.support.ui import WebDriverWait

          class autoLogin(unittest.TestCase):

          URL = 'http://zhidao.baidu.com/business/profile?id=87701'


          @classmethod
          def setUpClass(cls):
          cls.driver = webdriver.Firefox()
          cls.driver.implicitly_wait(20)
          cls.driver.maximize_window()



          def test_search_by_selenium(self):
          self.driver.get(self.URL)
          self.driver.title
          time.sleep(1)
          #將滾動條移動到頁面的底部
          all_window_height =  []
          all_window_height.append(self.driver.execute_script("return document.body.scrollHeight;"))
          while True:
          self.driver.execute_script("scroll(0,100000)") 
          time.sleep(3)
          check_height = self.driver.execute_script("return document.body.scrollHeight;")
          if check_height == all_window_height[-1]:  
          print("我已下拉完畢")
          break
          else:
          all_window_height.append(check_height) 
          print("我正在下拉")

          @classmethod
          def tearDownClass(cls):
          html=cls.driver.page_source
          problem = cls.driver.find_elements_by_css_selector("li h2.item-title a")
          data = pd.read_excel('example.xlsx', sheet_name = 'Sheet1')
          row = 1
          for i in problem:
              data.loc[row,'問題'] = i.text
              row += 1
          row = 1
          reply = cls.driver.find_elements_by_css_selector("div.item-right p")
          for j in reply:
              data.loc[row,'答案'] = j.text
              row += 1
              
          DataFrame(data).to_excel('test.xlsx', sheet_name='Sheet1')

          #保存成網頁
          with open("index.html", "wb") as f:
          f.write(html.encode())
          f.close()
          cls.driver.quit()

          if __name__ == '__main__':
          unittest.main(verbosity=2)

          text.xlsx


          總結
          在使用Scrapy爬蟲時,可以通過selenium來執行網頁中的一些js腳本,但是如何將二者結合起來,以及各種框架之間的靈活運用,都將是我需要面對的。
          --------------------- 
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、網站建設 平面設計服務。

          移動端 驗證碼/密碼 輸入框實現--安卓/ios適用

          seo達人

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

          先貼圖,需要實現的效果是這樣的。



          實現思路有兩個:

           

          1、用6個input,輸入一個數字后將focus給下一個輸入框。

          2、用一個input和6個span,input隱藏,用span顯示。

           

          現在大部分都是使用的第二種方法。(當然,如果你能說服產品也可以只用一個普通的input輸入框,就什么都不用考慮了)

           

          兩種方案遇到的坑,以及優缺點,如下:

           

          方案一:6個input。

           

          主要就是用js切換focus,在安卓是相當流暢的,但是在ios會嚴重卡頓,簡直逼死強迫癥。

           

          HTML:

          <div class="divYZM">
              <!-- onpropertychange是為了避免在ios中oninput方法不被觸發 -->
              <input id="check_1" class="numDiv" type="number" oninput="inputNext(check_1)" onpropertychange="inputNext(check_1)"/>
              <input id="check_2" class="numDiv" type="number" oninput="inputNext(check_2)" onpropertychange="inputNext(check_2)"/>
              <input id="check_3" class="numDiv" type="number" oninput="inputNext(check_3)" onpropertychange="inputNext(check_3)"/>
              <input id="check_4" class="numDiv" type="number" oninput="inputNext(check_4)" onpropertychange="inputNext(check_4)"/>
              <input id="check_5" class="numDiv" type="number" oninput="inputNext(check_5)" onpropertychange="inputNext(check_5)"/>
              <input id="check_6" class="numDiv" type="number" oninput="inputNext(check_6)" onpropertychange="inputNext(check_6)"/>
          </div>
          JS:

          function inputNext (id){ // 傳過來的id是個對象
              var index = Number(id.id.split("_")[1])
              if (id.value.length < 1) { // 刪除
                  id.value = ''
                  if (index > 1) {
                      var preId = 'check_' + Number(Number(index) - 1)
                      document.getElementById(preId).focus()
                      return false
                  }
              } else {
                  if(id.value.length>1) {
                      var nextValue = id.value.slice(1, 2)
                      var nextId = 'check_' + Number(Number(index) + 1)
                      id.value = id.value.slice(0, 1)
                      if ((index+1) <= 6) {
                          document.getElementById(nextId).value = nextValue
                          document.getElementById(nextId).focus()
                      }
                  }
              }
          }
          PS:我這里寫的刪除方法是有問題的,這也是我果斷放棄這種方案的原因之一。

           

          如果正常輸入,然后刪除是可以的。

           

          但是輸入幾個數后,先點擊中間的框刪除一個數字,再回到最后,便只能將中間到最后的這幾個刪掉,最前面的還需要手動點一下得到focus才能刪除。

           

          這對用戶來說,簡直太不友好了。。。

           

          CSS:

          .divYZM{
              width: 90%;
              margin: 0 auto;
              height: 100px;
              background-color: rgba(74, 35, 35, 0.42);
          }
          .numDiv{
              display: block;
              width: 10%;
              float: left;
              border-radius: 5px;
              text-align: center;
              line-height: 60px;
              font-size: 20px;
              font-weight: 900;
              color: red;
              background-color: white;
              height: 60px;
              border: 0;
              padding: 0;
              margin: 0;
              margin-left: 5.7%;
              top: 20px;
              position: relative;
              caret-color: transparent;
          }
          這里遇到的坑,舉例一個。

           

          input限制長度的屬性maxlength

           

          a、與如下兩種配合使用(tel也可以限制)

          <input type="text">  或者
          <input type="password">
           

          b、當type為number時不起作用。這時需要用js控制。

          <input type="number" oninput="if(value.length>5) value=value.slice(0,5)" />
          注意:此外,tel類型的input在ios上會調出全數字鍵盤,而number類型的input則會調出帶有標點符號的鍵盤。

           

           

          方案二:1個input和6個span。

           

          隱藏input,用span顯示內容。大坑就是,何種情況下能調起ios的軟鍵盤呢?

           

          先貼一下我剛開始的input樣式。

          width: 0;
          height :0;
          border: 0;
          padding: 0;
          margin: 0;

          第二種
          display:none;
           

          簡單粗暴,結果就是,ios木得反應。為啥呢,我想不通。

           

          后來在晚上睡覺的時候我在想,我這兩種方式input都么有占位啊,那是不是占位了就可以了呢?

           

          經測果然是可以的(默默譴責自己懶了一下,沒有將不隱藏input的情況,在手機上進行測試)。

           

          接下來貼正確代碼。

           

          CSS:

          #yzm{
              width: 0;
              border: 0;
              padding: 0;
              margin: 0;
              height: .44rem;
              position: absolute;
              outline: none;
              color: transparent;
              text-shadow: 0 0 0 transparent;
              width: 300%;
              margin-left: -100%;
          }
          #yzmTable {
              width: 90%;
              margin: 0 auto;
              height: 100px;
              /* border: 1px solid red; */
              background-color: rgba(74, 35, 35, 0.42);
              /* opacity: 0.1; */
          }
          #yzmTable span { 
              display: block;
              width: 10%;
              float: left;
              border-radius: 5px;
              text-align: center;
              line-height: 60px;
              font-size: 20px;
              font-weight: 900;
              color: red;
              background-color: white;
              height: 60px;
              margin-left: 5.7%;
              top: 20px;
              position: relative;
          }
          這里對input的樣式也包括對光標的隱藏,我在第一種方案中對光標未進行處理,因為在看到ios的卡卡卡之后果斷放棄了第一種方案。

           

          HTML:

          <input id="yzm" type="tel" maxlength="6" value="" oninput="yzmInsert()">
          <div id="yzmTable">
              <span id="s_1" onclick="intoYzm(1)">&nbsp;&nbsp;</span>
              <span id="s_2" onclick="intoYzm(2)">&nbsp;&nbsp;</span>
              <span id="s_3" onclick="intoYzm(3)">&nbsp;&nbsp;</span>
              <span id="s_4" onclick="intoYzm(4)">&nbsp;&nbsp;</span>
              <span id="s_5" onclick="intoYzm(5)">&nbsp;&nbsp;</span>
              <span id="s_6" onclick="intoYzm(6)">&nbsp;&nbsp;</span>
          </div>
          JS:

          function intoYzm(index) {
              var ele = document.getElementById("yzm")
              ele.focus()
          }
           
          function yzmInsert() { // input內容改變時觸發
              for (var i = 1; i <= 6; i++) {
                  var nextId = 's_' + i
                  document.getElementById(nextId).innerHTML = '&nbsp;&nbsp;'
              }
              var yzm = document.getElementById("yzm").value
              var yzmArr = yzm.split('');
              for (var i = 0; i < yzmArr.length; i++) {
                  const num = yzmArr[i];
                  var id = 's_' + Number(i + 1)
                  document.getElementById(id).innerHTML = '&nbsp;' + num + '&nbsp;'
              }
          }
           
          // 收起軟鍵盤的方法,點擊除了輸入框之外的其他區域就收起軟鍵盤
          $('body').on('touchend', function(el) {
              if(el.target.tagName != 'SPAN') {
                      $('yzm').blur()    
                }
          })
           

          在第二種方案中有兩個地方注意下:

           

          a、在js方法中加了對全局中6個span標簽(即六個輸入框)之外區域點擊事件的監聽,用以收起軟鍵盤,方法如下。

          $('body').on('touchend', function(el) {
              if(el.target.tagName != 'SPAN') {
                  $('yzm').blur()
              }
          })
           (比較粗糙,如果頁面中還有別的部分就比較受影響了,可以自行改進)

          b、在隱藏的input中添加了onclick方法,如下并且在其中用了blur方法使得此輸入框失去焦點。為什么這么做呢?

          <input id="yzm" type="tel" maxlength="6" value="" oninput="yzmInsert()" onclick="this.blur();">
          因為此處的隱藏并非真正的隱藏,而是透明化處理,邊框包括光標全部透明化,但實際上它還是占位的,所以當你點擊輸入框上方空白處時,仍會喚起軟鍵盤,就和我們之前所想的點擊輸入框之外區域就收起軟鍵盤沖突了。

           

          因此將input自身的點擊獲取focus禁止掉,就OK了。

           

          之前都是自己亂七八槽的瞎記,第一次寫給別人看,經驗不足,時間倉促。不足之處,還望指正。

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


          軟件測試 學習之路 CSS (四)

          seo達人

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

          一、文字樣式中階

          字體樣式
          代碼格式:
          font: 文字粗細 大小/行高 字體名稱;
          例子:font: bold 200px/400px "微軟雅黑";
          2.字體陰影
          代碼格式:
          text-shadow:x y r color;
          注:x是為負數則陰影向左,整數向右,同理y正數向上,負數向下,r代表陰影模糊程度,數值月大則越模糊,其單位都是px,color為文字顏色。
          例子:text-shadow: 10px 10px 0px red;
          提示:允許一段文字有多層陰影,多層之間用逗號隔開,每一層內,不同參數用空格隔開。

          凹凸字體 陰影巧用
          原理:通過背景顏色以及不同于背景顏色的陰影打造凹凸字體效果
          例子:
          <!DOCTYPE html>
          <html>
          <head>
          <meta charset="UTF-8">
          <title>凹凸文字</title>
          <style type="text/css">
          body{
          background: #ccc;
          }
          div{
          color: #ccc;
          text-align: center;
          font: bold 200px/400px "微軟雅黑";
          /*text-shadow: 1px 1px 0px #fff;-1px -1px 0px #333;*/
          text-shadow: 1px 1px 0px #333,-1px -1px 0px #fff;
          }
          </style>
          </head>
          <body>
          <div >
          凹凸文字
          </div>
          </body>
          </html>

          二、過渡屬性

          過渡屬性的作用就是體現元素默認樣式與最終樣式變化的過程。
          代碼格式:transition:all 1s linear 0s;
          注:

          第一個參數的作用是設置元素的哪些屬性過渡,all表示全部過渡,width代表屬性寬度過渡,其他不過渡,其他屬性也一樣。
          的哥屬性設置過渡需要的時長,單位s不能省略。
          第三個屬性設置過渡延遲多少秒執行,單位s不能省略。
          hover 設置鼠標移到某一元素時狀態。
          transition 這個屬性既可以添加在元素默認狀態,也可以添加在鼠標上移狀態即添加在hover標簽內,區別就是第二種做法在鼠標離開時候不會發生過渡變化。
          例子:
          <!DOCTYPE html>
          <html>
          <head>
          <meta charset="UTF-8">
          <title>過渡屬性</title>
          <style type="text/css">
          div{
          width: 200px;
          height: 200px;
          background-color: green;

          transition:all 1s linear 0s;
           
          }
          div:hover{
          width: 600px;
          background-color: yellow;
          }
          </style>
          </head>
          <body>
          <div id="\">

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

          vue 移動端彈出鍵盤導致頁面fixed布局錯亂

          seo達人

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

          話不多說,直接上問題圖片


          這里確認按鈕是fixed布局 bottom:0 彈出鍵盤之后按鈕被頂到了鍵盤上面

          網上搜到的解決方案有兩種,

          一種是監聽頁面高度(我采用的這種)

          一種是監聽軟鍵盤事件(ios和安卓實現方式不同,未采用)

          下面是實現代碼

          data() {
              return {
                  docmHeight: document.documentElement.clientHeight ||document.body.clientHeight,
                  showHeight: document.documentElement.clientHeight ||document.body.clientHeight,
                  hideshow:true  //顯示或者隱藏footer
              }
            },
          watch: {
                  //監聽顯示高度
                showHeight:function() {
                    if(this.docmHeight > this.showHeight){
                      //隱藏
                        this.hideshow=false
                    }else{
                      //顯示
                        this.hideshow=true
                    }
                }
            },
          mounted() {
                //監聽事件
                window.onresize = ()=>{
                    return(()=>{
                        this.showHeight = document.documentElement.clientHeight || document.body.clientHeight;
                })()
                }
           
            },
          <div class="bottom" v-show="hideshow">
              <div class="btn">
                確認操作
              </div>
            </div>
          我這里使用的是方法是:當鍵盤彈出時,將按鈕隱藏。如果必須出現按鈕的話,可以修改按鈕回歸到正常的流中。
          藍藍設計www.syprn.cn )是一家專注而深入的界面設計公司,為期望卓越的國內外企業提供卓越的UI界面設計、BS界面設計 、 cs界面設計 、 ipad界面設計 、 包裝設計 、 圖標定制 、 用戶體驗 、交互設計、網站建設 、平面設計服務。

          日歷

          鏈接

          個人資料

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

          存檔

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