後端小白的VUE入門筆記, 前端高能慎入

由於項目須要先後端分離,後端居然不用控制view層了,頁面的跳轉後端再也不干涉,(前端的vue通過打包後成了一張index.html) 後端只須要響應給前端json串就ok,其實這不是爽歪歪?可是以爲仍是奇奇怪怪,感受前端是個黑盒了, 因而忍不住去學習了vuejavascript

感受前端的框架帶來的這種先後端分離變化仍是特別明顯的,後端確實不用再操心view層了,頁面的轉換有vue經過後端的切換不一樣的組件,後端基本上沒有什麼變化,可是相應數據基本上是清一色的json格式的數據了, 此外, 目前碰到的後端的安全框架 SpringSecurity的使用有了些許變化,起碼認證成功仍是失敗,不能往指定的頁面跳轉了,轉而使用消息+狀態碼提示,由於就一張index.html,還能往哪裏跳轉?css

下面是近幾天的學習筆記, 仍是再整理一遍,畢竟會忘html

認識MVVM框架Vue

MV VM分別對應着前端

  • model : 數據模型,存放後端傳遞過來的數據
  • view : 視圖,其實就是html, 頁面
  • viewModel : vue 的實例

下面是一個入門的例子: 經過這個例子能夠看到:vue

  • 咱們new 出來vue的實例,而後把它關聯在了html中id爲 app的代碼塊,這樣目的是若是咱們在這個代碼塊中使用vue的模板語法,vue能夠解析
  • data: 這個模塊盛放的 mvvm中的第一個mjava

    其實這也能夠看出,vue的開發模式,它的出現屏蔽掉了dom操做,咱們不再用document.getElementById(), 而後innnerHtml了, 如今的工做就是把後端給的值填充進data塊中的屬性字段就ok,一旦發生改變,頁面會自動渲染上最新的值es6

<body>
<div id="app">
    <input type="text" v-model="username"><!-- 聲明式開發 dom監聽  -->
    <p>Haha {{username}}</p>   <!-- 數據綁定 -->
</div>

</body>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
    el:'#app', // 元素選擇器, 選出根路徑
    data:{ // Data Model 數據模型
       username:'哈哈'
    }
});
</script>

模板語法:

雙大括號 取值:ajax

<p>{{msg}}</p>
<p>{{msg.toUpperCase()}}</p>  <!--  能夠調用js函數 -->

嵌入文本或html編程

<p v-text="msg"></p>    <!--  至關於 textContent -->
<p v-html="msg"></p>   <!--  至關於 innerHtml -->

強制數據綁定,在原標籤前添加 :json

<img :src="imaUrl" alt="">

綁定監聽事件: @符

  • 比較有趣的地方,若是在methods塊中,js函數的定義是無參數據的, 在html代碼塊中能夠直接寫函數名,而不寫小括號,由於java代碼寫多了,看了想笑 ,(固然(),也能夠寫上,可是js編程者會認爲這是沒事找事)
<button @click="text"> 點我111 </button>
<button @click="text222('haha')"> 點我222 </button>

計算屬性

計算屬性,說白了就是vue給咱們的一塊糖,讓咱們定製數據的變化規則,而後vue幫咱們渲染在html頁面上

  • 計算屬性是針對data中的字段的操做
  • 計算屬性中的每個函數,都分兩部分: get和set , 默認是get,做用是把這個方法的返回值渲染進頁面, set方法,就是從新設置值, 而後get會從新渲染html
  • 計算屬性是存在緩存的,key就是函數的名字,value就是計算獲得的值

例子:

<body>
<div id="app">
姓名: <input type="text" placeholder="FirstName" v-model="secondName"> <br>
姓名1: <input type="text" placeholder="FullName1" v-model="FullName1"> <br>
姓名3: <input type="text" placeholder="FullName3" v-model="FullName3">  <br>
</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
// 下面的所有回調函數中, this都是vm對象
var vm = new Vue({
el: '#app',
data: {
    firstName: 'A',
    secondName: 'B',
},
computed: {
    FullName1() {
        return this.firstName + ' ' + this.secondName;
    },
    // todo  經過計算屬性實現雙向的數據綁定, 不受其餘影響
    FullName3: {
        get() { // 計算並返回當前屬性的值
            return this.firstName + ' ' + this.secondName;
        },
        set(vel) {  // get 執行以後 把結果返回給 set
            const names = vel.split(' ');
            alert(names[0]);
            alert(names[1]);
            this.firstName = names[0];
            this.secondName = names[1];
        }
    }
}
});

計算屬性寫在computed塊中, 能夠看到它經常使用的兩種寫法, 在使用是時候都是直接使用函數名就行,由於它並無參數

  • 函數名(){}
  • 對象名:{ get(){} , set(){} }

上面的FullName1以函數的,這種書寫格式是對 get方法的默認實現,方法的返回值會被渲染到頁面上

FullName3還重寫了set(val){} 方法, 若是咱們在FullName3對應的輸入框裏面輸入新的值, val就是這個新的值,在set方法中,若是對當前vue實例的data中的屬性作了改動,這個改動是雙向的,頁面中全部使用對應字段的地方的值,都會從新渲染

事件的監聽:

它的語法:

// 下面的所有回調函數中, this都是vm對象
var vm = new Vue({
el: '#app',
data: {
    firstName:'',
    secondName:''
},
computed: {},
method: {},
watch: {/* 監視 */
    firstName: function (newVal) {
        this.firstName = newVal + ' ' + this.secondName;
    }
}
});

它會監聽data中的屬性,當用戶改變了data中屬性的值,就會觸發對應的回調

class和style的綁定

class和style的屬性綁定一樣使用的是使用 : 強制屬性綁定

首先是寫好 css屬性,才能進一步使用vue將屬性樣式綁定在html上

head>
<meta charset="UTF-8">
<title>Title</title>
<style>
    .aClass{
        font-size: 30px; 
        color: #ff4400;
    }
    .bClass{
        color: #00b4ff;
    }
    .cClass{
        color: #1c036c;
    }
</style>
</head>

語法:

  • :class="data中的css屬性"
  • :class="{data中的css屬性:boolean, data中的css屬性:boolean}", 這種對象語法,就是當類名肯定可是是否顯示不肯定時使用,好比讓一個導航欄中的一個高亮顯示
  • :style="{color:activeColor,fontSize:fontSize +'px'}", style有單位的+單位
<body>
<div id="text">
    <h2>1. class綁定 :: class='X X X '</h2>
    <p :class="a">123123字符串</p>
    <p :class="{aClass:isa, bClass:isb}">class是對象,綁定class 類名:boolean </p>
    <h2>2. style 綁定 </h2>
    <p :style="{color:activeColor,fontSize:fontSize +'px'}">2. style 綁定 </p>
<button @click="update" >點擊</button>
</div>

下面的vue對象

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
var vm = new Vue({
    el: '#text',
    data: {
        a:'aClass', // 關聯着最上面的css樣式
        isa:true,
        isb:false,
        activeColor:'red',
        fontSize:'30'
    },
    methods:{
        update() {
            this.a='bClass'
        }
    }
})

條件渲染

<p v-if="ok">deal</p> --> ok是vue中data的數據,ok爲true時, 顯示
<p v-else>false</p>  --> 和 v-if成對出現, ok爲false, 顯示

<p v-show="ok"> 成功 </p>
<p v-show="!ok"> 失敗 </p>

列表的渲染 v-for, 及對數組的操做

下面的例子使用v-for遍歷數組中的每個數據, 遍歷的同時使用{{對象.屬性}}展現屬性,同時能夠根據每一個li的index綁定上不一樣的事件

<body>
<div id="text">
    <ul>
        <!-- 一旦有 v-for  加上key-->
        <li v-for="(p,index) in person" :key="index">
            {{p.name}} : {{p.age}} : {{index}}
            <button @click="deleteP(index)"> 刪除</button>
            <button @click="updateP(index,{name:'Cat',age:20})"> 更新</button>
        </li>
    </ul>
</div>

var vm = new Vue({
el: '#text',
data: {
person: [  /*  vue 只會監視person的改變, 不會監視數組中數據的改變*/
    {name: 'tom', age: 23},
    {name: 'tom2', age: 223},
    {name: 'tom2', age: 23},
    {name: 'tom3', age: 232},
    {name: 'tom5', age: 23}
]
},
methods: {
deleteP(index) {
    this.person.splice(index, 1);  //從index開始 刪除1個
},
updateP(index, person) {
    //  this.person[index]=person; 並無改變 persons  , 從index開始,刪除1個 添加person
    this.person.splice(index, 1, person)
}

若是咱們更新的js是這樣寫的, 數組中的內容確實會被改變,可是頁面的上數據並不會更新

this.person[index]=person; 並無改變 persons  , 從index開始,刪除1個 添加person

由於vue監聽的person的改變,person中只有一個數組,雖然數組中的數據變了, 可是數組沒變,因此咱們使用vue的提供的splice進行數組的操做

splice(下標,數量,[新的對象數組])

他能夠實現數組的增刪改的效果

  • 刪除
//刪除起始下標爲1,長度爲2的一個值(len設置2)
var arr2 = ['a','b','c','d']
arr2.splice(1,2);
console.log(arr2); 
//['a','d']
  • 修改
//替換起始下標爲1,長度爲1的一個值爲‘ttt’,len設置的1
var arr = ['a','b','c','d'];
arr.splice(1,1,'ttt');
console.log(arr);        
//['a','ttt','c','d']
  • 添加
var arr = ['a','b','c','d'];
arr.splice(1,0,'ttt');
console.log(arr);        
//['a','ttt','b','c','d']

其餘數組相關的操做

  • unshift()添加到第一個
  • shift() 添加到最後一個
  • push() 壓棧,棧頂
  • pop()彈出
  • sort()排序
  • reverse() 反轉

數組的映射,過濾,排序

js的箭頭函數和java8的lambda表達式特別像

  • 映射
array.map(item=>item.id)
// 能夠將數組中的每個元素映射成他的id屬性
  • 過濾
persons = person.filter(p => p.name.indexOf(searchModel)>=0); 
// 保留數組中知足條件的對象
  • ES6的語法糖
    把對象的指定字段存放進聲明的多個常量中
const{searchModel,person,orderType} = this;
  • 排序
persons.sort(function (p1,p2) {
                // 升序
                if (orderType===1){
                    return p1.age-p2.age;
                } else if (orderType===2){ // 降序
                    return p2.age-p1.age;
                }

事件綁定相關

@click綁定事件

<button @click="text1">text1</button>
<button @click="text2('haha')">text2</button>
<button @click="text3($event)">text3</button>
<button @click="text4">text4</button><!-- 若是沒有指定參數進去,傳遞進去的就是event-->
<button @click="text5(123,$event)">text5</button>

 var vm = new Vue({
el:'#test',
methods:{
    text1(){
        alert("text 1");
    },
    text2(msg){
        alert(msg);
    },
    text3(event){
        alert(event.target.innerHTML);
    },
    text4(event){
        alert(event.target.innerHTML);
    },
    text5(msg,event){
        alert(msg+event.target.innerHTML);
    },

能夠看到@click使用vue中method的函數時,若是沒有參數,能夠簡寫,去掉(), 若是不寫參數,傳遞進去的是事件自己event , text三中經過event拿到了標籤的文本內容

@click.prevent阻止事件的默認行爲

<a href="http:www.baidu.com" @click.prevent="text8">百度一下</a>  <!-- 阻止事件的默認行爲 -->

監聽某個按鍵的點擊事件

<input type="text" @keyup.enter="text9"> <!--  @keyup.13(名字)  監聽某一個鍵的點擊事件 -->

收集表單數據

使用vue將用戶填入表單中的數據收集起來, 收集到哪裏去? 實際上是收集到 vue的data塊中的屬性中

其實就是在html使用v-model暴力綁定dom監聽, 將單選框,輸入框,多選框中用戶輸入進去的內容和data中的屬性關聯起來

  • input,textarea 等輸入框,收集起來的值就是用戶輸入進去的值
  • 單選框 radio ,多選框 checkbox 等選擇框,收集起來的值的 html中的value屬性的值
<h1>表單中最終提交給後臺的是 value值</h1><br>
<h2> 使用v-model實現表單數據的自動收集 </h2>
<form action="/XXX"  @submit.prevent="handleSubmit" ><!-- 阻止表單的默認自動提交事件 -->
   <span>用戶名:</span>
   <input type="text" v-model="username"><br>
   <span>密碼</span>
   <input type="password"  v-model="pwd" ><br>

   <span>性別</span><br>
   <input type="radio" id="female" value="女" v-model="sex">
   <label for="female">女</label><br>
   <input type="radio" id="male"  value="男" v-model="sex">
   <label for="male">男</label><br><br>

   <span>愛好</span><br>
   <input type="checkbox" id="basket" value="basket" v-model="likes">
   <label for="basket">籃球</label>
   <input type="checkbox" id="foot" value="foot"  v-model="likes">
   <label for="foot">足球</label>
   <input type="checkbox" id="pingpang"  value="pingpang"   v-model="likes">
   <label for="pingpang">乒乓球</label><br><br>

   <span>城市</span><br>
   <select v-model="cityId">
       <option value="">未選擇</option>
       <option :value="city.id" v-for="(city,index) in allCitys" :key="index">{{city.name}}</option>
   </select>
   <span>介紹:</span>
   <textarea name="" id="" cols="30" rows="10" v-model="dec"></textarea>

<input type="submit" value="註冊"><br>

    </form>
    </div>
    <script type="text/javascript" src="js/vue.js"></script>

<script type="text/javascript">

var vm = new Vue({
    el:'#test',
    data:{
        username:'',
        pwd:'',
        sex:'女',
        likes:['foot'],
        allCitys:[{id:1,name:'北京'},{id:2,name:"山東"},{id:3 ,name:"青島"}],
        cityId:'3' /* 默認讓 3被選中*/,
        dec:"哈哈"
    },

    methods:{
        handleSubmit(){
            alert(this.username+this.pwd);
            alert(this.sex);
        }
    }
})

vue的生命週期

vue對象在建立初始化的過程當中一次執行以下聲明週期相關的方法, 根據這個特性,一般把加載進入一個新的頁面中時去發送ajax請求的方法放到mounted(){},收尾工做放在beforeDestroy(){}

var vm = new Vue({
el: "#text",
data: {},

beforeCreate() {  // 建立以前回調
    console.log("beforeCreate");
},

created() {  // 建立以後回調
    console.log("created");
},

beforeMount() {
    console.log("beforrMount");
},

// todo 經常使用, 異步操做, 好比發起ajax請求獲取數據, 添加定時器
mounted() { // 初始化顯示以後會當即調用一次
    console.log("mounted");
    this.intervalId = setInterval(() => {
        console.log("幹掉vm以後, 定時器還在跑, 內存泄露了");
        this.isShow = !this.isShow;
    }, 1000);

    /*
      若是下面不使用箭頭回調函數, this就是window, 而不是vm
    * setInterval(() => {
        this.isShow= !this.isShow;
    },1000);
    * */
},

// 更新階段
beforeUpdate() {  //更新階段以前回調
    console.log("beforeUpdate");
},

updated() {  // 更新階段以後回調
    console.log("updated");
},

// 死亡階段
// todo 經常使用 收尾工做
beforeDestroy() {  // 死亡以前回調一次
    console.log("beforeDestroy ");
    clearInterval(this.intervalId);
},

destroyed() {
    console.log("destroyed");
},

methods: {}
}
});

ES的語法糖,箭頭函數

好比在設置定時器時, 定時器中須要對vue的屬性進行操做,在定時器的代碼塊中this指的是定時器對象,es6的箭頭語法解決就這個問題, 在箭頭函數中this沒有的屬性,會到外層的vue中來找

this.intervalId = setInterval(() => {
    console.log("幹掉vm以後, 定時器還在跑, 內存泄露了");
    this.isShow = !this.isShow;
}, 1000);

動畫

按照vue的下面的幾步要求, vue 會給目標元素添加或者移除特定的 css,實現動畫的效果

  1. 須要添加動畫的標籤被 <transition name="" > XXX </transition>包裹
<div id="test">
   <transition name="YYY">
    <p v-show="isShow" class="">toggle</p>
    <button @click="isShow=!isShow">toggle</button>

    </transition>
</div>


<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    new Vue({
        el: '#test',
        data() {
            return {
                isShow: true
            }
        }
    });
  1. 定義以 .YYY-開頭的 css屬性, 這個YYY就是上面自定義的YYY, 須要在這些自定義的屬性中指定過分的屬性以及隱藏的屬性

一個簡單的動畫效果標籤從隱藏->出現, 再從出現到隱藏的過程,就像下面這樣

v-enter  v-enter-to   v-leave    v-leave-to
  隱藏     出現         出現       隱藏

自定義這四個時期的狀態

/* 顯示的過分效果*/
.YYY-enter-active {
    transition: all 1s;
}

/* 隱藏的過分效果*/
.YYY-leave-active {
    transition: all 3s;
}

/* 從無到有的樣式  */
.YYY-enter {
    opacity: 0;
}

/* 從有到無的樣式  */
.YYY-leave-to {
    opacity: 0;
    transform: translateX(20px);  /* 離開時,向X軸的正方向移動20px*/
}

格式化時間的插件庫

點擊進入 moment.js網址 ,在這裏能夠找到須要引入的script標籤

點擊進入 moment.js的文檔 在文檔中能夠找到對應的格式和例子

<div id="test">
    <h2>顯示格式化的日期時間</h2>
    <p>{{date}}</p>
    <p>默認完整: {{date | dateFormat}}</p><!--  一旦咱們這麼寫, 他就會把date的值,傳遞給dateFormat函數 -->
    <p>年月日: {{date | dateFormat('YYYY-MM-DD')}}</p><!--  一旦咱們這麼寫, 他就會把date的值,傳遞給dateFormat函數 -->
    <p>時分秒: {{date | dateFormat('HH:mm:ss')}}</p><!--  一旦咱們這麼寫, 他就會把date的值,傳遞給dateFormat函數 -->

</div>

/*  這個在官網上查找 */
<script  type="text/javascript" src="https://cdn.bootcss.com/moment.js/2.21.0/moment.js"></script>

<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
        // 自定義過濾器
    Vue.filter('dateFormat',(value,format)=>{ /*  Vue是函數對象 */
      return moment(value).format(format || 'YYYY-MM-DD HH:mm:ss');
    });

    new Vue({
        el:'#test',
        data:{
            date:new Date()
        }
    });

Es的語法糖

es6 的語法: 形參默認值 , 沒傳值的話,就使用默認值

function(value,format="YYYY-MM-DD"){
     return moment(value).format(format);
 }

vue的指令

常見的原生指令以下

v:text : 更新元素的textContent <br>
v:html : 更新元素的innerHtml<br>
v-if: true    若是爲true,標籤纔會輸出到頁面 <br>
v-else:    若是爲false,標籤纔會輸出到頁面 <br>
v-show:  經過控制display的樣式來控制顯示和隱藏<br>
v-for:    遍歷數組對象 <br>
v-on:   綁定監聽事件, 通常直接寫  @ <br>
v-bind:  強制綁定解析表達式  通常簡寫成 : <br>
v-model:  雙向數據綁定 <br>
ref:  指定惟一的標識, Vue對象能夠經過 $els 屬性來訪問這個元素對象  <br>
v-cloak: 防止閃現可能應爲網速的緣由{{msg}} 一直解析不了, 因而用戶就看到它了,不友好, 因而 vue推出 與css配合 [v-cloak] {display:none}  <br>

補充最後兩個

  • ref 指定惟一的標識, Vue對象能夠經過 $els 屬性來訪問這個元素對象
  • 防止閃現可能應爲網速的緣由{{msg}} 一直解析不了, 因而用戶就看到它了,不友好, 因而 vue推出 與css配合 [v-cloak] {display:none}

例子:

<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <style>
        [v-cloak] {   /*  回去尋找有這個屬性名的標籤  [v-cloak]   , 就是下面的p標籤 */
            display:none
        }
    </style>
</head>
<body>

<div id="test">
    <p ref="content123">哈哈哈哈</p>
    <button @click="hint">提示</button>
    //  v-cloak="" + 上面的css 樣式避免 {{ }} 閃現的效果
    <p v-cloak="">{{msg}}</p>
    <br>

</div>
<script type="text/javascript" src="js/vue.js"></script>
<script type="text/javascript">
    // 註冊全局指令
    Vue.directive('')

    new Vue({
       el:'#test',
       data:{
        msg: '嘿嘿'
       } ,
        methods:{
            hint(){
              //  由於 `<p ref="content123">哈哈哈哈</p>` 使用了ref,因此vue能夠經過this.$refs.content123 找到指定的這個元素
                alert(this.$refs.content123.textContent)
            }
        }
    });
相關文章
相關標籤/搜索