小型項目 就可使用 vue 就高度了 隨着頁面的複雜程序提升,就要學習 vue-rouer 來管理更多的頁面 再隨着項目的數據愈來愈多,管理數據也變得麻煩起來了,就開始使用 vuex 來管理數據javascript
3.2 框架 : 一整套的解決方案php
好比 : 想要添加樣式, 就調用 jquery 中的 .css() / .addClass()css
好比 : 想給 A:設置樣式 A.css(), B:addClass() C:style.background='red'
html
####2. 框架 (Framework), 表明:vue前端
好比 : 想用vue,組件裏遍歷就得使用 v-for, 下次不用 v-for 了,使用 for 不行 v-for='item in list'vue
也就是 : 誰起到了主導做用java
Vue 使用的是 MVVM 模式node
頻繁的操做DOM
數據雙向綁定
讓數據自動的雙向同步
每一個人操做 DOM 的方法不同,會形成性能不同 官網 : 雖然沒有徹底遵循 MVVM 模型,可是 Vue 的設計也受到了它的啓發。所以在文檔中常常會使用 vm (ViewModel 的縮寫) 這個變量名錶示 Vue 實例。jquery
npm i vue
(小寫)<script src='./vue.js'></script>
const vm = new Vue({
// 指定 vue 管理的邊界
el: '#app',
// 提供視圖中 須要的數據
// 視圖能夠直接使用data中的數據
data: {
msg: 'xxx'
}
})
複製代碼
{{}}
從data
中獲取數據,並展現在模板中{{}}
中只能出現 js 表達式1 'abc' false [] {}
1+2 arr.join('-') true ? 123 : 321
if語句 for語句
v-model 指令 : 數據雙向綁定的指令
做用 : 把data中的msg值 和 input上的值 綁定到一塊兒
注意 : v-model只能用在 表單控件上 (input checkbox 等)
> 能夠在瀏覽器分別演示 V => M 和 M =>V
複製代碼
let obj = {}
let temp
obj.name = 'zhanhgsan'
// 參數1 : 要給哪一個對象設置屬性
// 參數2 : 給對象設置什麼屬性
// 參數3 : 屬性的修飾符
Object.defineProperty(obj, 'name', {
set: function(newVal) {
console.log('賦值了', newVal)
},
get: function() {
console.log('取值了')
return temp
}
})
複製代碼
<input type="text" id="txt" />
//1. 拿到文本框
const txt = document.getElementById('txt')
//2. 時刻監聽txt ,拿到最新的值
txt.oninput = function() {
console.log(this.value)
obj.name = this.value
}
//3. 數據模型
var obj = {}
let temp
Object.defineProperty(obj, 'name', {
// 給屬性賦值的時候會掉
set: function(newVal) {
console.log('調用了set', newVal)
temp = newVal
txt.value = newVal
},
get: function() {
console.log('調用了get')
return temp
}
})
複製代碼
//1. 獲取 input的值,最新值
//2. 經過監聽oninput 拿到最新值
//3. 把最新值賦值給 obj.name
//4. 就會掉了set方法,就會修改了數據
複製代碼
//1. obj.name = 'xxx'
//2. 調用 set方法
//3. 把值賦值給input元素
複製代碼
說明 : 用在
表單
元素中, 用來實現數據雙向綁定
(input checkbox 等等) 做用 : 將數據txt
和文本框的值
綁定到一塊兒, 任何一方發生改變,都會引發對方的改變 注意 : v-model 在不一樣類型的表單元素中,該指令的做用不一樣webpack
<!-- 文本輸入框 綁定的是值 -->
<input type="text" v-model="txt" />
<!-- 多選框、按鈕 綁定的選中狀態 -->
<input type="checkbox" v-model="isChecked" />
複製代碼
說明 : 設置文本內容
msg1: '<a>這是一條信息</a>',
msg2: '<a href="#">我也是一條信息</a>'
複製代碼
說明 : 動態綁定數據 (單向) 出現緣由 : 在 HTML 屬性中, 沒法使用插值表達式 步驟:
// 加載靜態數據
<a href="https://wbaidu.com">aaa</a>
// 想加載動態數據 {{ }}能夠獲取data中的數據
// 可是 {{}} 不能使用在屬性中
<a href="{{ src }}">aaa</a>
// 因此使用v-bind
<a v-bind:href="{{ src }}">aaa</a> ok
<img v-bind:src="src"> ok
複製代碼
縮略 : v-bind 所有省略 只留下一個
:
改成 :
<a :href="src">aaa</a> ok
<img :src="src" /> ok
複製代碼
之後 使用 靜態加載數據 :
<a href="https://wbaidu.com">aaa</a>
動態加載數據 :<a :href="href">aaa</a>
// v-model : 數據雙向綁定 表單元素上
// : : 動態綁定數據(單向) 任意元素動態讀取屬性
容易出錯點 :
<!-- v-model 數據雙向綁定 -->
<!--場景 : 表單元素中 -->
<input type="checkbox" v-model="isChecked1" /> <br />
<!-- v-bind 數據動態綁定 (單向) -->
<!--場景 : 主要用在屬性中 -->
<input type="checkbox" :checked="isChecked2" />*
複製代碼
1.操做樣式
<!-- 1. 靜態類名 -->
<h1 class="red">哈哈</h1>
<!-- 2. 動態類名 -->
<h1 :class="cls">哈哈</h1>
<!-- 3. 最經常使用 -->
<!-- :class 裏的值是一個對象 鍵 : 類名 (可能會要,也能夠不要) 值 : 布爾值, true/false 肯定類要不要 -->
<h1 :class="{ red:isRed , fz:isFZ}">哈哈</h1>
<!-- 4. style -->
<h1 :style="{ color : 'red', fontSize : fz + 'px' }">哈哈</h1>
複製代碼
2.其餘操做
<!-- 1 -->
<!-- 重點 -->
<div :class="{ active: true }"></div>
===>
<div class="active"></div>
<!-- 2 -->
<div :class="['active', 'text-danger']"></div>
===>
<div class="active text-danger"></div>
<!-- 3 -->
<div :class="[{ active: true }, errorClass]"></div>
===>
<div class="active text-danger"></div>
--- style ---
<!-- 1 -->
<h1 :style="{ color : 'red', fontSize : fz + 'px' }">哈哈</h1>
<!-- fz : 80 -->
<!-- 2 將多個 樣式對象 應用到一個元素上-->
<!-- baseStyles 和 overridingStyles 都是對象 -->
<!-- 若是有相同的樣式,之後面的樣式爲準 -->
<div :style="[baseStyles, overridingStyles]"></div>
複製代碼
註冊事件/綁定事件
v-on:click 綁定了一個單擊事件
: 後面是事件名稱
<button v-on:click="fn">按鈕</button>
複製代碼
縮寫 : @click='fn' <button @click='fn'>按鈕</button>
函數寫在 methods
裏面
fn : function(){ ... }
fn() { ... }
複製代碼
> 在函數裏面操做數據
- 獲取數據 this.msg
- 修改數據 this.msg = 'XXX'
複製代碼
@click='fn(123)'
複製代碼
5.2 事件對象 $event
<!-- 4.1 綁定事件對象的時候, 沒有添加小括號,此時,直接在方法中,經過參數 e 就能夠獲取到事件對象 -->
<!-- 4.2 若是添加小括號,就拿不到事件對象了,vue留了一個$event -->
<button @click="fn1($event,123)">我是按鈕</button>
複製代碼
<!-- 需求1 : 最經常使用 遍歷數組 -->
<!-- 做用 : 遍歷 list1 數據, 爲數據中的每一項生成一個li標籤 -->
<!-- item 數組裏的每一項元素 -->
<ul>
<li v-for="(item,index) in list1">{{ item }} - {{ index }}</li>
</ul>
<!-- 需求2 : 遍歷元素是對象的數組 -->
<ul>
<li v-for="item in list2">{{ item.name }} - id:{{ item.id }}</li>
</ul>
<!-- 需求3 : 遍歷對象 -->
<ul>
<li v-for="(item,key) in obj">{{ item }}-{{key}}</li>
</ul>
<!-- 需求4 : 想要生成10個h1 -->
<h1 v-for="item in 10">我是h1 {{ item }}</h1>
複製代碼
重點是遍歷數組,,其餘的瞭解便可
注意用v-for更新已經渲染過的元素列表的時候,他會默認就地複用策略,若是數組的順序發生改變,vue不會必定dom元素來匹配順序,而是簡單的複用此處的每一個元素,這樣每一個節點的狀態就會對應不上
解決這時候就須要給每一個列表元素提供一個key
,這個key
須要是惟一的,以保證vue能準確的追蹤到每一個節點,key
最好是列表中每項的id
###一 : 準備工做
演示效果 :
當前任務:敲代碼、視頻、遊戲
git clone https://github.com/tastejs/todomvc-app-template.git
安裝依賴包 : npm i
安裝 vue : npm i vue
導入 vue : <script src="./node_modules//vue/dist/vue.js"></script>
在
index.html
裏的app.js
導入以前導入,由於 app.js 裏 就要用到 vue 了
實例化 vue :在app.js
中建立 vue 示例,並設置好邊界 el:'#app'
找到 index.html ,給 section 標籤添加一個 id
測試 vue :
data 中隨便來一個 msg 看能不能顯示到視圖中
這裏先甩一張圖
![](D:\study\筆記\個人整理\images\vue\Vue實例生命週期圖 - 新版.png)
#####注意 :
生命週期鉤子函數
, 咱們只須要提供這些鉤子函數便可說明 : 在實例初始化以前,數據觀測 和 event/watcher 事件配置以前被調用
組件實例剛被建立,組件屬性計算以前, 例如 data 屬性 methods 屬性
注意 : 此時,沒法獲取 data 中的數據 和 methoids 中的方法
場景 : 幾乎不用
說明 : 組件實例建立完成,屬性已綁定, 能夠調用 methods 中的方法、能夠獲取 data 值
使用場景 : 1-發送 ajax 2-本地存儲獲取數據
beforeCreate() {
// 沒法獲取數據和事件
console.warn('beforeCreate', this.msg, this.fn)
},
created() {
console.warn('created', this.msg, this.fn)
},
複製代碼
vm.$mount(el)
去指定邊界vm.$mount('#app')
複製代碼
template
option?// 若是提供了 template, 那麼 vue 就會將 template 的內容進行編譯,編譯後,替換頁面中 vue 管理的邊界
template : ` <h1>嘻嘻</h1> `,
複製代碼
說明 : 掛載以後, DOM 完成渲染
使用場景 : 1-發送 ajax 2-操做 DOM
記得把template去掉
// 渲染DOM以前
beforeMount() {
// 渲染以前的 <h1 id="h1" @click="fn">{{ msg }}</h1>
console.log(document.getElementById('h1'))
},
// 渲染DOM以後 <h1 id="h1">測試</h1>
mounted() {
console.log(document.getElementById('h1'))
}
複製代碼
說明:數據更新時調用,發生在虛擬 DOM 從新渲染和打補丁以前。你能夠在這個鉤子中進一步地更改狀態,這不會觸發附加的重渲染過程。
注意:此處獲取的數據是更新後的數據,可是獲取頁面中的 DOM 元素是更新以前的
小提示 : 打印 this.$el ,打開小三角是以後的,是由於打印是有監聽的功能,展現的是後面更改以後的
說明:組件 DOM 已經更新,因此你如今能夠執行依賴於 DOM 的操做。
beforeUpdate() {
// 更新以前的值 : 信息
console.warn('beforeUpdate', document.getElementById('h1').innerText)
},
updated() {
// 更新以後的值 : 信息1111
console.warn('updated', document.getElementById('h1').innerText)
}
複製代碼
created() {
this.timerId = setInterval(() => {
console.log(1111);
}, 500);
},
// 若是當組件銷燬了,還不清除定時器會出現性能問題
// 在瀏覽器中能夠嘗試銷燬 vm.$destroy()
// 最後銷燬
beforeDestroy() {
clearInterval(this.timerId)
},
複製代碼
說明:Vue 實例銷燬後調用。調用後,Vue 實例指示的全部東西都會解綁定,全部的事件監聽器會被移除,全部的子實例也會被銷燬。
created {
this.list = localStorage.getItem('list')
}
複製代碼
json-server 做用 : 根據指定的 JSON 文件, 提供假數據接口
地址 : json-server
使用步驟
1. 全局安裝 json-server : `npm i -g json-server`
2. 準備一個json數據
3. 執行 : `json-server data.json`
> json數據參考
json數據能夠參考 :
{
"todos": [
{
"id": 1,
"name": "吃飯",
"age": 20
}
]
}
複製代碼
REST API 格式
* 1. 查詢 : GET
* 2. 添加 : POST
* 3. 刪除 : DELETE
* 4. 更新 : PUT 或者 PATCH(打補丁)
複製代碼
* 1. 查詢所有數據 http://localhost:3000/todos
* 查詢指定數據 http://localhost:3000/todos/2
*
* 2. 添加一個對象 //localhost:3000/todos
* POST
* id 會自動幫咱們添加
*
* 3. 更新數據 http://localhost:3000/todos/3
* PUT 或者 PATCH
* PUT 須要提供該對象的全部數據
* PATCH 只須要提供要修改的數據便可
*
* 4. 刪除數據
* http://localhost:3000/todos/3
* DELETE
複製代碼
postman
測試接口;讀音 : /艾克笑絲/
做用 : 一個專門用來發送 ajax 請求的庫, 能夠在瀏覽器或者 node.js 中使用
Promise based HTTP client for the browser and node.js
以Promise爲基礎的HTTP客戶端,適用於:瀏覽器和node.js
封裝ajax,用來發送請求,異步獲取數據
複製代碼
使用步驟
1. 本地安裝 axios : `npm i axios`
2. 導入 axios
3. 使用
複製代碼
GTE 方式發送請求
// 方式1
axios.get('http://localhost:3000/todos/3').then(res => {
console.log('獲取到數據了:', res.data)
})
// 方式2
axios
.get('http://localhost:3000/menus', {
params: {
id: 003
}
})
.then(res => {
console.log('獲取到數據了:', res.data)
})
複製代碼
五、 POST 方式發送請求
// post 請求
axios
// 第一個參數:表示接口地址
// 第二個參數:表示接口須要的參數
.post('http://localhost:3000/todos', {
name: 'axios添加數據',
done: true
}).then ( res => 打印 res)
複製代碼
使用axios測試 todos 的幾種接口
//1. GET
// 沒有參數
axios.get('http://localhost:3000/todo').then(res => {
console.log(res)
})
// 有參數
axios.get('http://localhost:3000/todo/1').then(res => {
console.log(res)
})
axios
.get('http://localhost:3000/todo', {
params: {
id: 2
}
})
.then(res => {
console.log(res)
})
// 2. POST
axios
.post('http://localhost:3000/todo', {
name: 'XXX',
age: 1
})
.then(res => {
console.log(res)
})
//3. 刪除
axios.delete('http://localhost:3000/todo/8', {}).then(res => {
console.log(res)
})
//4. 更新 - put
axios
.put('http://localhost:3000/todo/2', {
name: '111',
age: 300
})
.then(res => {
console.log(res)
})
// 4. 更新 - patch
axios
.patch('http://localhost:3000/todo/1', {
age: 3000
})
.then(res => {
console.log(res)
})
複製代碼
獲取所有
axios.get('http://localhost:3000/list').then(res => {
console.log(res.data);
this.list = res.data;
});
複製代碼
刪除任務
axios.delete('http://localhost:3000/list/' + id).then(res => {
this.list = this.list.filter(item => item.id !== id);
console.log(res);
});
複製代碼
添加任務
# id 會自動加
axios
.post('http://localhost:3000/list', {
name: todoName,
done: false
})
.then(res => {
console.log(res.data);
this.list.push({
// 屬性名 和屬性值 同樣的話,,能夠省略一個
id,
name: todoName,
done: false
});
});
複製代碼
更新任務 (在 hideEdit 裏實現)
# 難點1 : 在 hideEdit 這個方法裏
# 難點2 : 獲取的這個id 就是editId
hideEdit(e) {
axios.patch('http://localhost:3000/list/' + this.editId, {
name: e.target.value
}).then(res => {
console.log(res);
this.editId = -1;
})
},
複製代碼
刪除已經完成 的
# 由於 這個假接口沒有實現如下刪除 完畢
clearCompleted() {
// 清除已經完成的,,只須要過濾出來未完成的便可
let arr = this.list.filter(item => item.done);
arr = arr.map(item => item.id);
for (let i = 0; i < arr.length; i++) {
axios.delete('http://localhost:3000/list/' + arr[i]).then(res => {
this.list = this.list.filter(item => item.id != arr[i]);
});
}
},
複製代碼
點擊修改狀態
# 單獨給 checkbox 都註冊點擊事件
clickBox(id) {
let todo = this.list.find(item => item.id == id);
axios.patch('http://localhost:3000/list/' + id, {
done: !todo.done
}).then(res => {
console.log(res);
});
}
複製代碼
單頁web應用,
就是隻有一個web頁面的應用,
是加載單個HTML頁面,
並在用戶與應用程序交互時動態更新該頁面的web應用程序
複製代碼
對於傳統的多頁面應用程序來講, 每次請求服務器返回的都是一個完整的頁面
對於單頁應用程序來講,
只有第一次會加載頁面,
之後的每次請求,
僅僅是獲取必要的數據.而後,
由頁面中js解析獲取的數據,
展現在頁面中
複製代碼
Vue 中的兩種註冊組件的方法 1.全局註冊 2.局部註冊
全局組件在全部的vue實例中均可以使用
局部組件在全部的當前實例中可使用
複製代碼
/** * 第一個參數 : 組件名 * 第二個參數 : 是一個配置對象, 該配置對象與 Vue 實例的配置對象幾乎徹底相同 * 也就是說: vue實例中用到的配置項,和組件中的配置項幾乎相同 */
Vue.component('hello', {
template: ` <h1 class="red">這是hello組件</h1> `
})
複製代碼
var Component = function() {}
// 使用對象
Component.prototype.data = {
demo: 123
}
// 使用函數
Component.prototype.data = function() {
return {
demo: 111
}
}
var component1 = new Component()
var component2 = new Component()
component1.data().demo = '8888'
console.log(component2.data().demo) // 456
複製代碼
示例:
<h1 @click='fn' class="red">這是hello組件</h1>
methods: {
fn() {
console.log('fn')
}
},
computed: {},
watch: {},
filters: {}
}
複製代碼
todo-head.js
<script src="./components/todo-head.js"></script>
<todo-head></todo-head>
<child :msg="pmsg"></child>
複製代碼
props: ['msg']
複製代碼
完善 TodoMVC => 完成 傳值 + 渲染列表頁
1 父組件中提供一個方法
pfn(arg) {
console.log('父組件中接受到子組件傳遞過來的數據:', arg)
}
複製代碼
2 將這個方法傳遞給子組件
// 自定義事件 <child @fn="pfn"></child>
複製代碼
3 子組件調用這個方法( 觸發父組件中傳遞過來的自定義事件 )
// 這個方法是點擊事件觸發的
handleClick() {
// 調用父組件中的方法 fn
// 注意:經過 $emit 方法來觸發事件 fn
// 第一個參數:表示要觸發的自定義事件名稱,也就是 @fn
// 第二個參數:表示要傳遞給父組件的數據
this.$emit('fn', 'child msg')
}
複製代碼
完善 TodoMVC => 完成 傳值 +添加+ 刪除+清除完成
全部的 prop 都使得其父子 prop 之間造成了一個
單向下行綁定
:父級 prop 的更新會向下流動到子組件中,可是反過來則不行。這樣會防止從子組件意外改變父級組件的狀態,從而致使你的應用的數據流向難以理解。 看圖 當 todo-head 中的 todoName 設置數據後回車添加到 todoList,todoList 的長度就會發生變化, 而後就會根據(組件與組件之間的)單向數據流,把數據單向下流到子組件中 並且必須是經過 props 往下傳遞的才能夠
驗證 props 只讀
正常下是不須要子組件修改父組件傳過來的值的,可是.....
修改父組件傳給子組件的
數據
思路 : 把接收過來的數據,保存到 data 中一個臨時值
Vue.component('child', {
template: ` <div>子組件 {{ cmsg }} </div> `,
data() {
return {
cmsg: this.msg
}
},
props: ['msg'],
created() {
this.cmsg = 666
}
})
複製代碼
官 : HTML 中的特性名是大小寫不敏感的,因此瀏覽器會把全部大寫字符解釋爲小寫字符。
html 的標籤和 屬性 都是同樣,忽略大小寫
<H1 TITLE="哈哈">我是h1</H1>
官 : 這意味着當你使用 DOM 中的模板時,camelCase (駝峯命名法) 的 prop 名很差使了
<child :cMsg="pmsg"></child>
會報警告,父傳子也接收不到了You should probably use "c-msg" instead of "cMsg".
方式 1 : 全用小寫,不要使用駝峯命名
接收 :
cmsg
props/讀取 :cmsg
方式 2 官 : 須要使用其等價的 kebab-case (短橫線分隔命名) 命名:
接收 :
:c-msg='pmsg'
props/讀取 :cMsg
計算屬性 : 已知值(todoList 在 根組件) ==> 獲得一個新值(子組件裏使用)
父 => 子通信
需求 : 組件 jack ===> 恁弄啥哩 ===> 組件 rose
事件總線 (event bus 公交車) 的機制
來實現的空Vue實例
// 第一步 : 事件總線
var bus = new Vue()
// 第二步 : 發送數據 可在點擊事件裏 觸發事件
// 參數1 : 惟一標識 參數2:參數
bus.$emit('todo', '恁弄啥哩?')
// 第三步 : 接收數據 可在 created 裏 註冊事件
bus.$on('todo', arg => {
console.log('接收過來的', arg)
})
複製代碼
// 註冊局部組件:
components: {
// child表示組件名稱
// 值爲配置對象,與 Vue.component 中的第二個參數相同
// 注意:子組件child屬於 Vue實例,所以,只能在 Vue實例的模板中使用
child: {
template: ` <div>這是局部組件 child</div> `
}
}
複製代碼
說明 : vm.$refs
一個對象, 持有已註冊過 ref 的全部子組件 ( HTML 元素)
使用 :
// 標籤
<div ref="div">哈哈</div>
// 組件
<child ref="child"></child>
複製代碼
// mounted 操做DOM
* this.$refs.div
* this.$refs.child
複製代碼
注意點 : 若是獲取的是一個子組件,那麼經過 ref 就能獲取到子組件中的 data
和 methods
this.$refs.child.num
this.$refs.child.fn
複製代碼
場景 : 通常在第三方的組件中, 可能會用到這個功能
示例 :
// 組件
<div ref="div">哈哈</div>
<child ref="child"></child>
// js
mounted() {
console.log(this.$refs.div)
console.log(this.$refs.child.fn)
}
複製代碼
單頁web應用,
就是隻有一個web頁面的應用,
是加載單個HTML頁面,
並在用戶與應用程序交互時動態更新該頁面的web應用程序
複製代碼
對於傳統的多頁面應用程序來講, 每次請求服務器返回的都是一個完整的頁面
對於單頁應用程序來講,
只有第一次會加載頁面,
之後的每次請求,
僅僅是獲取必要的數據.而後,
由頁面中js解析獲取的數據,
展現在頁面中
複製代碼
哈希值
( # hash) 與 展現視圖內容
之間的對應規則
在 web App 中, 經過一個頁面來展現和管理整個應用的功能.
SPA 每每是功能複雜的應用,爲了有效管理全部視圖內容,前端路由 應運而生. (爲何要學習路由??)
簡單來講,路由就是一套映射規則(一對一的對應規則), 由開發人員制定規則.
當 URL 中的哈希值( `#` hash) 發生改變後,路由會根據制定好的規則, 展現對應的視圖內容
複製代碼
npm i vue-router
<script src="./vue.js"></script>
// 千萬注意 :引入路由必定要在引入vue以後,由於vue-router是基於vue工做的
<script src="./node_modules/vue-router/dist/vue-router.js"></script>
複製代碼
3.0 實例路由對象+掛載到 vue 上
const router = new VueRouter() 路由實例 與 Vue 實例 關聯到一塊兒 驗證路由是否掛載成功, 就看打開頁面,最後面有沒有個
#/
3.1 入口 (#哈希值)
// 方式1 : url地址爲入口 調試開發用
輸入url地址 改變哈希值
`01-路由的基本使用.html#/one`
// 方式2 : router-link+to
複製代碼
// path : 路由路徑
// component : 未來要展現的路由組件
routes: [{ path: '/one', component: One }, { path: '/two', component: Two }]
複製代碼
3.3 組件
一個哈希值對應一個組件
const One = Vue.component('one', {
template: ` <div> 子組件 one </div> `
})
複製代碼
<!-- 出口 組件要展現的地方-->
<router-view></router-view>
複製代碼
<!-- 1. 入口 -->
<!-- to 屬性 , 實際上就是哈希值,未來要參與路由規則中進行與組件匹配 router-link 組件最終渲染爲 : a標籤, to屬性轉化爲 a標籤的href屬性 -->
<router-link to="/one">首頁</router-link>
複製代碼
組件
組件能夠改成對象格式
const One = {
template: ` <div> 子組件 one </div> `
}
複製代碼
過程 : 入口 ==> 路由規則 ==> 組件 ==> 出口
演示 : 多個組件匹配
能夠有多個入口,但只須要一個出口
示例 :
<div id="app">
<!-- 1 路由入口:連接導航 -->
<router-link to="/one">One</router-link>
<router-link to="/two">Two</router-link>
<!-- 4 路由出口:用來展現匹配路由視圖內容 -->
<router-view></router-view>
</div>
<!-- 導入 vue.js -->
<script src="./vue.js"></script>
<!-- 導入 路由文件 -->
<script src="./node_modules/vue-router/dist/vue-router.js"></script>
<script>
// 3 建立兩個組件
const One = Vue.component('one', {
template: '<h1>這是 one 組件</h1>'
})
const Two = Vue.component('two', {
template: '<h1>這是 two 組件</h1>'
})
// 0 建立路由對象
const router = new VueRouter({
// 2. 路由規則
routes: [
{ path: '/one', component: One },
{ path: '/two', component: Two }
]
})
const vm = new Vue({
el: '#app',
//0. 不要忘記,將路由與vue實例關聯到一塊兒!
router
})
</script>
複製代碼
<a href="#/one" class="router-link-exact-active router-link-active">One</a>
<a href="#/two" class="">Two</a>
複製代碼
.router-link-exact-active,
.router-link-active {
color: red;
font-size: 50px;
}
複製代碼
修飾方式 2 : 修改默認高亮類名 (推薦)
由於有時候項目中可能已經針對導航有過設置樣式,後來再加的路由,因此若是再從新像方式 1 再加一次,會重複 因此 :能夠 修改默認高亮的 a 標籤的類名
const router = new VueRouter({
routes: [],
// 修改默認高亮的a標籤的類名
// red 是已經存在過的
linkActiveClass: 'red'
})
複製代碼
瀏覽器地址欄中的哈希值 與 router-link 的 to 屬性值,徹底匹配對,纔會添加該類
瀏覽器地址欄中的哈希值
包含 router-link 的 to 屬性值,就會添加該類名<router-link to="/" exact>
One
</router-link>
複製代碼
看圖分析: 列表 => 詳情組件
<!-- 1. 入口 -->
<router-link to="/detail/1">手機1</router-link>
<router-link to="/detail/2">手機2</router-link>
<router-link to="/detail/3">手機3</router-link>
複製代碼
routes: [
// 2 . 路由規則
{ path: '/detail/1', component: Detail },
{ path: '/detail/2', component: Detail },
{ path: '/detail/3', component: Detail }
]
//3. 組件
const Detail = Vue.component('detail', {
template: ` <div> 顯示詳情頁內容....{{ $route.path }} </div> `
})
複製代碼
routes: [
// 2 . 路由規則
{ path: '/detail/:id', component: Detail }
]
複製代碼
3.2 獲取參數的三種正確方式
const Detail = Vue.component('detail', {
template: ` // 方式1 : 組件中直接讀取 <div> 顯示詳情頁內容....{{ $route.params.id }} </div> `,
created() {
// 方式2 : js直接讀取
// 打印只會打印一次,由於組件是複用的,每次進來鉤子函數只會執行一次
console.log(this.$route.params.id)
},
// 方式3 : 監聽路由的參數變化 爲何不須要深度監聽,由於它不是data中的
watch: {
$route(to, from) {
console.log(to.params.id)
}
}
})
複製代碼
若是輸入的沒有帶參數的
有參數的對應 : 下面都是正確打開方式
detail/1 ==> 顯示詳情頁內容....1
detail/2 ==> 顯示詳情頁內容....2
detail/3 ==> 顯示詳情頁內容....3
複製代碼
若是經過改變 url 地址,不輸入參數 就看不到
顯示詳情頁內容
這些字 說明沒有正確匹配到detail組件
內
// 可識別的路徑是這樣的
* detail
* detial/1
* detial/2
* detial/3
複製代碼
// 連接:
<router-link to="/user/1001">用戶 Jack</router-link>
<router-link to="/user/1002">用戶 Rose</router-link>
// 路由:
{ path: '/user/:id', component: User }
// User組件:
const User = {
template: `<div>User {{ $route.params.id }}</div>`
}
複製代碼
{ path: '/', redirect: '/home' }
複製代碼
概念 ==> webpack 是什麼?? 前端模塊化打包(構建)工具
webpack能夠解決這些依賴關係,並對他們進行打包
1 - 打包 2 - 模塊化
語法轉換
- Less/SASS 預編譯CSS -> CSS -> 瀏覽器中使用
- ES6 新語法有兼容性問題 -> ES5 -> 瀏覽器中使用
- const fn = () => {} ===> var fn = function() {}
複製代碼
文件壓縮、合併
JS/HTML/CSS 壓縮後,才能發佈上線
文件合併( 無論有多個JS、CSS,默認打包直接生成一個JS文件 )
複製代碼
開發期間提供一個服務器環境
自動打開瀏覽器、監視文件變化,自動刷新瀏覽器
複製代碼
項目上線,打包後才能上線
總結
webpack 這個打包(構建)工具,就是提供了前端開發須要的一整套完整的流程,也就是
webpack 可以滲透的前端開發的各個環節、各個流程中,幫你實現 複雜、繁瑣、重複的工做,有了 webpack 後,開發人員只須要關注當前要實現的業務便可。
複製代碼
模塊化 : 邏輯
組件化 : 界面
webpack爲前端提供了模塊化開發環境,並且webpack是基於node,有了webpack,就能夠像寫Node代碼同樣,寫前端代碼了
在 webpack 看來全部的資源都是模塊,無論是: CSS、圖片、字體、JS、html 等
在webpack提供的模塊化環境中,
1 想要加載一個JS文件,只須要 require('./a.js')
2 想要加載一個CSS文件,只須要 require('../css/index.css')
3 想要加載一個圖片文件,只須要 require('../iamges/a.png')
4 ...
複製代碼
入口(entry)、出口(output)、加載器(loader)、插件(plugins)
文件名不能有漢字,不能取名叫 webpack
package.json
, 命令 : npm init -y
npm i -D webpack webpack-cli
webpack : 是 webpack 工具的核心包
webpack-cli : 提供了一些在終端中使用的命令
-D(--save-dev) : 表示項目開發期間的依賴,也就是 : 線上代碼中用不到這些包了
複製代碼
main.js
文件console.log('我就要被打包了,哦也');
複製代碼
package.json
的scripts
中,添加腳本"scripts": {
"build": "webpack main.js"
},
// webpack 是webpack-cli 中提供的命令, 用來實現打包的
// ./main.js 入口文件,要打包哪一個文件
複製代碼
npm run build
mode
"build" : "webpack ./main.js --mode development"
// WARNING in configuration
// The 'mode' option has not been set, webpack will fallback to 'production' for this value.
// 若是沒有設置 mode 配置項, webpack 會默認提供 開發環境(production)
// Set 'mode' option to 'development' or 'production' to enable defaults for each environment.
// 項目開發的兩種環境
1. 開發環境 (development) : 開發過程就是開發環境
2. 生產環境 (production) : 線上環境, 也就是 : 項目作好了,發佈上線
生產環境下, 打包生產的js文件都是壓縮後的, 開發環境下代碼通常是不壓縮的
複製代碼
src/index.html
html => ul#list>li{我是 li \$}\*10
npm i jquery
, 而且引入 jquery
main.js
, 在 main.js 裏寫入// 使用ES6的模塊化語法
import $ from 'jquery' // 優勢 不用沿着路徑去找
$('#list > li:odd').css('backgroundColor', 'red')
$('#list > li:even').css('backgroundColor', 'green')
// 語法報錯
複製代碼
// 引入 main.js 會報錯,由於瀏覽器不支持這個import 的Es6語法
// npm run build 以後
// 引入 dist/main.js 後會ok,由於webpack 幫咱們轉化爲瀏覽器可以識別的es5語法了
複製代碼
//1. 若是index.html 中引入 jquery , 再引入 mian.js (沒有引入jquery了) => ok
//2. 若是index.html 中沒有引入 jquery , 直接使用es6的模塊化語法 import , 引入main.js就會報錯
//3. 若是index.html 中沒有引入 jquery , 直接使用es6的模塊化語法 import , webapck打包出 dist/main.js 引入 dist/main.js ==> ok
複製代碼
爲何 dist文件下的main.js
文件裏的代碼忽然這麼多
看圖 (打包流程)
code 記得保存一份
準備工做 : src
源文件 : index.html
和main.js
webpack 打包有兩種方式
1-命令行 2-配置項
方式 1 : 命令行
* "build" : "webpack ./mian.js" --mode development
* npm run build
* 通常狀況下 : 改成
* "build" : 入口 --output 出口
* "build": "webpack ./src/js/main.js --output ./dist/bundle.js --mode development",
*
* 驗證 : index.html 引入 bundle.js
複製代碼
第一步 : 項目`根目錄`下, 建立一個 `webpack.config.js`文件 (文件名固定死)
專門指定其餘文件 : --config webpack.XX.js
第二步 : 在 `webpack.config.js` 中,進行配置
// webpack 是基於 node的 , 因此配置文件符合 node 方式書寫配置
// 注意 : 不要再這個文件中使用ES6的的模塊化 import語法
// main.js裏可使用,是由於要經過webpack轉化爲es5的
// 而這個是webpack 的配置文件,,它是要轉化別人的,因此必需要經過
第三步 : 修改 `package.json` 中的 `scripts` , 腳本命令爲: "build": "webpack"
第四步 : 執行命令 : `npm run build`
複製代碼
const path = require('path')
module.exports = {
// 入口
entry: path.join(__dirname, './src/js/main.js'),
// 出口
output: {
// 出口目錄
path: path.join(__dirname, './dist'),
filename: 'bundle.js'
},
// 開發模式
mode: 'development'
}
複製代碼
做用 :
1. 可以根據指定的模板文件 (index.html),自動生成一個新的 index.html,而且注入到dist文件夾下
2. 可以自動引入js文件
複製代碼
npm i html-webpack-plugin
第一步: 引入模塊
const htmlWebpackPlugin = require('html-webpack-plugin')
第二步: 配置
// 插件
plugins: [
// 使用插件 指定模板
new htmlWebpackPlugin({
template: path.join(__dirname, './src/index.html')
})
]
複製代碼
做用 : 爲使用 webpack 打包提供一個服務器環境
npm i -D webpack-dev-server
"dev" : "webpack-dev-server"
npm run dev
--open
--port 3001
--hot
( 整個頁面和整個項目打包 )// hot 不要寫在配置文件裏面,,否則的話還要配其餘插件麻煩
"dev" : "webpack-dev-server --hot",
devServer : {
open : true,
port : 3001
}
複製代碼
npm run dev
==> 不會打包的 ,只會把項目放到服務器裏2.1 執行 : `npm run build` 對項目進行打包,生成dist文件
2.2 模擬本地服務器 : 安裝 : `npm i -g http-server`
2.3 把dist文件裏的內容放到服務器裏便可, 直接運行`http-server`
複製代碼
webpack 只能處理 js 文件,非 js(css.less.圖片.字體等)處理處理不了, 藉助 loader 加載器
建立一個 css 文件, 而後在 main.js
中引入 import '../css/index.css';
ul { style-list : none }
安裝 : npm i -D style-loader css-loader
在 webpack.config.js
中,添加個新的配置項 module
在 module
中添加 loader
來處理 css
// loader
module: {
rules: [
//1.處理 css
// 注意點 use執行loader 順序 從右往左
// css-loader : 讀取css文件內容,將其轉化爲一個模塊
// style-loader :拿到模塊, 建立一個style標籤,插入頁面中
{ test: /\.css$/, use: ['style-loader', 'css-loader'] }
]
}
複製代碼
import '../css/index.less';
npm i -D less-loader less style-loader css-loader
module->rules
less
ul {
background-color: aqua;
li {
&:hover {
color: yellow;
}
}
}
複製代碼
配置 :
{ test :/\.less$/, use : ['style-loader','css-loader','less-loader'] },
複製代碼
設置背景圖片.cls {
width: 300px;
height: 300px;
background: url('../css/4.jpg');
background-size: 100%;
}
安裝 : npm i -D url-loader file-loader
url-loader (推薦) 和 file-loader 二選一便可
在 webpack.config.js 添加 loader 規則
// 處理圖片
{ test : /\.(jpg|png)$/, use : ['url-loader'] },
複製代碼
原始: background-image: url(../images/1.jpg);
處理後: background-image: url(9c9690b56876ea9b4d092c0baef31bb3.jpg);
複製代碼
方式1 :{ test : /\.(jpg|png)$/, use : ['url-loader?limit=57417'] },
方式2 :
{
test: /\.(jpg|png)$/, use: [
{
loader: 'url-loader',
options: {
// 比57417這個小 => 轉化爲base64
// 大於等於這個57417值 => 不會轉base64 內部調用 file-loader 加載圖片
limit: 57417
}
}
]
},
複製代碼
準備字體圖標: 字體圖標文件 iconfont
或者 從阿里矢量圖標
裏下載
拷貝到項目中的 css 文件夾中
在 main.js 中引入 css 文件
import '../css/iconfont/iconfont.css'
複製代碼
使用 :
在 webpack.config.js 中配置
// 4. 處理字體圖標
{ test:/\.(svg|woff|woff2|ttf|eot)$/,use:'url-loader'}
複製代碼
var o = { ...obj }
在谷歌上能夠,edge 就不能夠npm i -D babel-core babel-loader@7
npm i -D babel-preset-env babel-preset-stage-2
babel-polyfill與babel-plugin-transform-runtime
也是作兼容處理的,之前都是用這個,兼容更早的{ test: /\.js$/, use: 'babel-loader', exclude: /node_modules/ }
複製代碼
.babelrc
{
"presets": [
"env",
"stage-2"
],
-----------
// 暫時不用
// 若是將來某一天真的用到了polify
"plugins": [
["transform-runtime", {
"helpers": false,
"polyfill": true,
"regenerator": true,
"moduleName": "babel-runtime"
}]
複製代碼
var obj = {
name: 'zs',
age: 20
}
var o = { ...obj }
console.log(o)
複製代碼
腳手架 2.X ==> 2.Xvue
腳手架 3.X ==> 3.X vue
vue-cli 是 vue 的腳手架工具
做用 : vue-cli 提供了一條命令, 咱們直接經過這條命令就能夠快速的生成一個 vue 項目 (vue init XX
) 。 項目的基本結構、以及 webpack 配置項 所有配置 好了
爲何會有腳手架工具 ???
由於 webpack 配置繁瑣, 阻止一批想用 vue 可是不會 webpack 的開發人員,因此做者直接將全部 vue 項目中用到的配置所有幫你寫好了,這樣,就不須要開發人員再去配置基礎 webpack 配置項了,使用 vue-cli 這個腳手架工具後,再也不用擔憂 webpack 配置問題了, 咱們前端只須要寫 vue 代碼, 來實現功能便可
npm i -g vue-cli
vue init webpack 項目名稱
vue init webpack vue-demo01
? Project name # 回車
? Project description # 回車
? Author # 回車
? Vue build standalone # => 運行時+編譯 => 詳見下面的問題1
? Install vue-router? # Yes
? Use ESLint to lint your code? # Yes => 詳見下面的問題2
? Pick an ESLint preset Standard # standard
? Set up unit tests # No
? Setup e2e tests with Nightwatch? # No
? Should we run `npm install` for you after the project has been created? # (recommended) npm
複製代碼
To get started:
cd vue-demo01
npm run dev
複製代碼
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
第一遍:文件夾, 第二遍再細化文件
# build - webpack 相關配置
- build.js - 生產環境構建代碼
- check-version.js 檢查 node、npm 等版本
- util.js 構建工具相關
- vue-loader.config.js vue-loader 的配置文件
- webpack.base.conf.js - webpack 的基礎配置
- webpack.dev.conf.js - webpack 開發環境配置
- webpack.prod.conf.js - webpack 發佈環境配置
# config - vue 基本配置文件(好比:監聽端口(17), 使用 eslint:(26))
- dev.env.js - 開發環境變量
- index.js 項目的一些配置
- prod.env.js 生成環境變量
# node_modules - node 安裝的依賴包
# src - 資源文件夾, 之後咱們就在這個目錄下寫代碼
- assets - 靜態資源 (圖片 css 都放在這)
- components - 公用組件
- router - 路由
- App.vue - 項目的根組件
- main.js - 項目的入口文件(總邏輯)
# static - 靜態資源 (圖片 json 數據之類的)
- .gitkeep git 保持文件,由於 git 上傳,會忽略空文件夾
# .babelrc - babel 配置文件, (es6 語法編譯配置,將 es6 轉化爲瀏覽器可以識別的代碼)
# .editorconfig - 定義代碼格式
- charset = utf-8 編碼 utf8
- indent_style = space 縮進 空格
- indent_size = 2 縮進字符
- end_of_line = lf 回車做爲換行的標記
- insert_final_newline = true 最近一空白行做爲結尾
- trim_trailing_whitespace = true 清除最開始的空白
- 若是使用 ?
- 1. 安裝 vscode 的 editorConfig for vscode
- 2. eslint 檢測修復後
# .eslintignore - eslint 檢測忽略的地方
- /build/
- /config/
- /dist/
- /\*.js 根目錄下帶.js 的
# .eslintrc.js - eslint 的配置文件
# .gitignore - git 的忽略文件
# .postcssrc.js - css 配置文件 (啥也沒有處理)
# index.html - 頁面入口
# package.json - 項目配置文件
複製代碼
assets 靜態資源
components 組件
App.vue 根組件 => 指定路由出口
app 中的 #app 仍是 index.html 中的 #app, app.vue 中的會覆蓋前者 能夠經過分別添加 title 屬性驗證一下
路由出口要寫在 app.vue 組件模板中
main.js
Vue.config.productionTip = false
不要打印提示new Vue({
el: '#app', // 目標顯示
router, // 掛載路由
components: { App }, // 註冊組件 App
template: '<App/>' // 模板顯示組件 app
})
複製代碼
route/index.js => 路由
必定要記住 :Vue.use(Router)
模塊化公工程中必定要安裝路由插件 .js 就是一個模塊
官網裏 也提到 https://router.vuejs.org/zh/installation.html
參考 : vue.js => 安裝 => 對不一樣構建本版本的解釋
// 須要編譯器
new Vue({
template: '<div>{{ hi }}</div>'
})
// 不須要編譯器
new Vue({
render (h) {
return h('div', this.hi)
}
})
複製代碼
router/index.js =>
import HelloWorld from '@/components/HelloWorld'
import HelloWorld from 'C:/users/.../src/components/HelloWorld'
複製代碼
概念 : ESLint 是在 JavaScript 代碼中識別和報告模式匹配的工具,它的目標是保證代碼的一致性和避免錯誤。
如何使用 eslint ?
"editor.formatOnSave": true, //#每次保存的時候自動格式化
"eslint.autoFixOnSave": true, // #每次保存的時候將代碼按eslint格式進行修復
"eslint.validate": [
{ "language": "html", "autoFix": true },
{ "language": "vue", "autoFix": true },
{ "language": "javascript", "autoFix": true },
{ "language": "wpy", "autoFix": true }
],
"prettier.eslintIntegration": true, // #讓prettier使用eslint的代碼格式進行校驗
"javascript.format.insertSpaceBeforeFunctionParenthesis": true,
"editor.formatOnType": true //#讓函數(名)和後面的括號之間加個空格
複製代碼
關閉 Eslint :
dev.useEslint
設置爲falsenpm run dev
測試 : 刪除 main.js 中的 /* eslint-disable no-new */ 關閉後 會報波浪線,可是不會報錯了
Prettier
eslint-disable-next-line # 忽略檢測下一行 可使用單行註釋/多行註釋,其餘都是多行註釋
eslint-disable # 忽略當前整個文件
eslint-disable no-new # 忽略前面是new開頭
複製代碼
準備 :開啓服務器+數據庫
vue 項目學什麼?
畫圖 : 接口訪問路徑 : 前端頁面 ===> 接口服務器 ===> 數據庫服務器 ==> 數據庫
打開
phpStudy
,點擊啓動
打開 navicat
點擊鏈接
: 建立一個MySQL
鏈接
用戶名和密碼 : root-root(不能亂寫) 這個是和 config 裏的配置同樣的
建立一個數據庫 : shop_admin
不要亂寫, 選擇倒數找到 unt-8
雙擊打開數據庫
導入 sql語句
=> 右鍵運行 SQL 文件 => shop-api 最後一個 sql 文件
若是沒有反應 : 表 => 右鍵刷新
shop-api
npm start
API 接口服務啓動成功,佔用端口 8888
http://localhost:8888/api/private/v1/login?username=admin&password=123456
項目使用接口 : (記得保存)
// shop-api裏面有
複製代碼
phpStudy
中的 mySql
shop-api
, 運行 npm start
導出 : export default
默認 只能導出一個
let str = 'abc'
let num = 20;
let obj = { name :'zs' }
export default num
// export default obj
複製代碼
導入 : import
導入的名字能夠任意
import res from './a.js'
console.log(res)
複製代碼
**導出 : export **
// 邏輯模塊
// 登陸一個函數
export let login = () => {
console.log('登陸');
}
// 註冊一個函數
export let register = () => {
console.log('註冊');
}
複製代碼
導入 : import
// 方式1
import * as res from './a'
console.log(res);
res.login()
res.register()
// 方式2
import { login, register as reg } from './a'
login()
register()
複製代碼
import axios from 'axios';
複製代碼
vue init webpack shop_admin_35 清除不要的東西 (logo 和 hello world 組件 )
安裝 : npm i vue-router 建立一個router文件夾 / router.js 實例化路由 導出路由模塊 , main.js 引入 ,掛載到vue實例上
/**
準備工做
四個步驟
- 先把須要的組件建立出來 Login.vue Home.vue
- 走流程
1.先建立組件 /login/Login.vue 2.走流程
- 入口 : url手動寫
- 規則 : {path :'/login', component: Login}
- 組件 : 引入便可
- 出口 : 在 app.vue 根組件 裏 寫一個出口
連接 : element-cn.eleme.io/#/zh-CN/com… 概念 : element 是一個(基於 vue 2.X )組件庫
安裝
: npm i element-ui ( -S == --save == 不寫 ) (-D 開發階段須要 發佈階段不須要)快速上手
:引入(main.js)
// 引入 element
import ElementUI from 'element-ui';
import 'element-ui/lib/theme-chalk/index.css';
// 安裝一下 element-ui
Vue.use(ElementUI);
複製代碼
測試 : 找到官網裏的組件,拿到一個 按鈕 注意點 :template 裏面只能由一個根元素 one root element
el-form el-form-item
安裝 axios 引入 使用
聲明式導航 ==> 組件 標籤 編程式導航 this.$router.push('/home') ==> 事件裏
route : 路由對象 , 包含url的信息對象, (path query, params) 解析 地址 #後面的信息
注意1 : num='8' ==> 把字符串8 賦值給了num :num='8' ==> : 把 8 原來的類型賦值給num 注意2 : 若是想讓label和input在一行 => 設置 label-width='100px' => el-form 若是想讓 label 和 input 不在一行 =>不要設置 label-width