前端小姿式

文章包含學習中遇到的問題

小白水平 可能會包含一些錯誤 或者還沒寫完... 或者非最佳實踐 僅供參考

1.父子組件的v-model

  • 參考vue官方文檔:點我
  • 父級不須要操做額外代碼
  • 子代操做方法一:
  • 這個vue的官方api會有介紹javascript

    model: {
            prop: 'checked',
            event: 'change'
        }
    • v-on:change="$emit('change', $event.target.checked)"
  • 子代操做方法二:css

    props:{
            value:[String,Number],
        }
    handleInput(event) {
            const value = event.target.value;
            // 經過這個實現v-model的set
            this.$emit('input', value);
        },
  • 2018/8/21 update: 看了很多文章,這種比較多 以input爲例子
  • 先簡單介紹下 v-model 語法糖
<input
         :value="something"
         @input="something=$event.target.value"
    />
    <!-- 組件上的簡化 -->
    <custom-input
    :value="something"
    @input="something=$event"
    >    
    </custom-input>

    <!-- 子組件 -->
    <input type="text" :value="currentValue" @input="handleInput">
    <!-- 1.子組件設置props的value -->
     props:['value'],//接受父組件傳遞過來的value值 
    <!-- 2.向父組件傳遞改變的值 -->
     methods:{
            handleInput(event){
                let value =event.target.value;
                this.$emit('input',value);//觸發input事件,並傳入新的值
            },
            setCurrentValue(value) {
                this.currentValue = value;
            },
        } 
    <!-- 3.重要:經過watch父組件的value改變纔會更新子組件 這裏以前就會出現父級value改變 子代不改變的bug-->
    watch: {
      value(val, oldValue) {
        this.setCurrentValue(val);
      }
    },

2.父子組件的DOM事件

// 例子
     <input type="checkbox" ref='switch' @click="handleClick"/>
     handleClick(evt) {
        this.$emit('click', evt);
      }
    // 例子
     <input type="checkbox" ref='switch' @focus="handleFocus"/>
     handleFocus(event) {
        this.focused = true;
        this.$emit('focus', event);
      },

3.父子組件的data

  • 好比placeholder能夠直接寫,在組件中使用v-bind:'$attrs'

4.父子組件的方法

  • 組件使用的時候會觸發一些方法,這個方法怎麼在父級執行,好比登錄按鈕觸發(19/4/8:回頭看看這句話,我當時在想什麼?)
  • 這個應該看作上面DOM事件,當子元素觸發click,onmouseout,onmouseenter時經過emit觸發父級的一個方法

5.父子組件樣式的設置

/* 父組件 */
  <Example :width=40></Example>
  /* 子組件 */
  <span class="el-switch__core" ref="core" :style="{ 'width': width + 'px' }">

6.組件的註冊和安裝

  • Vue.use()
// 第一步,註冊組件
    import Switch from './src/component';
    Switch.install = function(Vue) {
        // name="TuiSwitch"
        Vue.component(Switch.name, Switch);
    };
    export default Switch;
    // 第二步,安裝組件(main.js)
    import Switch from 'install文件';
    Vue.use(Switch);
    // 第三步,在組件中直接使用便可
    <tui-switch></tui-switch>

7.百分比寬高

  • 脫離標準文檔流的塊級元素的百分百寬高是根據距離最近的定位元素的borderwidth
  • 通常狀況下設置百分百自適應佈局是根據父級元素的contentwidth

8.垂直方向margin,padding的百分比

  • 垂直方向margin,padding百分比,每每不是咱們意料中是根據上級元素的高度(height)來計算的,實際上是根據寬度(width)來計算的
  • 若是爲了實現間距效果可使用一個空的且高度(height)爲百分比的div來實現

9.axios

  • 全局配置:
axios.defaults.timeout = 30000;
    // 開發時只關心接口名稱便可
    axios.defaults.baseURL = "http://10.0.1.1:8080";
    // 配置axios的攔截器,能夠用來配置token
    axios.interceptors.request.use(
        config => {
            if (localStorage.getItem("token")) {
                config.headers.Authorization = localStorage.getItem("token");
            }
            return config
        },
        error => {
            return Promise.reject(error)
        }
    );
  • axios 出現415錯誤,須要在request設置content-type
axios.post(url, params, {
            headers: {
                "Content-Type": "application/json;charset=UTF-8"
            }
            }).then(res=>{})
  • 生成有轉義字符的數據
JSON.stringify({sdkParams: JSON.stringify(this.params)});
    <!-- 這樣子後面的字符串中的引號就會有轉義字符 -->

10.git

  • origin master:master
  • 經過 git remote -v 顯示origin表明的遠程地址
  • 第一個master表示本地的分支名
  • 第二個master表示遠程的分支名,若是沒有會新建
  • win10 中使用 webstorm 時 git不當心保存錯誤的密碼用戶名 push會一直出錯 能夠搜索windows憑據 而後修改便可

11.分析elementUI

  • 解壓壓縮包到當前項目的node_modules目錄
  • node modules 的一些規則
  • import element-ui from 'element-ui'
Node將在node_modules中搜索element-ui目錄,Node會假設element-ui爲一個包並試圖找到包定義文件package.json。若是element-ui目錄裏沒有包含package.json文件,Node會假設默認主文件爲index.js,即會加載index.js。若是index.js也不存在,那麼加載將失敗。
package.json:
{
  "license": "MIT",
  "main": "lib/element-ui.common.js",
  "name": "element-ui",
}
node將會返回element-ui.common.js模塊

12.WebSocket

websocket(prodId) {
        this.ws = new WebSocket('ws://..........');
        this.ws.onopen = function () {
          console.log("ws connected!");
        };
        this.ws.onmessage = e => {

        };
        this.ws.onclose = function () {
          // 關閉 websocket後的回調函數
          console.log("ws closed");
        };
        // 組件銷燬時調用,主動關閉websocket鏈接
        this.over = () => {
          ws.close();
        };
      },
    beforeDestroy() {
        if (this.over) {
          this.over();
        }
    send(msg){
        if(this.ws){
            this.ws.send(msg)
        }
    }

13.Vue單文件格式

<!-- 這是文件擴展名爲 .vue 的 single-file components(單文件組件) 相比傳統new Vue({ el: '#container '})要好不少 -->
    <template>
        <div>This will be pre-compiled</div>
    </template>
    <script src="./my-component.js"></script>
    <style src="./my-component.css"></style>
    <!-- 開發時也會常用這種的格式 -->

14.button的切換動畫

  • 具備切換效果的動畫可使用checked來實現,而且可使用$refs來根據checked的狀態來設置樣式

15.vh,vw

  • 相對於視口的長度單位,pc視口就是瀏覽器窗口,因此能夠實現window.onresize的效果(這句話應該是自適應的意思?)

16.flex

  • flex是flex-grow flex-shrink flex-basis的縮寫html

    • flex-grow相比其餘元素的比例
    • flex-shrink元素佔得份數,用來計算收縮時縮放的程度
    • flex-basis元素默認寬度
  • flex:1 的子代會自動撐開填滿空白部位,在不使用絕對定位時,能夠實現一個寬度自適應,另外一個寬度固定(使用width設置固定值)
  • 在有固定高的容器中實現標題在上面,內容在剩餘高度居中:前端

    • 父元素
    display: flex;
        flex-direction: row;
        flex-wrap: wrap;
    • 標題flex:1來實現佔滿一行
    • 須要居中的子元素align-self: flex-start||baseline;均可以實現,(測試元素是一個img)

17.事件的解綁

var EventUtil={
     /*檢測綁定事件*/
     addHandler:function(element,type,handler){
         if(element.addEventListener){
            element.addEventListener(type,handler,false);
        }
        else if(element.attachEvent){
            element.attachEvent('on'+type,handler);
        }
        else{
            element["on"+type]=handler /*直接賦給事件*/
        }

    },
    /*經過removeHandler*/
    removeHandler:function(element,type,handler) {   /*Chrome*/
        if (element.removeEventListener)
            element.removeEventListener(type, handler, false);
        else if (element.deattachEvent) {               /*IE*/
            element.deattachEvent('on' + type, handler);
        }
        else {
            element["on" + type] = null;
            /*直接賦給事件*/
        }
    }
};

### 18.多層組件的封裝vue

  • 其實多層組件中參數是能夠傳遞的,好比這個taginput,並且使用v-model傳遞參數,並不須要使用watch監聽value改變而後使用$emit,value變化會自動從子組件傳遞到最外層
  • 18-9-13 當時的觀點有點弱智啊,這個這個直接改變了子組件中的值啊,多是由於對象深度緣由沒有報錯?java

    <!-- 數據單向綁定,不須要使用watch從父組件更新值到子組件,這句話很矛盾啊 -->
      <template>
      <div>
          <div class="product_info_row" v-for='(arr,index) in value' :key="index">
          <div class="tag_input">
              <lubun-input :cancleable='true' v-for='(v,i) in arr.tags' :key="i" type="text" v-model="v.value" :width=width :tagrow='index'
              :tagid='v.id' @click='removeTag' />
              <!-- 失去焦點也須要保存 -->
              <lubun-input autofocus v-if='arr.show' type="text" v-model="arr.value" :width=80 @enter='buildTag(arr)' @blur='buildTag(arr)'
              />
              <lubun-button v-else text="+" @click="addTag(arr)" :width=30 />
          </div>
          </div>
      </div>
      </template>
      <script>
      export default {
          name: "LubunTaginput",
          componentName: "LubunTaginput",
          props: {
              width: {
                  type: [String, Number],
                  default: 150
              },
              value: {
                  type: Array,
                  default: function () {
                      return [
                          {
                          id: 0,
                          show: false,
                          value: "",
                          tags: []
                          }
                      ]
                  }
              }
          },
          methods: {
              addTag(rows) {
                  rows.show = true;
                  rows.value = "";
              },
              removeTag(obj) {
                  // console.log("傳入的rows:",obj);
                  var tags = this.value[obj.tagRow].tags;
                  // console.log("rows中的tags",tags);
                  for (let i = 0; i < tags.length; i++) {
                      // console.log("循環tags:", tags[i]);
                      if (tags[i].id === obj.tagId) {
                          // console.log('find');
                          tags.splice(i, 1);
                          return;
                      }
                  }
              },
              buildTag(rows) {
                  rows.show = false;
                  // 內容爲空不會生成tag
                  if (rows.value !== "") {
                      rows.tags.push({ id: rows.id++, value: rows.value });
                      rows.value = "";
                  }
              }
          },
      };
      </script>

19.absolute的寬度

  • 有些狀況absolute居中須要使用兩個嵌套absolute的div,這個時候最外層有可能會寬度不會被內容撐開,若是是文本的話可使用white-space:nowrap 這樣就能夠撐開兩個div了
  • transform: translateX(-50%);transform: translateY(-50%);只會有一個生效, 須要使用縮寫形式 transform: translate(-50%,-50%); 這個能夠實現一個absolute塊完美居中

20.vue事件總線:BUS

  • 解決組件之間信息的傳遞,發送數據的組件使用$on("Event Name",value)事件觸發(當數據改變時觸發這個函數就能夠了),接受數據的組件使用$emit("Event Name",callback)接受便可,你能夠把這個事件註冊在mounted中(以後這個就能夠等着其餘組件$emit的數據了)
  • 事件有時候會重複觸發:註冊的事件是全局的,它並不會隨着組件的銷燬而自動註銷,須要手動註銷
beforeDestroy() {
             //組件銷燬前須要解綁事件。不然會出現重複觸發事件的問題
             bus.$off("Event Name");
         },
  • PS:在生命週期beforeDestroy,destroy中,this.$route.path 獲取到的實際上是下一個頁面的path

21.flex兩列布局

  • 左右兩列布局
  • 左邊寬度自適應,可是有個最小寬度
  • 右邊寬度固定
father{
        display: flex;
        width: 100%;
        height: 100%;
        overflow: auto;
    }
    child-left{
        position: relative;
        min-width: 800px;
        height: 100%;
        flex: 1;
    }
    child-right{
        position: relative;
        min-width: 420px;
        height: 100%;
    }

22.上傳圖片按鈕

  • 使用lable+vue實現
<label style="width:80%" class='btn' for="uploadPic">上傳文件</label>
    <input id="uploadPic" type="file" @change='uploadPic' style="display:none">
  • 使用js實現
<span class="button" onclick="sel_local_images()" id="add_img" title="Add new file from local disk">加載圖片</span>
    <input type="file" id="invisible_file_input" name="files[]" style="display:none">
    //js中再給input加change事件便可
    //這個也能夠在vue中使用,給input加@change,而後手動觸發這個input 的click()就能夠彈出上傳文件的界面了
var invisible_file_input = document.getElementById("invisible_file_input");
    function sel_local_images() {
                 if (invisible_file_input) {
                     invisible_file_input.setAttribute('multiple', 'multiple');
                     invisible_file_input.accept = '.jpg,.jpeg,.png,.bmp';
                     invisible_file_input.onchange = (e)=>{
                         // 得到第一張圖片
                         var img = e.target.files[0];
                     };
                     invisible_file_input.click();
                 }
             }

23.圖片base64顯示

//reader有幾個讀取文件的方法用於讀取成不一樣格式,還有幾個鉤子函數用於不一樣階段執行一些功能
                // var img =xxxxxxxxxxxx 
                // 將圖片的base64格式顯示在頁面上,圖片可使用input上傳
                let reader = new FileReader();
                reader.onload = (theFile)=>{
                        that.imgLoaded = e.target.result;
                        // 2018-10-24 圖片尚未加載完成,不是DOM的問題,使用onload才能正確得到原始寬高
                        var i = new Image();
                        i.src = e.target.result;
                        i.onload = () => {
                            img_loaded_width = i.width;
                            img_loaded_height = i.height;
                }}
                // 這個貌似會執行上面的onload
                reader.readAsDataURL(img);

24.前端下載文件

var blob = new Blob([JSON.stringify(data, null, 2)],{type : 'application/json'});
    var aTag = document.getElementById('download_img');
    aTag.setAttribute('href', URL.createObjectURL(blob));
    aTag.setAttribute('download',  that.imgLoadedName.split('.')[0]+'.json');
    aTag.click();

25. vue中ref命名不可使用中劃線

26. 前端調用相機

  • 經過video控件,經過捕獲video的流,截取video中的圖像實現拍照,
  • 經過input[file]控件調用移動端的攝像頭,實現拍照。
第一種能夠實現對拍照界面的重寫,IPhone環境11開始兼容;

    第二種方式其實是調用input[type='file'],會彈出一個選擇框讓用戶選擇是調用相機仍是調用相冊,

    第二種兼容優於第一種,很差的地方就是這種方法沒法控制拍照,想要在移動端實現只能拍照不能選擇照片或者在拍照界面添加引導遮罩層的方法是行不通了。
<video width="640" height="480" id="myVideo"></video>
    <canvas width="640" height="480" id="myCanvas"></canvas>
    <button id="myButton">截圖</button>
    <button id="myButton2">預覽</button>
    <button id="myButton3">
        <a download="video.png">另存爲</a>
    </button>
var cobj = document.getElementById('myCanvas').getContext('2d');
    var vobj = document.getElementById('myVideo');

    getUserMedia({video: true}, function (stream) {
        vobj.src = stream;
        vobj.play();
    }, function () {
    });


    document.getElementById('myButton').addEventListener('click', function () {
        cobj.drawImage(vobj, 0, 0, 640, 480);
        document.getElementById('myButton3').children[0].href = cobj.canvas.toDataURL("image/png");
    }, false);

    document.getElementById('myButton2').addEventListener('click', function () {
        window.open(cobj.canvas.toDataURL("image/png"), '_blank');
    }, false);


    function getUserMedia(obj, success, error) {
        if (navigator.getUserMedia) {
            getUserMedia = function (obj, success, error) {
                navigator.getUserMedia(obj, function (stream) {
                    success(stream);
                }, error);
            }
        } else if (navigator.webkitGetUserMedia) {
            getUserMedia = function (obj, success, error) {
                navigator.webkitGetUserMedia(obj, function (stream) {
                    var _URL = window.URL || window.webkitURL;
                    success(_URL.createObjectURL(stream));
                }, error);
            }
        } else if (navigator.mozGetUserMedia) {
            getUserMedia = function (obj, success, error) {
                navigator.mozGetUserMedia(obj, function (stream) {
                    success(window.URL.createObjectURL(stream));
                }, error);
            }
        } else {
            return false;
        }
        return getUserMedia(obj, success, error);
    }

27. xml解析:<command>標籤在轉成DOM時會直接去掉中間的子代,很奇怪

28. el的表單驗證prop和rule中屬性名和v-model的參數名稱是要相同的

29. RestTemplate的請求會經過其餘服務的過濾器

30. jenkins rancher 實現持續集成 jira跟蹤

31. n不換行

有時候後端傳過來的字符串中\\n轉成字符對象時會成爲\n可是在vue中渲染到頁面中不會出現換行,而是顯示爲\n
    (compose.environment[key]).replace(/\\n/g,'\n') 而後就能夠實現前端換行了 很奇怪 不知道爲何

32. 傳遞單純數組的後端操做

//{men:{name:'Kik',age:11},place:['A','B','C']}
     ArrayList<String> place = (ArrayList<String>) jsonObject.getObject("place", List.class);

33. fastJSON通常用法

String algorithmList = "["a","b","c"]" 
    List<String> apacMainIdList = JSONObject.parseObject(algorithmList, List.class);

34. body的帶siderbar的自適應佈局

<!--使用absolute和top,left,right,bottom來完成div填充剩餘部分-->
     <div style="position:absolute;background:#ccc;top:0;left:0;right:0;bottom:0;overflow:hidden">
           <div style="position:absolute;width:140px;background:#C00;top:0;left:0;bottom:0">
           </div>
           <div style="position:absolute;left:140px;background:#0C0;top:0;right:0;bottom:0;">
           </div>
     </div>

35. 前端讀取網絡路徑文件

  • XMLHttpRequest
// 讀取爲二進制
    function createXHR(){
        return window.XMLHttpRequest?
        new XMLHttpRequest():
        new ActiveXObject("Microsoft.XMLHTTP");
    }
    function getData(url){
        let request = createXHR();
        request.open("GET",url,false);
        request.responseType = 'blob';
        request.onload = function () {
                        var reader = new FileReader();
                        reader.readAsArrayBuffer(request.response);
                        reader.onload = function (e) {
                            var DAT_data = e.target.result;
                            console.log("DAT_data:" + DAT_data);
                        };
                    };
        request.send();
    }
  • ajax

36. event.target 和 event.currentTarget

  • target是觸發事件的那個元素 currentTarget是處理這個事件的元素 好比ul和li,給ul綁定點擊事件,點擊li後,target是li,currentTarget是ul

能夠參考

相關文章
相關標籤/搜索