前言
官網:https://cn.vuejs.org/
官方文檔:https://cn.vuejs.org/v2/guide/
熱門組件庫地址:https://github.com/vuejs/awesome-vue
第三方UI框架:Element归榕、Iview、MintUI
安裝
直接引入方式:下載 vue.js ,直接在項目中引入(和引用 JQuery 一樣)
CDN引入方式:
開發(fā)環(huán)境
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
生產環(huán)境
<script src="https://cdn.jsdelivr.net/npm/vue@2.6.0"></script>
NPM航厚,使用 vue-cli 構建 vue 項目
初入門
<script>
<html>
<head>
<meta charset="utf-8">
<title>Vue-Learn</title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
</head>
<body>
<div id="box1">
{{name}}
</div>
</body>
<script type="text/javascript">
// 初始化 vue,在瀏覽器控制臺可以通過 vm 控制
var vm = new Vue({
el: "#box1",
data:{
name: "Hello World!"
},
// 方法
methods: {
},
// 計算屬性
computed: {
}
})
</script>
</html>
</script>
Vue 基礎
模板語法
直接取值
{{ 屬性 }}
需要解析標簽鞠评,防止XSS延塑、CSRF攻擊
<div v-html=""></div>
表達式
<img v-bind:src="imgSrc"></img>
或者簡寫
<img :src="imgSrc"></img>
條件
v-if : 從 dom 中刪除
v-else-if :
v-else
v-show :只是不在頁面顯示
列表
v-for="todo in todos"
v-for="(todo,index) in todos" : index 為索引值
或者
v-for="todo of todos"
v-for="(todo,index) of todos"
事件
v-on:click 或者 @click
v-model : 實現表單輸入和應用狀態(tài)之間的雙向綁定蠢护〉探幔可以代替輸入框value
class 與 style
綁定HTML Class
|----對象語法
|----數組語法
綁定內聯樣式
|----對象語法
|----數組語法
數組更新檢測
使用以下方法操作數組必怜,可以檢測變動
push()肉拓、pop()、shift()梳庆、unshift()暖途、splice()、sort()膏执、reverse()
1
filter() concat() 和 slice() map()驻售,不會檢測變動,可以使用新數組替舊數組
輸入框事件
事件對象
@input="handleInput"
handleInput(ev){
// ev 表示事件對象
console.log(ev)
// 輸入框的值
console.log(ev.target.value)
}
事件對象和傳參
@input="handleInput($event, param)"
handleInput(ev, param){
// ev 表示事件對象
console.log(ev)
console.log(ev.data)
}
多選框
v-model 使用數組更米,value 表示對應的標識
獲取 v-model 綁定的值即可獲取多選的值
<input type="checkbox" v-model="checkedGroup" value="vue"> vue
<input type="checkbox" v-model="checkedGroup" value="react"> react
<input type="checkbox" v-model="checkedGroup" value="jquery"> jquery
new Vue({
el: "#box",
data: {
checkedGroup: []
}
})
單選框
v-model 使用字符串欺栗,value 表示對應的標識,name 標識一組單選
獲取 v-model 綁定的值即可獲取單選的值
<input type="radio" v-model="picked" name="favor" value="vue">vue
<input type="radio" v-model="picked" name="favor" value="react">react
<input type="radio" v-model="picked" name="favor" value="query">query
Axios 請求
參考鏈接:https://github.com/axios/axios
計算屬性
調用不能使用小括號征峦,必須有返回值纸巷。寫起來像方法,用起來是屬性;
計算屬性當屬性值發(fā)生改變的時候茉稠,會自動重新計算屬性值七问,并渲染到頁面上;
watch 監(jiān)聽
監(jiān)聽某一個值發(fā)生變化存哲,和改變之后需要如何處理
mixins 混入
引入js,同名方法優(yōu)先級低于 methods
new Vue({
mixins: [funUtils]
})
生命周期
組件注冊方式
組件作用域隔離七婴;組件只能有另一個根節(jié)點祟偷;
全局組件
data 必須是函數式寫法,必須有返回值
Vue.component("", {})
局部組件
Vue.component("common", {
components:{
"localComponents":{
// 局部組件打厘,該組件只供common組件使用
}
}
})
通信
父傳子通信
通過 Prop 向子組件傳遞數據:不限制類型
父組件在調用子組件的時候賦值
<div id="commucation">
<p>父組件</p>
// 父傳子通信修肠,如果動態(tài)傳值可以對 param 使用 v-bind 綁定
<child param="君不見黃河之水天上來"></child>
</div>
子組件通過 props 屬性獲取父組件的傳參
Vue.component("child", {
template:
<nav> <span style="background: yellow">子組件</span> <br> {{ param }} </nav>
,
// props:["param"]
// 屬性驗證
props:{
param:String
}
})
完整示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父組件</p>
<child param="君不見黃河之水天上來"></child>
</div>
</body>
<script type="text/javascript">
// 組件之間互不影響,沒有任何關聯,但是可以通信
// 子組件
Vue.component("child", {
template:
`
<nav>
<span style="background: yellow">子組件</span>
<br>
{{ param }}
</nav>
`,
// props:["param"]
// 屬性驗證
props:{
param:String
}
})
// 父組件
let vm = new Vue({
el: "#commucation"
})
</script>
</html>
子傳父通信
通過事件通知父組件
子組件通過事件通知父組件調用子組件時綁定的事件
childClick(){
console.log("子組件點擊調用")
// 使用 this.emit("noticeevent", 1000);
}
父組件在調用子組件的時候綁定事件,并指定父組件中接收參數的函數
調用子組件
<div id="commucation">
<p>父組件</p>
<child @noticeevent="getChildParam"></child>
</div>
接收參數的函數
// 父組件
let vm = new Vue({
el: "#commucation",
methods:{
// data 為子組件傳的參數
getChildParam(data){
console.log("data", data)
}
}
})
完整示例
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父組件</p>
<child @noticeevent="getChildParam"></child>
</div>
</body>
<script type="text/javascript">
// 組件之間互不影響,沒有任何關聯,但是可以通信
// 子組件
Vue.component("child", {
template:
`
<nav>
<span style="background: yellow">子組件</span>
<br>
<button @click="childClick()">子組件click</button>
<br>
</nav>
`,
methods:{
childClick(){
console.log("子組件點擊調用")
// 通知父組件的中調用子組件標簽中的事件
this.$emit("noticeevent", 1000);
}
}
})
// 父組件
let vm = new Vue({
el: "#commucation",
methods:{
getChildParam(data){
console.log("data", data)
}
}
})
</script>
</html>
refs 通信
ref 綁定在標簽上户盯, this.refs 獲取時組件對象;
ref 綁定在標簽上
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<input type="text" ref="name"/>
<button type="button" @click="getDom">GET</button>
</div>
</body>
<script type="text/javascript">
// 父組件
let vm = new Vue({
el: "#commucation",
methods:{
getDom(){
// this.$refs 獲取所有ref
// this.$refs.name 獲取ref值為name的節(jié)點
// this.$refs.name.value 獲取ref值為name節(jié)點的值
console.log("獲取的值為:", this.$refs.name.value)
}
}
})
</script>
</html>
ref 綁定在組件上
父傳子
父組件通過 ref 綁定調用子組件的調用標簽吗伤,通過 this.r e f s . c h i l d C o m p o n e n t ( c h i l d C o m p o n e n t 指 定 的 是 父 組 件 調 用 子 組 件 綁 定 的 r e f 值 ) 獲 取 子 組 件 吃靠, 通 過 t h i s . refs.childComponent (childComponent指定的是父組件調用子組件綁定的ref值)獲取子組件,通過 this.refs.childComponent(childComponent指定的是父組件調用子組件綁定的ref值)獲取子組件足淆,通過this.refs.childComponent.getParent(params) 調用子組件的函數
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父組件</p>
<input type="text" ref="inputVal"/>
<button type="button" @click="transferVal">通過refs傳值給子組件</button>
<child ref="childComponent"></child>
</div>
</body>
<script type="text/javascript">
// 組件之間互不影響,沒有任何關聯,但是可以通信
// 子組件
Vue.component("child", {
template:
`
<nav>
<span style="background: yellow">子組件</span>
<br>
</nav>
`,
methods:{
getParent(data){
console.log("獲取父組件的值為:", data)
}
}
})
// 父組件
let vm = new Vue({
el: "#commucation",
methods:{
transferVal(){
console.log("this.$refs.inputVal.value", this.$refs.inputVal.value);
let params = this.$refs.inputVal.value;
// 獲取ref綁定的子組件,并調用子組件的函數(可以傳參)
// this.$refs.childComponent 獲取子組件
// this.$refs.childComponent.getParent(params) 調用子組件的函數
this.$refs.childComponent.getParent(params);
}
}
})
</script>
</html>
bus 通信(簡單的非父子通信)
發(fā)布訂閱模式巢块,通過同一個 vue 實例作為中間件中心
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父組件</p>
<child1></child1>
<child2></child2>
</div>
</body>
<script type="text/javascript">
// 創(chuàng)建一個 vue 實例,作為中央事件總線
let bus = new Vue();
// 子組件 1
Vue.component("child1", {
template:
`
<nav>
<span style="background: yellow">子組件 1</span>
<button @click="transferData()">transfer</button>
</nav>
`,
methods:{
transferData(){
console.log("開始輸出數據");
// 通知dataMount事件
bus.$emit("dataMount", "君不見黃河之水天上來")
}
}
})
// 子組件 2
Vue.component("child2", {
template:
`
<nav>
<span style="background: red">子組件 2</span>
<br>
</nav>
`,
mounted() {
// 監(jiān)聽dataMount事件
bus.$on("dataMount", (data)=>{
console.log("the data is ", data);
})
}
})
// 父組件
let vm = new Vue({
el: "#commucation"
})
</script>
</html>
Vuex
import Vue from 'vue';
import Vuex from 'vuex';
Vue.use(Vuex);
export default new Vuex.Store({
state: {
// 共享狀態(tài)
},
mutations: {
// 用于修改共享狀態(tài)
},
actions: {
// ajax 異步請求調用 mutations 中的函數,修改共享狀態(tài)
},
});
// 其他vue組件通過 "this.$store.state.共享狀態(tài)屬性" 進行訪問
動態(tài)組件
<component :is=""></component>
<keep-alive>
<component :is=""></component>
</keep-alive>
slot 插槽
插槽是混合父組件的內容混到子組件中
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父組件</p>
<child>
<ul>
<li>11111111</li>
<li>22222222</li>
<li>33333333</li>
</ul>
</child>
</div>
</body>
<script type="text/javascript">
// 子組件 2
Vue.component("child", {
template:
`
<nav>
<div>子組件</div>
<!--slot插槽:混合父組件的內容混到子組件中-->
<slot></slot>
</nav>
`
})
// 父組件
let vm = new Vue({
el: "#commucation"
})
</script>
</html>
具名插槽
插槽具有名字巧号,可以使用name屬性指定使用插槽的位置
父組件使用 slot 屬性指定插槽名稱
子組件使用 <slot name=""> 指定slot名稱
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
<p>父組件</p>
<child>
<div slot="slot1">aaaaa</div>
<div slot="slot2">bbbbb</div>
<div slot="slot3">ccccc</div>
</child>
</div>
</body>
<script type="text/javascript">
// 子組件 2
Vue.component("child", {
template:
`
<nav>
<div>子組件</div>
<!--slot插槽:混合父組件的內容混到子組件中, name指定插槽名稱-->
<div style="background: red">
<slot name="slot1"></slot>
</div>
<div style="background: yellow">
<slot name="slot2"></slot>
</div>
<div style="background: blue">
<slot name="slot3"></slot>
</div>
</nav>
`
})
// 父組件
let vm = new Vue({
el: "#commucation"
})
</script>
</html>
動畫
推薦:https://github.com/daneden/animate.css
使用方式:
<div id="commucation">
<p class="animated bounceIn"> 君不見黃河之水天上來 </p>
</div>
輪播/滑動效果
推薦:https://www.swiper.com.cn/
指令
指令不在 Vue 實例中
指令可以傳js對象
<div v-demo="{ color: 'white', text: 'hello!' }"></div>
1
指令具有生命周期
// 注冊一個全局自定義指令 v-focus
Vue.directive('focus', {
// 當被綁定的元素插入到 DOM 中時……
inserted: function (el族奢,binding) {
// el 是原生節(jié)點,binding 表示標簽值
// 聚焦元素
el.focus()
}
})
過濾器
自定義過濾器
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="commucation">
{{name | msgFilter}}
</div>
</body>
<script type="text/javascript">
let vm = new Vue({
el: "#commucation",
data:{
name: "君不見黃河之水天上來"
},
filters:{
msgFilter: function(value){
console.log("value", value)
// 處理數據
return value.split('之')[1];
}
}
})
</script>
</html>
路由
路由容器
<router-view name=""></router-view>
1
hash 路由
location.hash 切換
window.onhashchange 監(jiān)聽路徑的切換
1
2
history 路由
// 路徑沒有 #
const router = new Router({
mode : "history",
})
history.pushState 切換
window.onpopstate 監(jiān)聽路徑的切換
嵌套路由
import Vue from 'vue'
import Router from 'vue-router'
import Home from './views/Home.vue'
// 注冊路由模塊
Vue.use(Router)
export default new Router({
mode: 'history',
base: process.env.BASE_URL,
routes: [
{
path: '/',
name: 'home',
alias: "/index", // 別名
component: Home,
children:[
{
path: '/',
name: 'home',
component: Home,
}
]
},
// 重定向
{
path: '/li',
name: 'li',
redirect: "/about"
}
]
})
動態(tài)路由配置
{
# 使用 :id 做動態(tài)路由配置丹鸿,: 是做一個占位符
path: '/detail/:id1/:id2/:id3',
name: 'home'
component: Detail
}
編程式路由
路徑跳轉
this.$router.push(/path/{id}
)
路由名稱跳轉
this.$router.push({name:"",params:{}})
聲明式路由
<router-link>
獲取hash值
獲取當前路由
let hashVal = location.hash
獲取當前路由信息
this.$route
路由守衛(wèi)
全局守衛(wèi)
在 router.js 配置
router.befaoreEach((to, from, next) => {
if(to.path === '/center'){
// 攔截判斷
if(usre.isLogin()){
// 有登錄信息,可以訪問
next();
}else{
// 無登錄信息庭敦,需要登錄
next('/login')
}
}else{
// 允許過去
next();
}
})
Vuex
管理共享狀態(tài)——解決非父子通信
數據快照——緩存后端數據,避免重復請求疼电,影響用戶體驗
時光旅行——調式