<span v-text="msg"></span>
<!-- 二者等價 -->
<span>{{msg}}</span>
複製代碼
v-html:javascript
<div v-html="rawHtml"></div>
複製代碼
<div id="app">
<input v-model="somebody">
<p>hello {{somebody}}</p>
</div>
<script> var app = new Vue({ el: '#app', data: { somebody:'小明' } }) </script>
複製代碼
上面這個例子中直接在瀏覽器input中輸入別的名字,下面的p的內容會直接跟着變。這就是雙向數據綁定。css
v-model:僅僅是一個語法糖,至關於
:value
+@input
html![]()
input
事件:當輸入框中的數據改變時發生
<a v-bind:href="hrefname">百度</a>
<a :href="hrefname">百度</a>
<script> var app = new Vue({ el:"#app", data: { hrefname:"http://www.baidu.com", } }) </script>
複製代碼
<a v-if="ok">yes</a>
複製代碼
若是屬性值ok爲true,則顯示。不然,不會渲染這個元素。前端
<a v-if="ok">yes</a>
<a v-else>No</a 複製代碼
<div v-if="type``='A'">
A
</div>
<div v-if="type``='B'">
B
</div>
<div v-if="type``='C'">
C
</div>
<div v-else>
Not A,B,C
</div>
複製代碼
<h1 v-show="ok">hello world</h1>
複製代碼
也是用於根據條件展現元素。和v-if不一樣的是,若是v-if的值是false,則這個元素被銷燬,不在dom中。可是v-show的元素會始終被渲染並保存在dom中,它只是簡單的切換css的dispaly
屬性。vue
注意:v-if有更高的
切換開銷
v-show有更高的初始渲染開銷。 所以,若是要很是頻繁的切換,則使用v-show較好;若是在運行時條件不太可能改變,則v-if較好java
特別提醒
node
v-show
須要放到一個真實的dom上,不能放在template
上面webpack
v-for 遍歷數組ios
<p v-for="(value,index) in links">{{value}}</p>
複製代碼
注意:在使用v-for過程當中,要綁定惟一的key
,key儘可能不要綁定index,若是有id儘可能綁定id
git
<p v-for="(value,index) in links" :key="index">{{value}}</p>
特別提醒
建議不要在與
v-for
相同的元素上使用v-if
。由於v-for
指令的優先級高於v-if
當它們處於同一節點。v-for
的優先級比v-if
更高,這意味着v-if
將分別重複運行於每一個v-for
循環中。
<style>
.abc{color: red;}
.def{background-color: blue;}
.g-h{color: yellow;}
</style>
<div id="app">
<p class="abc">這是一個p標籤</p>
<p :class="className">這是一個p標籤</p>
<!-- ? : 三元運算符 -->
<p :class="isPass ? className : ''">這是一個p標籤</p>
<p :class="{abc:true}">這是一個p標籤</p>
<p :class="{abc:isPass}">這是一個p標籤</p>
<p :class="{abc:isPass,def:true}">這是一個p標籤</p>
<p :class="{'g-h':true}">這是一個p標籤</p>
<p :class="['abc','def']">這是一個p標籤</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
name:"wangcai",
className:"abc",
isPass:true,
}
})
</script>
複製代碼
<div id="app">
<p :style="myStyle">這是一個p標籤</p>
</div>
<script>
var app = new Vue({
el: '#app',
data: {
myStyle:{color:'red',backgroundColor:'blue'}
}
})
</script>
複製代碼
el指定app管理的邊界
面試題
如何經過
$el
獲取到更新後的dom元素? 答:在下一下事件環中獲得更新後dom元素
數據模型
計算屬性,依賴於data中的數據
計算屬性和方法的區別:
過濾器
過濾器的簡單使用:
![]()
組件:三部曲
- 定義組件
- 註冊組件
- 使用組件
組件的簡單使用:
![]()
生命週期方法
$watch
能夠監控Data中的數據,經過$watch
獲得值,確定是更新後的值 使用
vm.$watch( "name", function(newValue,oldValue){ } )
vue中的$nextTick主要涉及到vue中DOM的異步更新 nextTick
應用場景及緣由
created()
鉤子函數進行的DOM操做必定要放在Vue.nextTick()
的回調函數中緣由:在
created()
鉤子函數執行的時候DOM 其實並未進行任何渲染,而此時進行DOM操做無異於徒勞,因此此處必定要將DOM操做的js代碼放進Vue.nextTick()
的回調函數中。與之對應的就是mounted()
鉤子函數,由於該鉤子函數執行時全部的DOM掛載和渲染都已完成,此時在該鉤子函數中進行任何DOM操做都不會有問題 。
Vue.nextTick()
的回調函數中。Vue的官方文檔中詳細解釋
Vue 異步執行 DOM 更新。只要觀察到數據變化,Vue 將開啓一個隊列,並緩衝在同一事件循環中發生的全部數據改變。若是同一個 watcher 被屢次觸發,只會被推入到隊列中一次。這種在緩衝時去除重複數據對於避免沒必要要的計算和 DOM 操做上很是重要。而後,在下一個的事件循環「tick」中,Vue 刷新隊列並執行實際 (已去重的) 工做。Vue 在內部嘗試對異步隊列使用原生的
Promise.then
和MessageChannel
,若是執行環境不支持,會採用setTimeout(fn, 0)
代替。
例如,當你設置
vm.someData = 'new value'
,該組件不會當即從新渲染。當刷新隊列時,組件會在事件循環隊列清空時的下一個「tick」更新。多數狀況咱們不須要關心這個過程,可是若是你想在 DOM 狀態更新後作點什麼,這就可能會有些棘手。雖然 Vue.js 一般鼓勵開發人員沿着「數據驅動」的方式思考,避免直接接觸 DOM,可是有時咱們確實要這麼作。爲了在數據變化以後等待 Vue 完成更新 DOM ,能夠在數據變化以後當即使用Vue.nextTick(callback)
。這樣回調函數在 DOM 更新完成後就會調用。
$set
能夠給data中動態地添加一個數據,前提
是隻能給對象中添加數據
示例
事件三要素: 事件源,事件類型,監聽器
語法
:v-on: 處理事件 或 @處理事件
注意:mouseover / mouseout 與 mouseenter / mouseleave的區別
- 當綁定事件的元素裏面沒有子元素的時候,兩組觸發效果是一致的。
- 當綁定事件的元素裏面有子元素的時候,鼠標通過綁定mouseover的當前元素以及它裏面的子元素的時候,都會觸發, 而通過綁定mouseenter的元素時,只會在鼠標剛進入的時候觸發,當進入其子元素的時候,是不會再觸發的了。
總結
:
不論鼠標指針穿過被選元素或其子元素,都會觸發 mouseover 事件。對應mouseout
只有在鼠標指針穿過被選元素時,纔會觸發 mouseenter 事件。對應mouseleave
當事件發生時,事件對象中保存了不少信息,如點擊的座標。 $event
固定的名字
示例:
![]()
示例:
![]()
示例:
![]()
// 自定義按鍵名稱
Vue.config.keyCodes.ent = 13;
// 頁面引用
<input type="text" @keyup.ent="enter_click"/>
複製代碼
全局組件 : 定義全局組件,在每一個組件中均可以進行引用
語法:
Vue.component("組件名",{template:"組件內容"})
示例:
![]()
組件:三部曲
- 定義組件
- 註冊組件
- 使用組件
示例:
![]()
父傳子 : 父中有數據,傳遞給子,
步驟:
1,肯定父中有數據 2,在父組件的模板中經過屬性綁定把數據綁到子組件上 3,在子組件中定義props屬性,用來接收父傳遞過來的數據 4,在子組件的模板就可使用接收過來的數據了
示例:
![]()
屬性校驗:
總結:
父綁定數據 子接收數據
過程:
- 在父組件模板中,給子組件添加一個事件監聽
- 在子組件中,某個時間經過
this.$emit
發出這個事件,發出事件的同時就能夠攜帶數據- 當父中的方法觸發,數據做用這個方法的第一個參數
示例:
![]()
npm i nrm -g
切換安裝源
查看安裝源
nrm ls
![]()
切換安裝源 nrm use taobao
安裝vue的腳手架
npm i -g @vue/cli
vue create myvue
cd myvue
npm run serve
html代碼
<div id="app">
<h1>Hello App!</h1>
<p>
<!-- 使用 router-link 組件來導航. -->
<!-- 經過傳入 `to` 屬性指定連接. -->
<!-- <router-link> 默認會被渲染成一個 `<a>` 標籤 -->
<router-link to="/foo">Go to Foo</router-link>
<router-link to="/bar">Go to Bar</router-link>
</p>
<!-- 路由出口 -->
<!-- 路由匹配到的組件將渲染在這裏 -->
<router-view></router-view>
</div>
複製代碼
script代碼
// 1. 定義 (路由) 組件。
// 能夠從其餘文件 import 進來
const Foo = { template: '<div>foo</div>' }
const Bar = { template: '<div>bar</div>' }
// 2. 定義路由
// 每一個路由應該映射一個組件。 其中"component" 能夠是
// 經過 Vue.extend() 建立的組件構造器,
// 或者,只是一個組件配置對象。
const routes = [
{ path: '/foo', component: Foo },
{ path: '/bar', component: Bar }
]
// 3. 建立 router 實例,而後傳 `routes` 配置
// 你還能夠傳別的配置參數, 不過先這麼簡單着吧。
const router = new VueRouter({
routes // (縮寫) 至關於 routes: routes
})
// 4. 建立和掛載根實例。
// 記得要經過 router 配置參數注入路由,
// 從而讓整個應用都有路由功能
const app = new Vue({
router
}).$mount('#app')
// 如今,應用已經啓動了!
複製代碼
經過路由
咱們能夠在任何組件內經過
this.$router
訪問路由器,也能夠經過his.$route
訪問當前路由:
格式
router.push(location, onComplete?, onAbort?)
注意:
在 Vue 實例內部,你能夠經過
$router
訪問路由實例。所以你能夠調用this.$router.push
。
示例:
示例:
npm install axios
import axios from 'axios';
當vue的實例建立時,會伴隨一系列的方法運行,稱做生命週期函數
父組件向子組件傳遞數據是經過prop傳遞的,子組件傳遞數據給父組件是經過$emit觸發事件來作到的。
props 與 $emit的簡單使用
![]()
注意
: 使用$emit 觸發父類綁定的方法時,觸發的名稱必須所有是小寫,若父類綁定使用到小駝峯,則在觸發時,所有變成小寫,駝峯之間用-隔開
能夠實現父組件與孫子組件之間的數據的傳遞 this.
attrs中
$attrs的簡單使用
特別提醒
父組件中所綁定的傳給父組件的屬性,都存放在$attrs中,若在子組件中不接收,直接進行綁定,可使用:
v-bind="this.$attars"
$listenners的簡單使用
觸發父傳遞的click事件: @click="
listeners"
$parent 獲取父組件的實例,能夠以此來調用父組件中的方法。
this.$parent.cut();
$children 獲取全部的兒子, 能夠以此來獲取子組件中的數據
this.$children[0].msg = "張三"
特別提醒
children:獲取的是全部子組件的實例
ref 與refs是成對使用 ref 用於定義 $refs用戶獲取
$dispatch
是掛載到Vue實例
上的一個方法, 自動向上
父類中查找觸發的方法,若是該方法存在就觸發
示例
eventBus
原理
事件總線是,在vue的
原型
上,掛載一個$eventBus
事件(名字本身起),經過$on
進行綁定事件, 先在事件中心中註冊一些事件 在須要的位置就能夠經過$emit
去發佈事件(觸發事件)
示例
在數據進行傳遞的時候,數據的傳遞與觸發的方法結合,能夠有比較簡便的語法糖
,更加方便程序的開發,可是與此同時也有必定的難度,不是很容易懂。下面就簡單的介紹幾種語法糖。
.sync
語法糖
.sync
是@update:data
的語法糖,data
是vue中data中的數據
在給子類傳遞數據的時候,經過.sync
對屬性進行限定,在子類中能夠直接觸發update:數據名稱
來修改父類中對應的數據,該方法能夠省去父類中修改屬性的方法。
沒有使用.sync
以前
示例
使用.sync
以後
沒有簡化: 簡化後:
示例
特別注意
update是規定的觸發的方法,update冒號後面跟的必須是父類中要修改的數據的數據名
v-model
語法糖
v-model
是:value
和@input
的語法糖,綁定的屬性必須是value
在給子類傳遞數據的時候,直接使用v-model
進行綁定,在子類中,能夠觸發input
事件,來達到修改數據的目的
示例
特別注意
v-model
至關於:value
+@input
至關於上述方法的簡寫
數據監控: : 監控數據的獲取與改變,能夠簡稱爲數據劫持。
vue中data數據的監控原理:
代碼以下:
// 數據的監控,監控數據的獲取與改變
// vue中data數據的監控原理
obj = {
name: "wangcai",
age:18
};
function obServe(obj){
if(typeof obj ``= "object"){
for(key in obj){
defineReactive(obj,key,obj[key]);
}
}
}
function defineReactive(obj,key,value){
obServe(value);
Object.defineProperty(obj,key,{
get(){
console.log("get...");
return value;
},
set(val){
console.log('set... :');
obServe(val);
value = val;
}
})
}
// defineProperty是數組是無效的
//解決方式以下:
// vue中封裝了數據的全部的方法,此處只作列舉
let arr = ["push","slice","shift","unshift"]
arr.forEach(method=>{
let old = Array.prototype[method];
Array.prototype[method] = function(value){
console.log("set...")
old.call(this,value)
}
})
//-----------------------------------------------------------
// 測試數組
// observer(obj)
// obj.age = [1,2,3] // set..
// obj.age.push(4) // 設置值 defineProperty對數據是無效的
//-----------------------------------------------------------------
// 測試簡單的對象
// obServe(obj)
// console.log(obj.name) //get...
// obj.name = "hello" // set...
// 測試嵌套的對象
// observer(obj)
// obj.name // get...
// obj.name = "hello" // set...
// obj.age = { k:"kkkk" } // set...
// obj.age.k = "mmmm" // set...
複製代碼
在vue的路由跳轉中有兩種方式,分別是問號模式,和冒號模式,二者不能進行混合使用,
格式
傳值
:<router-link to="/user/detail?id=1">用戶1</router-link>
獲取值
:{{this.$route.query.id}}
注意
:使用問號進行傳值的時候不需在router中特別設置路由
格式
傳值
:<router-link to="/user/detail/2">用戶2</router-link>
配置router路由文件
path:"detail/:id",
獲取值
:{{this.$route.params.id}}
在全局中有三個路由守衛,分別是beforeEach
,beforeResolve
,afterEach
beforeEach
router.beforeEach((to, from, next) => {}
beforeResolve
router.beforeResolve((to, from, next) => {}
afterEach
router.afterEach((to, from) => {}
格式:
const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
beforeEnter: (to, from, next) => {
// ...
}
}
]
})
複製代碼
在組件的內部存在整合三個路由組件,分別是beforeRouteEnter
、beforeRouteUpdate
、beforeRouteLeave
beforeRouteEnter
不能
獲取組件實例this
beforeRouteUpdate
this
beforeRouteUpdate ((to, from, next) => {}
beforeRouteLeave
this
beforeRouteLeave((to, from, next) => {}
beforeEach
beforeRouterLeave
。beforeEach
守衛。beforeRouteUpdate
守衛 (2.2+)。beforeEnter
。beforeRouteEnter
。beforeResolve
守衛 (2.5+)。afterEach
鉤子。beforeRouteEnter
守衛中傳給 next 的回調函數。源碼
// 基於node的 node不支持import語法
// 默認環境變量 NODE_ENV 生產環境 production development
let path = require('path');
module.exports = {
// 配置開發環境(npm run serve)或生產環境(npm run build)url
publicPath:process.env.NODE_ENV ``= 'production'? 'http://www.abcd.cn':'/',
//打包後的資源放入的文件夾,默認未放入文件夾
assetsDir:'asserts',
//打包後生成的文件夾,默認是dist
outputDir:'./dist',
// 是否使用本身的內部模板 通常不使用
runtimeCompiler:false,
// 打包後刪除生成的.map文件 再也不使用sourcemap
productionSourceMap:false,
chainWebpack:config=>{
// 能夠獲取到webpack的配置 在增長一些本身的邏輯
// 配置目錄別名 別名叫+
config.resolve.alias.set('_c',path.resolve(__dirname,'src/components'));
config.resolve.alias.set('_v',path.resolve(__dirname,'src/views'));
},
//webpack配置,到時候會合併到默認的webpack中。
configureWebpack:{ // webpack-merge
plugins:[],
module:{}
},
// 開發 服務時使用 上線時不須要 解決跨域的問題
devServer:{
proxy:{
'/api/getUser':{
target:'http://localhost:3000',
pathRewrite:{
'/api':''
}
}
}
},
//第三方插件的配置
pluginOptions: {
'style-resources-loader': {
preProcessor: 'less',
patterns: [
path.resolve(__dirname,'src/assets/common.less')
]
}
}
}
複製代碼
源碼
let express = require('express');
let app = express();
// 在後端配置,讓全部的人均可以訪問個人api接口
app.use('*', function (req, res, next) {
// 容許哪些客戶端來訪問我
res.setHeader("Access-Control-Allow-Origin","*");
// 容許能夠添加哪些頭,而後來訪問我
res.setHeader("Access-Control-Allow-Headers","*");
// res.header('Access-Control-Allow-Headers', 'Content-Type,Authorization');
// 容許哪些方法來訪問我
res.setHeader("Access-Control-Allow-Methods","OPTIONS,PUT,DELETE");
// res.header('Access-Control-Allow-Methods', '*');
// 能夠每隔半小時,來發送一個options請求--試探請求
res.setHeader("Access-Control-Max-Age","1800");
// 請求的類型編碼
res.header('Content-Type', 'application/json;charset=utf-8');
// 容許客戶端攜帶憑證,處理cookie信息,若是有,而且不對每次請求都新開一個session
res.setHeader("Access-Control-Allow-Credentials",true);
next();
});
複製代碼
路由的元信息通常可用於權限的校驗
定義路由的時候能夠配置 meta
字段
配置meta字段,該字段配置爲對象信息
一個路由匹配到的全部路由記錄會暴露爲 $route
對象 (還有在導航守衛中的路由對象) 的 $route.matched
數組。所以,咱們須要遍歷 $route.matched
來檢查路由記錄中的 meta
字段。
示例: