码文不易啊,转载请带上本文链接呀,感谢感谢 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 内容,只是我通过一段时间的学习,做的自我总结,以便学习和复习,写的不准确之处还望大神们能留言指正