Vue3 入门

1 项目介绍

之前跟着实战项目做了Vue2的项目,由于对Vue学艺不精,以个人能力比较难跟着Vue2做Vue3项目,且Vue3可参考的博客对Vue基础比较高。故现在把Vue3实战关键知识点记录下来,仅作学习用途。
本项目是一个用Vue3实现的待做任务清单。点击网页的按钮跳转到清单页面(主要页面)。在清单页面,可以在上方输入框内输入待做任务:当input不在列表中时在列表中生成任务。点击任务前面的checkbox表示任务已完成。鼠标在当前行时改变背景颜色且显示删除链接,点击删除实现删除任务的功能。最底下是任务和已完成的数量统计,以及清除已完成按钮。

2 新建项目

2.1 新建

cmd进入新建项目的地址,输入

Vue3 create 项目名称

选择Manually select features,自定义Vue版本、用到的features(比如Vuex/Router/Babel等)、以及后续设置。

cd 项目名称

进入项目文件夹,运行

npm run serve

命令即可运行vue项目。

2.2 目录结构

Vue目录
整个文件目录:node_modules项目依赖;public中的.ico文件是浏览器标签页最左侧的图标,html文件是项目最终的呈现页面;babel.config.js管理babel(转义语法);package.json包管理;vue.config.js 设置。
src目录介绍
src文件: assets静态文件,components组件,router 配置路由,store状态,views路由组件, App.vue是根组件,main.js是入口js文件。
由于是单页面网页,实际上把vue的主页放入publc/index.html的id="app"的div元素。

2.3 vue文件结构

vue文件分为三块:template 主要写HTML,script 主要写js,style 写样式。
其中template标签只能有一个子节点,若有多个标签应该写入一个div中。

3 组件

在components文件夹新建三个组件的文件夹,每个文件夹新建相应的Vue文件。
在Views文件夹下的HomeView.vue当成主页面,在script标签中输入import引入三个组件,@指代src文件夹,比如

import 组件 from ‘@/components/组件文件夹/组件’。

3.1 组件基本设置

import 组件名 from 组件路径
import {defineComponent,ref} from 'vue'

export default defineComponent {
name: 'Home',
props: { // 父组件的传值

},
components: {

},
setup(props, ctx) { //处理数据
	let a = ref('sd')
	let b = ref(3)
    return {	
      a,
      b
    }
}

注意setup中的数据一定要写入return,此时这几个引入的组件就可以像html标签一样在template标签中使用了。比如{{a}}。类似之前vue2中写的: script标签中的export default中的data {}中的变量就能在html中使用了。

3.2 数据

3.2.1 ref

定义单个数据 ,主要用于setup函数中

import {ref} from 'vue'  //首先引入ref
setup(props, ctx) {
    let num = ref(4)
    let arr = ref(['a','v','t'])  //ref定义数组
    let obj = ref({  //ref定义对象
      age: 10,
      name: 'aaa'
    })
    return {	//要有返回,才能在html中使用
      num,	//实际上是键值对num: num,由于两个值相同因此可以简写
      arr,
      obj
    }
  }

注意:在方法中访问ref定义的数据的值要使用value属性,如a.value

3.2.2 reactive

实际上是一个对象,比ref更便捷, 使用数据需要加前缀,如下面要使用obj对象需要写成 data.obj

import {reactive} from 'vue' //同样要先引入
setup(props, ctx) {
    let data = reactive({
      str: 'obj',
      arr: ['q','t','9','t','y'],
      obj:{
        size: 10,
        width: 20,
        id: '124'
      }
    })
    return {
      data
    }
  }
3.2.3 toRefs

和reactive组合使用,可以简化前缀。如果使用的时候不想要前缀,可以使用toRefs。注意:里面的变量名不能和其他单独定义的变量重名。

import {toRefs} from 'vue' //引入
// 前面同上
return {
      // data
      ...toRefs(data)
    }

3.3 方法

箭头函数

let 方法名 = (参数) => {

}

4 Vuex状态管理

4.1 基础

4.1.4 state基础设置 createStore & useStore
//  store/index.js
import { createStore } from 'vuex'

export default createStore({
	state: { //定义状态
		name: 'js'
	},
// 同步修改状态
mutations: {
	setName(state, payload) {
	state.name = payload
	}
},
// 异步提交mutations
actions: {
	asyncSetName(store, params) {
		setTimeout(() => {
			// commit是调用mutations的方法
			store.commit('setName', params)
			}, 2000)
	}
},
// 模块
modules: {
}

})

通过计算属性得到vuex中定义的数据,此时在该页面template标签可以使用list

// 主页面比如Home.vue
<script scoped lang="scss">
import { useStore } from 'vuex'
// 通过computed得到store/index.js中的state字段里的list值
setup() {
	let state = useStore()
	let list = computed(() => {
		return store.state.list
	})
	return {
		list
	}
}
</script>
4.2.2 computed计算

必须有返回值,调用使用函数名即可。

<template>
	<div>
		<!-- 使用computed计算只需要调用函数名-->
		{{a}}+{{b}} 两数之和为 {{add}}
	</div>
</template>

<script>
import {defineComponent, computed, ref} from 'vuex'
export default defineComponent {
	name: '',
	props: {},
	components: {},
	setup() {
		let a = ref(1)
		let b = ref(5)
		let add = computed(() => {
			return a.value + b.value
		})
		return {
			a,
			b,
			add
		}
	}


}

</script>

5 路由

5.1 router文件夹下的index.js

哈希模式createWebHashHistory比历史模式在url上多一个#

import { createRouter, createWebHistory } from 'vue-router'
import HomeView from '../views/HomeView.vue'

// 配置路由
const routes = [
  {
    path: '/',
    name: 'home',
    component: HomeView
  },
  {
    path: '/about',
    name: 'about',
    // route level code-splitting
    // this generates a separate chunk (about.[hash].js) for this route
    // which is lazy-loaded when the route is visited.
    // 按需引入组件
    component: () => import(/* webpackChunkName: "about" */ '../views/AboutView.vue')
  }
]

const router = createRouter({
  history: createWebHistory(process.env.BASE_URL), //历史模式
  routes: routes //同名可以简写成routes
})

export default router

5.2 组件使用路由

在需要跳转的组件页面,使用router自带的函数,比如back, push, go。这里只显示和路由跳转有关的代码,实现了点击按钮就跳转到about页。

<template>
  <div>
    <button @click="goto">跳转到ABOUT</button>
  </div>
</template>

<script>
import {useRouter} from 'vue-router'

export default defineComponent({
  setup(props, ctx) {
    let router = useRouter()
    // 在按钮中定义的点击事件触发goto跳转函数
    let goto = () => {
      // 使用router自带的push函数,参数为router文件夹下js文件中定义的path
      router.push('/about')
    }
    return {
      goto
    }
  }
})
</script>

5.3 路由传参

使用router对象的push函数传递参数的两种办法。

5.3.1 query传参

会在地址栏显示参数值,刷新后值还在,参数传递过去的类型是string,有path/name其一即可

router.push({
				// 这里选择path或name即可
                path: '/home',
                query: {
                    name: name.value,
                    num: num.value,
                    obj: JSON.stringify(obj.value)
                }
            })
5.3.2 params传参

地址栏不显示参数,刷新后值消失,要求有name。其中name属性是router中js文件的name属性值。

router.push({
				// params传参必须是name
                name: 'home',
                params: {
                    name: name.value,
                    num: num.value,
                    obj: JSON.stringify(obj.value)
                }
            })
5.3.3 接收参数

在接收参数的组件中接收参数的相关代码,其中route是当前路由对象。

<script>
...
import {useRoute} from 'vue-router'
export default defineComponent({
 ...
  setup() {
    // route是当前路由对象。可以接收query传递的参数。
    let route = useRoute()
    // 这是query传参的接收
    console.log(route.query.num)
    // 这是params
    console.log(route.params.num)
   ...
    return {

    }
  }
})
</script>

6 生命周期

setup 组件创建的过程
onMounted 组件挂载的过程。数据、dom。作用:发请求; 初始化数据,接收路由传参。
onUnmounted 组件卸载的生命周期。作用:清除定时器、闭包函数…

7 父子组件传参

7.1 父组件传值

父组件把要传的参动态绑定,子组件通过props接收。如 :msg=‘msg’, 前者:msg是子组件接收参数存储的对象, 后者msg是父组件中要传参的名称。
在子组件中设置props,必须要设置数据类型校验。
然后在setup函数中设置参数props,此时直接用props.msg即为父组件的传参。子组件要显示该参数只需要写{{msg}}。

// 父组件的前端样式,动态绑定子组件,传递参数给子组件的msg对象
<child :msg='msg'></child>

// 子组件的前端 使用msg即可直接引用父组件传值
{{msg}}

// 子组件的脚本
import { defineComponent , ref , onMounted} from 'vue'
export default defineComponent({
    name: 'child',
    // props接收父组件的传值
    props: {
        msg: {
            // 数据类型校验
            type: String
            // 参数是否必传,默认F
            // required: True,
            // default: '默认值'
        }
    },
    setup(props, ctx) {
    	// 打印props的msg对象
        console.log(props.msg)
        let childMsg = ref('我是子组件的数据')
        let childNum = ref(11)
        let send = () => {
            // 通过ctx.emit分发事件 第一个参数是事件名称,第二个是数据
            ctx.emit('send', childMsg.value)
        }
        // 分发事件可以通过按钮点击事件触发,也可以在onMounted触发
        onMounted (() => {
            ctx.emit('send', childMsg.value)
            // 传递多个参数 1.数组 2.对象
            ctx.emit('sen', [childMsg.value, childNum.value])
            ctx.emit('s', {
                msg: childMsg.value,
                num: childNum.value
            })
        })
        return {
            childMsg,
            childNum,
            send
        }
    },
})

7.2 子组件传值

子组件通过ctx的emit分发事件传值,第一个参数是事件名称,第二个是数据;分发事件可以通过按钮点击事件触发,也可以在onMounted触发。传递多个参数时, 1.数组 [obj1.value,obj2.value…] 2.对象 {name1: obj1.value,name2: obj2.value…}。父组件通过@事件设置回传函数获取参数,@事件名即emit设置的第一个参数。

// 父组件前端
<child @sen='send'></child>

// 父组件脚本
setup() {
		...
        // 父组件接收子组件传值 通过send函数获取参数
        let send = (val) => {
            console.log(val)
        }
        return {
            ...
            send
        }
    },



// 子组件前端 
<button @click="sen">传值给父组件</button>

// 子组件的脚本
import { defineComponent , ref , onMounted} from 'vue'
export default defineComponent({
  	...
    setup(props, ctx) {
        let childMsg = ref('我是子组件的数据')
        let childNum = ref(11)
        let sen = () => {
            // 通过ctx.emit分发事件 第一个参数是事件名称,第二个是数据
            ctx.emit('send', childMsg.value)
        }
        // 分发事件可以通过按钮点击事件触发,也可以在onMounted触发
        onMounted (() => {
            ctx.emit('send', childMsg.value)
            // 传递多个参数 1.数组 2.对象
            ctx.emit('sen', [childMsg.value, childNum.value])
            ctx.emit('s', {
                msg: childMsg.value,
                num: childNum.value
            })
        })
        return {
            childMsg,
            childNum,
            send
        }
    },
})
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值