前言
Vue 這個東西很強,聽說不會js的學完后也能用得飛起?就是有點無腦,本文主要意圖是記錄自己學習中的流程和各種疑點,總之它提供給我們有一堆相似的操作,但是要把它用成這個語言該有的樣子,精確到哪個文件夾該放什么文件,形成一種開發的風格、規約,這樣最好不過
剛剛開始學 Vue的時候用的是 傳統的開發方式,把一堆東西塞在 html 頁面里面,或者鏈接來鏈接去的,就像下面這樣:
<!DOCTYPE html>
<html>
<head>
<title></title>
<link rel="stylesheet" type="text/css" href="index.css">
</head>
<body>
<script src="https://cdn.bootcss.com/vue/2.6.10/vue.min.js"></script>
<script type="text/javascript">
// ... BODY
Vue.component('Tree', {
data: function () {
return {
count: 0
}
},
template: '<button v-on:click="count++">You clicked me {{ count }} times.</button>'
})
// ... 過濾器 等等....
new Vue({
data:{
},
methods:{
}
})
</script>
</body>
</html>
這樣在小項目中確實沒啥問題,但是東西越來越大就會有煩惱:
- 全局定義 ,強制要求每個
component
中的命名不得重復- 字符串模板 (String templates) 缺乏語法高亮,在 HTML 有多行的時候,需要用到丑>陋的
\
- 不支持 CSS (No CSS support) 意味著當 HTML 和 JavaScript 組件化時,CSS 明顯被遺漏
- 沒有構建步驟 (No build step) 限制只能使用 HTML 和 ES5 JavaScript, 而不能使用預處理器,如 Pug (formerly Jade) 和 Babel
然后現在又突然用到 單文件組件
,模塊化
,組件化
的開發方式,一時半會有點難受,
但用了一段時間過后:真香
<template>
<div>
</div>
</template>
<script>
export default {
name: 'test',
};
</script>
<style scoped>
</style>
至此組件更加內聚,低耦合
Vue cli 2.x版本構建項目目錄一覽
以下皆為
Vue cli
命令構建的項目,Vue cli 命令:
vue ui
Vue cli 4.x版本構建項目目錄一覽
關于static
,assets
文件夾
相同點:資源在html中使用,都是可以的。
不同點:使用assets下面的資源,在js中使用的話,路徑要經過webpack中loader編譯,路徑不能直接寫。static里面的文件build
后只是復制一遍,路徑要寫絕對路徑注意:在動態的綁定上面,使用assets中的資源會加載失敗,因為webpack使用的是
commenJS
規范,必須使用require
才可以(在運行時動態的決定請求哪一個資源進來)
總結:
static
中放別人的庫(建議放一些外部第三方)
assets
中放自己的資源
關于compoents
,views
文件夾
在之前的 vue cli2.x 中我還沒有發現有個 views 的文件夾,現在多了一個,所以就百度了下:
然后又扯到了一個
containers
文件夾
總結:
components
中是推薦放常用的一些小組件,這些組件將來可能被復用到很多個地方,
views
中推薦放頁面級的組件,按照它的命名,可以想到是各個視圖,一般views組件不被復用
containers
屬于容器級組件,根據項目大小決定是否使用
關于生命周期函數
我非常好奇的是,為什么要把
outerHTML
翻譯成外部的HTML
,不應該是內部的嘛?然后我看了下中文的vue.js文檔,看到里面的直接翻譯,我驚了!!!
vue的.png
這難到不是對新手理解及其不友好?前輩的直接翻譯,是真的
n p
然后我又查了 MDN,還在一些框架中看到outerHTML 的字樣,它們的功能都是如此:
outerHTML屬性用來設置或者返回元素本身以及其后代HTML內容
這就好像我剛入門編程的時候,接觸到的英文教材上面的
context
,直接被翻譯成了上下文
,那不分明就是執行調用時,入棧的時候有個執行體么?用來保持里面的結構,數據等等......
Vue 組件的三大組成部分
template 模板:
<template>
<div id="app"> <!--根標簽-->
{{mseeage}} <!--插值語句-->
</div>
</template>
每個模板要求有一個
container
容器 (必須要有一個根標簽,span
,p
等等內聯元素都行)
script 腳本:
<script>
export default {
name:'app',
data(){
return{
arr:[]
}
},
components:{
...
}
...
}
</script>
在模塊化編程中 data 需要是一個函數且返回一個對象,而不是單純的
key
,value
components 中的 組件名稱命名請參考 Vue 官方風格指南
style 樣式表:
<style>
...
</style>
v-bind 動態綁定標簽屬性
<div id="app" v-bind:title="titleName">
{{msg}}
</div>
<!--簡寫為:-->
<div id="app" :title="titleName">
{{msg}}
</div>
Vue 插值語句
<span>Message: {{ msg }}</span>
export default{
data(){
return:{
msg:666
}
}
}
v-on: 事件觸發
<div id="app" v-on:click="test">
{{msg}}
</div>
<!--省略為 @click-->
<div id="app" @click="test">
{{msg}}
</div>
可以將
on
縮寫為@
,比如@keyup
,@click
,@mousemove
v-model 觀察者模式實現的雙向綁定
<template>
<input type="text" v-model="name" />
</template>
<script>
export default {
data(){
return{
name:''
}
}
}
</script>
在input 中輸入內容,vue組件實例中的屬性馬上響應發送改變,牽一發而動全身
常用指令
https://cn.vuejs.org/v2/api/#%E6%8C%87%E4%BB%A4
computed 計算屬性(它是屬性)
<div id="app-name">
<input type="text" name="" v-model="firstname">
<input type="text" name="" v-model="lastname">
<input type="text" name="" v-model="fullname">
</div>
const vm = new Vue({
el:'#app-name',
data:{
//普通屬性
firstname:'Will',
lastname:'Smith',
},
computed:{
// 計算屬性
fullname:{
get(){
return this.firstname +' '+ this.lastname;
},
set(value){
const names = value.split(' ');
this.firstname = names[0];
this.lastname = names[1];
}
}
}
});
被初始化的時候調用一次 參考生命周期示意圖
不定義
get()
,set()
時fullname
中的執行體(context
)為get
時觸發計算屬性內部與 data 中有相關聯的值也會觸發(當相關聯的值發送改變的時候)
vue 知道 計算屬性
fullname
依賴于 普通屬性firstname
,lastname
,當它們兩個中的任意一個發生改變時,``fullname的
set`被觸發
想觀察值發生的變動并且及時作出反應時,使用 computed,適合將普通屬性中復雜一點的邏輯寫在里面
watch 偵聽器(是一個監視者)
<template>
<div>
<el-input v-model="demo"></el-input>
{{value}}
</div>
</template>
<script>
export default {
name: 'index',
data() {
return {
demo: '',
value: ''
};
},
watch: {
demo(newval,oldval) {
this.value = this.demo;
}
}
};
</script>
watch 是一個屬性,用來監視 (
data
)列表中的普通屬性
一旦被檢測的
普通屬性
的值發生變化,watch 可以捕獲到修改還可以用來監視 路由的變化 (
'$route'(to,from){ }
)
computed、watch、methods 比較
大佬文章 https://blog.csdn.net/zhouzy539/article/details/96340814
vue.js 官網給出 computed 與 methods 的答案是:computed 會緩存結果
普通函數中這樣定義:
methods:{
now:function(){
return Date.now()
}
}
我稍微將官網的例子修改了下,這樣方便我理解,對比一下下面的 computed 中的計算屬性 now:
每次手動調用都是新的 Date 值
在計算屬性中這樣定義:
computed: {
now: function () {
return Date.now()
}
}
$vm.now 始終返回了初始化完成時候的值,既緩存了結果
假設我們有一個性能開銷比較大的計算屬性 A,它需要遍歷一個巨大的數組并做大量的計算。然后我們可能有其他的計算屬性依賴于 A 。如果沒有緩存,我們將不可避免的多次執行 A 的 getter!如果你不希望有緩存,請用方法來替代。
w3plus上的總結:
methods
:正如他的名字一樣,它們是掛載在對象上的函數,通常是Vue實例本身或Vue組件。computed
:屬性最初看起來像一個方法,但事實卻又不是方法。在Vue中,我們使用data
來跟蹤對特定屬性的更改,得到一定的反應。計算屬性允許我們定義一個與數據使用相同方式的屬性,但也可以有一些基于其依賴關系的自定義邏輯。你可以考慮計算屬性的另一個視圖到你的數據。watchers
:這些可以讓你了解反應系統(Reactivity System)。我們提供了一些鉤子來觀察Vue存儲的任何屬性。如果我們想在每次發生變化時添加一些功能,或者響應某個特定的變化,我們可以觀察一個屬性并應用一些邏輯。這意味著觀察者的名字必須與我們所觀察到的相符。對于w3plus的總結我的理解:
methods
:和computed寫得一樣的功能來用完全沒毛病,自己手動調用computed
:可以在數據變化的時候自己調用,處理復雜的邏輯,上面的加粗關鍵詞[自定義]watchers
: 把它用成它改有的樣子,比如 實現特定的功能、產生特定的邏輯,newvalue
與oldvalue
比較,反應系統一詞,我理解為,我們可以把
watchers
定義為普通屬性
的鉤子函數
,在它數據發送改變后,我們做點什么
小小總結:
watch
擅長處理的場景:一個數據影響多個數據
computed
擅長處理的場景:一個數據受多個數據影響相比于watch/computed,
methods
不處理數據邏輯關系,只提供可調用的函數
class 與 style 動態綁定
<div id="app-name" class="per" :class="a"></div>
<script>
const vm = new Vue({
el:'#app-name',
data:{
a:'aClass'
}
});
</script>
在瀏覽器中顯示為:
<div id="app-name" class="per aClass"></div>
可取值為:String
,Object
,Array
<div id="app-name">
<p :class="a">class is string </p>
<p :class="{aClass:true , bClass:false}">class is string </p>
<p :class="['aClass','bClass']">class is array </p>
</div>
字符串值會在組件實例的 普通屬性和計算屬性中查找
對象值為
key:value
,value 標識為true
時才起作用數組值:按照排列順序起作用,
注意:即使是 <p :class="['a','b']" class="c"> 這樣寫
還是 顯示為 <p class="c a b"> 的覆蓋順序。
另外 <p :class="['a','b']" class="a"> 是不會報錯的
:style=
用法一致,不過表現為這樣:
data(){
return{
newStyle:{
color:'red',
border:'1px solid blue'
}
}
}
Vue 條件渲染 ,v-if/else
, v-show
先看v-if/else
:
<div id="app-name">
<p v-if="isLive">存活</p>
<p v-else="isLive">死亡</p>
<button @click="isLive=!isLive">switch</button>
</div>
const vm = new Vue({
el:'#app-name',
data:{
isLive:false
}
});
改寫成 v-show
<div id="app-name">
<p v-show="isShow">顯示</p>
<p v-show="isShow">不顯示</p>
<button @click="show">switch</button>
</div>
const vm = new Vue({
el:'#app-name',
data:{
isShow:false
},
methods:{
show(){
this.isShow = !(this.isShow)
}
}
});
兩者相同點:
- 功能一樣
兩者不同點:
v-if else
是 移除與創建元素,需要通過內存來創建v-show
是在頁面中 決定該元素的display
來進行切換的
總結:頻繁切換的情況下使用
v-show
比較好
Vue 列表渲染
以前是通過先在頁面上寫好靜態的 布局,然后設置
css
,class
,然后再在js中用語句動態的循環data.length
次,使勁的createElement
,setAttribute
,appendChild
, 現在舒服了
<div id="test">
<ul>
<li v-for="(p,index) in filterPersons)" :key="index">{{p.name}}--{{p.age}}</li>
</ul>
</div>
new Vue({
el:'#test',
data:{
persons:[
{name:'Bob',age:18},
{name:'Jack',age:22},
{name:'Anna',age:23}
],
}
}
固定的搞法,
v-for="(p,index) in filterPersons)" :key="index"
for...in
是用key
來遍歷的,遍歷對象合適不過index
為附加定義的一個唯一下標值:key
作為該元素的唯一標識,注意key
相同時會拋出錯誤,(可能會引起更新錯誤)
Vue 單個組件的調試
先安裝
npm install -g @vue/cli-service-global
再使用命令 vue serve
后面是具體的路徑下的組件
vue serve src/components/Test.vue