由於項目須要先後端分離,後端居然不用控制view層了,頁面的跳轉後端再也不干涉,(前端的vue通過打包後成了一張index.html) 後端只須要響應給前端json串就ok,其實這不是爽歪歪?可是以爲仍是奇奇怪怪,感受前端是個黑盒了, 因而忍不住去學習了vuejavascript
感受前端的框架帶來的這種先後端分離變化仍是特別明顯的,後端確實不用再操心view層了,頁面的轉換有vue經過後端的切換不一樣的組件,後端基本上沒有什麼變化,可是相應數據基本上是清一色的json格式的數據了, 此外, 目前碰到的後端的安全框架 SpringSecurity的使用有了些許變化,起碼認證成功仍是失敗,不能往指定的頁面跳轉了,轉而使用消息+狀態碼提示,由於就一張index.html,還能往哪裏跳轉?css
下面是近幾天的學習筆記, 仍是再整理一遍,畢竟會忘html
MV VM分別對應着前端
下面是一個入門的例子: 經過這個例子能夠看到: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="">
綁定監聽事件: @符
<button @click="text"> 點我111 </button> <button @click="text222('haha')"> 點我222 </button>
計算屬性,說白了就是vue給咱們的一塊糖,讓咱們定製數據的變化規則,而後vue幫咱們渲染在html頁面上
例子:
<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塊中, 能夠看到它經常使用的兩種寫法, 在使用是時候都是直接使用函數名就行,由於它並無參數
上面的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的屬性綁定一樣使用的是使用 : 強制屬性綁定
首先是寫好 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>
語法:
<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遍歷數組中的每個數據, 遍歷的同時使用{{對象.屬性}}展現屬性,同時能夠根據每一個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進行數組的操做
他能夠實現數組的增刪改的效果
//刪除起始下標爲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); // 保留數組中知足條件的對象
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中的屬性關聯起來
<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對象在建立初始化的過程當中一次執行以下聲明週期相關的方法, 根據這個特性,一般把加載進入一個新的頁面中時去發送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: {} } });
好比在設置定時器時, 定時器中須要對vue的屬性進行操做,在定時器的代碼塊中this指的是定時器對象,es6的箭頭語法解決就這個問題, 在箭頭函數中this沒有的屬性,會到外層的vue中來找
this.intervalId = setInterval(() => { console.log("幹掉vm以後, 定時器還在跑, 內存泄露了"); this.isShow = !this.isShow; }, 1000);
按照vue的下面的幾步要求, vue 會給目標元素添加或者移除特定的 css,實現動畫的效果
<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 } } });
一個簡單的動畫效果標籤從隱藏->出現, 再從出現到隱藏的過程,就像下面這樣
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() } });
es6 的語法: 形參默認值 , 沒傳值的話,就使用默認值
function(value,format="YYYY-MM-DD"){ return moment(value).format(format); }
常見的原生指令以下
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>
補充最後兩個
例子:
<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) } } });