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