##Python項目-Day54-vue.js
-
Vue.js是什麼?
Vue (讀音 /vjuː/,類似於 view) 是一套用於構建用戶界面的漸進式框架。與其它大型框架不同的是,Vue 被設計爲可以自底向上逐層應用。Vue 的核心庫只關注視圖層,不僅易於上手,還便於與第三方庫或既有項目整合。另一方面,當與現代化的工具鏈以及各種支持類庫結合使用時,Vue 也完全能夠爲複雜的單頁應用提供驅動。
-
聲明式渲染
Vue.js 的核心是一個允許採用簡潔的模板語法來聲明式地將數據渲染進 DOM 的系統:
<div id="app"> {{ message }} </div> var app = new Vue({ el: '#app', data: { message: 'Hello Vue!' } })
頁面:
Hello Vue!
除了文本插值,我們還可以像這樣來綁定元素特性:
<div class="container" id="myapp"> <h1 v-bind:title="message">123</h1> </div> <script type="text/javascript"> let app =new Vue({ el:'#myapp', data:{ message:"頁面加載於"+new Date().toLocaleString() }, methods:{ } }) </script>
可以檢查元素,看到:
<h1 title="頁面加載於2018/10/9 下午4:46:24">123</h1>
除了title,其他的id,href等等html元素屬性都可以去bind
-
條件與循環
使用v-if可以控制切換一個元素是否顯示也相當簡單:
<h1 v-if="flag">python</h1> let app =new Vue({ el:'#myapp', data:{ flag:true }, methods:{ } })
在控制檯輸入:
app.flag=false;
頁面上的python就會消失
使用v-for 指令可以綁定數組的數據來渲染一個項目列表:
<ul> #:id是v-bind:id的縮寫,v-text相當於innertext,v-html相當於innerhtml <li v-for="tool in tools" :id="tool.id" v-text="tool.title"></li> </ul> <script type="text/javascript"> let app =new Vue({ el:'#myapp', data:{ tools:[ {"id":"001","title":"vue"}, {"id":"002","title":"js"}, ] } }) </script>
-
用戶交互
爲了讓用戶和你的應用進行交互,我們可以用 v-on 指令添加一個事件監聽器,通過它調用在 Vue 實例中定義的方法:
<h1 v-text="showText"></h1> <button v-on:click="reversed">逆轉</button> #也可以使用@click <button @click="reversed">逆轉</button> let app =new Vue({ el:'#myapp', data:{ showText:"vue" }, methods:{ reversed:function () { this.showText=this.showText.split("").reverse().join("") } } })
v-model的使用
<h1 v-text="showText"></h1> <input type="text" v-model="showText"> let app =new Vue({ el:'#myapp', data:{ showText:"vue" }, })
-
vue組件
組件系統是 Vue 的另一個重要概念,因爲它是一種抽象,允許我們使用小型、獨立和通常可複用的組件構建大型應用。仔細想想,幾乎任意類型的應用界面都可以抽象爲一個組件樹:
Vue.component('job-item',{ template:` <li></li> ` }); <ul> <job-item v-for="tool in tools" v-text="tool.title"></job-item> </ul>
但是這樣會爲每個待辦項渲染同樣的文本,這看起來並不炫酷。我們應該能從父作用域將數據傳到子組件纔對。讓我們來修改一下組件的定義,使之能夠接受一個 prop:
#job-item就是一個組件 #"prop",類似於一個自定義特性。 #這個 prop 名爲 todo。 Vue.component('job-item',{ props:["todo"], template:` <li v-text="todo.title"></li> ` }); <!-- 現在我們爲每個 job-item 提供 todo 對象 todo 對象是變量,即其內容可以是動態的。 我們也需要爲每個組件提供一個“key”,稍後再 作詳細解釋。 --> <ul> <job-item v-for="tool in tools" v-bind:todo="tool" v-bind:key="tool.id"></job-item> </ul>
###以上都是簡單介紹vue.js,下面開始是vue.js正式介紹
-
創建一個vue實例
var app = new Vue({ data:{ flag:true } }) #在app中,下面這三個是相等的 console.log(app.$data.flag); #true console.log(app.flag); #true console.log(this.flag) #true
我們的數據對象可以不用放在data裏面
var tools=[ {"id":"001","title":"vue"}, {"id":"002","title":"js"}, ]; let app =new Vue({ el:'#myapp', data:{ tools:tools, } })
當這些數據改變時,視圖會進行重渲染。值得注意的是只有當實例被創建時 data 中存在的屬性纔是響應式的。也就是說如果你添加一個新的屬性,比如:
app.b = 'hi'
那麼對 b 的改動將不會觸發任何視圖的更新。如果你知道你會在晚些時候需要一個屬性,但是一開始它爲空或不存在,那麼你僅需要設置一些初始值。比如:
data: { newTodoText: '', visitCount: 0, hideCompletedTodos: false, todos: [], error: null }
這裏唯一的例外是使用 Object.freeze(),這會阻止修改現有的屬性,也意味着響應系統無法再追蹤變化。
var obj = { foo: 'bar' } Object.freeze(obj) new Vue({ el: '#app', data: obj }) <div id="app"> <p>{{ foo }}</p> <!-- 這裏的 `foo` 不會更新! --> <button v-on:click="foo = 'baz'">Change it</button> </div>
-
實例生命週期鉤子
每個 Vue 實例在被創建時都要經過一系列的初始化過程——例如,需要設置數據監聽、編譯模板、將實例掛載到 DOM 並在數據變化時更新 DOM 等。同時在這個過程中也會運行一些叫做生命週期鉤子的函數,這給了用戶在不同階段添加自己的代碼的機會。
就是在vue的生命週期內調用一些函數會有一些特殊的作用:
比如 created 鉤子可以用來在一個實例被創建之後執行代碼:
new Vue({ data: { a: 1 }, created: function () { // `this` 指向 vm 實例 console.log('a is: ' + this.a) } }) // => "a is: 1"
不要在選項屬性或回調上使用箭頭函數,比如 created: () => console.log(this.a) 或 vm.$watch(‘a’, newValue => this.myMethod())。因爲箭頭函數是和父級上下文綁定在一起的,this 不會是如你所預期的 Vue 實例,經常導致 Uncaught TypeError: Cannot read property of undefined 或 Uncaught TypeError: this.myMethod is not a function 之類的錯誤。
生命週期圖示:
實例:
beforeCreate:function () { console.log("------beforeCreate-------"); // console.log("this",this); }, created:function () { console.log("------created------"); }, beforeMount:function () { console.log("-------beforeMount------") }, mounted:function () { console.log("------mounted--------") }, beforeUpdate:function () { console.log("------beforeUpdate------"); }, beforeDestory:function () { console.log("---beforeDestory----"); }, updated:function () { console.log("-----updated--------"); } ------beforeCreate------- 數據還沒有監聽,沒有綁定到vue對象實例,同時也沒有掛載對象 ------created------ 數據已經綁定到了對象實例,但是還沒有掛載對象 -------beforeMount------ 模板已經編譯好了,根據數據和模板已經生成了對應的元素對象,將數據對象關聯到了對象的 $el屬性,$el屬性是一個HTMLElement對象,也就是這個階段,vue實例通過原生的createElement等方法來創建這個html片段,準備注入到我們vue實例指明的el屬性所對應的掛載點 ------mounted-------- 將$el的內容掛載到了el,相當於我們在jquery執行了$(el).html($el),生成頁面上真正的dom,上面我們就會發現dom的元素和我們$el的元素是一致的。在此之後,我們能夠用方法來獲取到el元素下的dom對象,並進 行各種操作 當data發生改變時,會調用beforeUpdate和updated方法 在控制檯輸入: app.$destroy() ---beforeDestory---- -----destroyed-------
-
計算屬性和偵聽器
模板內的表達式非常便利,但是設計它們的初衷是用於簡單運算的。在模板中放入太多的邏輯會讓模板過重且難以維護。例如:
<div id="example"> {{ message.split('').reverse().join('') }} </div>
在這個地方,模板不再是簡單的聲明式邏輯。你必須看一段時間才能意識到,這裏是想要顯示變量 message 的翻轉字符串。當你想要在模板中多次引用此處的翻轉字符串時,就會更加難以處理。
所以,對於任何複雜邏輯,你都應當使用計算屬性。
computed:{ reversedMessage:function () { return this.message.split("").reverse().join("") } } <h1 v-text="reversedMessage"></h1> #結果:43:40:9午下 9/01/8102於載加面頁
計算屬性緩存 vs 方法:
兩種方式的最終結果確實是完全相同的。 不同的是計算屬性是基於它們的依賴進行緩存的。 只在相關依賴發生改變時它們纔會重新求值。 這就意味着只要 message 還沒有發生改變,多次訪問 reversedMessage 計算屬性會立即返回之前的計算結果,而不必再次執行函數。
也就是說當計算屬性依賴的值發生變化時,它纔會重新去求值