碼文不易啊,轉載請帶上本文連結呀,感謝感謝 https://www.cnblogs.com/echoyya/p/14394057.html
在2020年9月中旬,vue.js釋出了3.0正式版,在不久的將來,VUE3.0 也終將成為大前端的必然趨勢,
環境搭建
-
node
版本要求:Node.js8.9
或更高版本 ,輸入node -v
檢視node版本 -
vue-cli
版本:達到vue-cli4.5.0
以上,可建立vue3.0的專案,支援體驗vue3.0的新特性,(3.x Preview)
,vue -V
檢視腳手架版本 -
終端輸入:
vue create project_name
核心知識
一 、元件的定義和使用
元件:是維護單一功能,可複用的單個個體,相同的樣式及邏輯即可抽離成元件,方便維護,複用性增強。也是vue3.0專案中,最核心的概念
defineComponent
:vue3.0中提供了一個函式返回傳遞給它的物件,最重要的是:在TypeScript下,給予了元件 正確的引數型別推斷 。此處先不展開介紹,後續會總結 vue3.0 + ts。
setup
:元件的啟動函式,兩個引數: props(父元件傳遞的資料)
,content ( 上下文物件)
,最後return 定義的資料,方法,鉤子函式等,且setup中 沒有this,不能訪問this
<script>
import { defineComponent } from 'vue'
export default defineComponent ({
setup (props, content) {
// TODO 資料,方法,鉤子函式等
return { }
}
})
</script>
二、資料的定義和使用
ref
:定義單個資料
,接受一個引數值並返回一個響應式且可改變的ref 物件
。ref 物件擁有一個指向內部值的單一屬性.value
。
import { ref } from 'vue'
export default {
setup () {
let num1 = ref(10) // Number
let name1 = ref('Echoyya') // String
let arr1 = ref(['a','d','c','d']) // Array
let obj1 = ref({age:20}) // Object
// 獲取及改變 ref物件的值,獲取內部值的單一屬性 value
console.log(num1.value) // 10
num1.value++
console.log(num1.value) // 11
return {
//使用 ref 定義的資料,需要直接 return
num1,name1,arr1,obj1
}
}
}
reactive
: 用於建立響應式資料,接收一個普通物件然後返回該普通物件的響應式代理
,即雙向資料繫結,-
使用 reactive 定義的資料,不需要逐一 return,可以使用 ES6 的擴充套件運算子。
-
解構會破壞雙向資料繫結的特性, 變更為單向資料繫結
-
解決:vue3.0中新增了新特性,可對當前的資料進行轉換。將其轉換為響應式資料,
toRefs
將資料包裹即可轉換為響應式資料
-
import { reactive, toRefs } from 'vue'
export default {
setup () {
let data = reactive ({
num:33,
arr:['a','d','c','d'],
obj:{age:20},
})
// 獲取及改變:reactive 定義的資料,呼叫時直接 reactive變數名.資料名,
console.log(data.num) // 33
data.num++
console.log(data.num) // 34
return {
...toRefs(data)
}
}
}
三、方式的定義和使用
建立的方法仍然需要 return
<template>
<div>
<p><button @click="clickNum">{{num}}</button></p>
<p><button @click="clickNum1">{{num1}}</button></p>
<p><button @click="singleMethod">{{name}}</button></p>
</div>
</template>
<script>
import { reactive, ref, toRefs } from 'vue'
export default {
setup () {
let num1 = ref(10)
let name = ref('Echoyya')
let data = reactive({
num:33,
})
// 定義多個方法,不需要逐一 return
let methods = {
clickNum1: () => {
num1.value++
console.log(num1.value);
},
clickNum : () => {
data.num ++
console.log(data.num);
}
}
// 定義單個方法,需要return
let singleMethod = () => {
console.log(name.value)
}
return {
num1,
name,
singleMethod,
...toRefs(data)
...methods,
}
}
}
</script>
四、路由的定義、使用和傳參
- /src/router/index.js:在路由檔案中使用了
createRouter
方法
import { createRouter } from 'vue-router'
const routes = [
{
path: '/',
name: 'Home',
component: () => import('../views/Home.vue')
},
{
path: '/about',
name: 'About',
component: () => import('../views/About.vue')
}
]
const router = createRouter({
routes
})
export default router
- home元件中使用,路由跳轉及傳遞引數
<template>
<div>
<p><button @click="gotoQuery">query跳轉</button></p>
<p><button @click="gotoParams">params跳轉</button></p>
</div>
</template>
<script>
import { useRouter } from 'vue-router'
export default {
setup (){
// router物件是全域性路由的例項。
let router = useRouter()
// 跳轉路由用push: 跳轉時可使用name 和 path,傳遞引數可使用query 和 params
let gotoQuery = () => {
// query: 可以使用name和path,引數顯示在位址列中, 且頁面重新整理引數仍在
router.push({
// name:'About',
path:'/about',
query:{
name:'Echoyya',
age: 25,
obj:JSON.stringify({gender:"f"})
},
})
}
let gotoParams = () => {
// params:只能使用name ,不顯示在位址列中,且頁面重新整理,引數清空 console.log(route.params); 列印空物件
router.push({
name:'Home',
params:{
name:'Echoyya',
age: 25,
obj:JSON.stringify({gender:"f"})
}
})
}
return {
gotoQuery,
gotoParams
}
}
}
- about元件中使用,接收路由引數
import { useRoute } from 'vue-router'
export default {
setup (){
// route物件表示當前的路由資訊,包含了當前 URL 解析得到的資訊。包含當前的路徑,引數,query物件等。
let route = useRoute()
console.log(typeof route.query.age) //string, query傳遞的引數都是string型別
console.log(route.query); //獲取query傳參
console.log(route.params); //獲取params傳參
return {}
}
}
五、父子元件傳值
-
父 to 子
:通過動態繫結屬性
的方式,子元件在props
中去接收, -
子 to 父
:通過ctx.emit('事件名稱', 傳遞的引數)事件分發
的方式, 父元件當中,呼叫子元件標籤上繫結自定義事件,其中包含一個引數,即子元件傳遞過來的資料-
ctx.emit('事件名稱', 傳遞的引數)事件分發
, ctx是 setup 函式的第二個引數,上下文物件 -
emit 只能接受兩個引數,其餘不生效,第一個引數:事件名稱,第二個: 傳遞的資料
-
事件分發,不一定要通過點選事件,也可使用鉤子函式等
-
需要傳遞多個引數時,emit第二個引數可選擇陣列或是物件
-
father.vue
<template>
<div class="wrapper">
<p>this is father components</p>
<p> 子元件傳遞的值:{{childMsg}}</p>
<!-- msg 自定義屬性,send 自定義監聽事件-->
<p><child :msg="msg" @send="getChildData"></child></p>
</div>
</template>
<script>
import { ref } from 'vue'
import child from '../components/child'
export default {
components:{
child
},
setup() {
let msg = ref('father元件資料')
let childMsg = ref('')
let getChildData = (data)=>{
childMsg.value = data
}
return {
msg,
childMsg,
getChildData
}
},
}
</script>
child.vue
<template>
<div>
this is child components
<p>父元件傳遞過來的值:{{msg}}</p>
<p><button @click="send">傳值給父元件</button></p>
</div>
</template>
<script>
import {ref,onMounted, reactive} from 'vue'
export default {
name:'child',
// props 接收的資料,不能直接修改,如props.xxx = yy
props:{
msg:{
type:String , // 資料型別校驗
require:true , // 是否必傳 預設false
default:'預設值' // require和default 有些衝突,即必填時,可不設定預設值
}
},
setup(props,ctx){
console.log(props.msg); // 父元件傳遞的資料:father元件資料
let childMsg = ref('child元件資料')
let data = reactive({
childNum:10
})
let send = ()=>{
ctx.emit('send',childMsg.value)
// ctx.emit('send',[childMsg.value,data.childNum]) // 陣列
// ctx.emit('send',{ // 物件
// msg:childMsg.value,
// num:data.childNum
})
}
return {
childMsg,
send,
...data
}
}
})
</script>
六、狀態管理的定義和使用
狀態管理即 VUEX
,為達到資料共享的目的
- /src/store/index.js:在狀態管理檔案中使用了
createStore
方法
import { createStore } from 'vuex'
export default createStore({
// 定義所需要的狀態
state: {
name: 'Echoyya',
},
// 同步修改state ,是方法,不能操作非同步操作(包括髮送請求及定時器等)
mutations: {
// 可接收兩個引數:一:state,二:需修改的值,payload(可選)
setName(state, payload) {
state.name = payload
},
},
// 提交 mutations
actions: {
// 可接收兩個引數 一:store, 二 要修改的值
asyncSetName(store, params) {
setTimeout(() => {
// commit 是提交mutation, 提交非同步的mutations方法
store.commit('setName', params)
console.log(store.state.name)
}, 2000)
}
},
// 模組化
modules: {}
})
- 元件中呼叫,VUEX運算元據
<template>
<div>
{{name}}===={{name1}}===={{name2}}
<p><button @click="setName">設定 name</button></p>
<p><button @click="asyncSetName">非同步設定 name</button></p>
</div>
</template>
<script>
import { reactive, ref, toRefs, computed } from 'vue'
import { useStore } from 'vuex'
export default {
setup (){
//通過 ref 方式
let name = ref(store.state.name)
// 計算屬性 方式
let name1 = computed(()=>{
return store.state.name + 'computed'
})
//reactive 方式
let data = reactive({
name2:store.state.name + '_reactive'
})
// 觸發 mutations
let setName = ()=>{
console.log(store.state.name) // Echoyya
store.commit('setName','nhyya')
console.log(store.state.name) // nhyya
}
// 觸發 action
let asyncSetName = ()=>{
store.dispatch('asyncSetName','nhyya1212')
}
return {
name,
name1,
...toRefs(data),
setName,
asyncSetName
}
}
})
</script>
七、常用的生命週期
-
setup:不需要引入的生命週期 ,表示元件建立的過程,且沒有this
-
onMounted:比
setup
稍微晚一些執行,表示元件掛載的過程,包括資料, dom元素等,是一個函式,需要傳入一個回撥函式執行,無引數。- 常用於:傳送請求、資料初始化的操作、接受路由傳遞的引數
-
onUnmounted:與
onMounted
相對應,元件解除安裝或銷燬(路由跳轉),常用於清除定時器等操作
較 VUE2.0 另有哪些改變?
-
3.0去掉了filter, 沒有beforeCreate created,用setup取代
-
setup裡沒有this
-
3.0相容IE12以上
-
可直接監聽陣列型別的資料變化
-
監聽的目標為物件本身,不需要像Object.defineProperty一樣遍歷每個屬性,有一定的效能提升
-
直接實現物件屬性的新增/刪除
-
重構 Virtual DOM:模板編譯時的優化,將一些靜態節點編譯成常量
-
另附上vue3.0 文件地址: https://v3.cn.vuejs.org/
上述內容並非全部 VUE3 內容,只是我通過一段時間的學習,做的自我總結,以便學習和複習,寫的不準確之處還望大神們能留言指正