vue3.0学习记录和实战项目
vue3.0学习记录和实战项目
前言
在掘金上摸鱼看到了“一个基于vue3+vite+ts的完整项目”的文章,好了我也要开始搞一搞vue3.0,反正最近打算搞个新项目,干脆就用新的;
于是开始摸鱼看文章了,现在也很多关于3.0的文章看看,(学习中,不对的,欢迎纠正)
文档:.官方(应该是吧)
Vue 组合式 API:https://composition-api.vuejs.org/zh/api.html
安装
- 方式1(使用Vite安装)
可以康康我的上一篇vite 搭建 Vue3.0项目 - 方式2(使用Vue-cli安装),然而这个项目是用的Vue-cli安装的
脚手架 vue-cli:
npm install -g @vue/cli # OR yarn global add @vue/cli
vue create hello-vue3
# select vue 3 preset
- 1
- 2
- 3
目前的了解(值得注意的新特性)
this指向的变化
- Vue2.0 this直接指向组件实例
- Vue3.0 this指向组件代理对象,代理对象在指向组件实例
2.x vs 3.0 钩子函数
setup
新的 setup 组件选项在创建组件之前执行,一旦 props 被解析,作为在组件内使用 Composition API 的入口点。从生命周期钩子的视角来看,它会在 beforeCreate 钩子之前被调用。
!注意:由于在执行 setup 时尚未创建组件实例,
因此在 setup 选项中没有 this。这意味着,除了 props 之外,
你将无法访问组件中声明的任何属性——本地状态、计算属性或方法。
响应式数据:Vue3.0则需要在setup 中通过ref或者reactive 来声明响应式数据。
- 1
- 2
- 3
- 4
- 5
setup 选项应该是props,context
- props:props 是响应式的,当传入新的 prop 时,它将被更新,但是不能使用 ES6 解构,因为它会消除 prop 的响应性,如果需要解构 prop,可以通过使用 setup 函数中的 toRefs 来安全地完成此操作
- context:context是一个普通的对象(不是响应式的)并且暴露出3个组件属性: 1. arrts 2.emit 3.slots
从 setup 返回的所有内容都将暴露给组件的其余部分 (计算属性、方法、生命周期钩子等等) 以及组件的模板。
export default {
components: {},
props: {
user: { type: String }
},
setup(props,{attrs, slots, emit}) {
console.log(props) // { user: '' }
return {} // 这里返回的任何内容都可以用于组件的其余部分
}
// 其余部分
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
ref
ref 是一个函数,它接受一个参数值并返回一个响应式且可改变的 ref 对象。ref 对象拥有一个指向内部值的单一属性 .value。而ref只能监听简单类型的变化,不能监听复杂类型的变化(对象/数组)。 它的本质是reactive,当我们给ref函数传递一个值时,ref函数会自动将ref转换成reactive
从 setup 返回的 refs 在模板中访问时是被自动解开的,因此不应在模板中使用 .value
import { ref } from 'vue'
const counter = ref(0)
console.log(count.value) // 0
count.value++
console.log(count.value) // 1
如果传入 ref 的是一个对象,将调用 reactive 方法进行深层响应转换。
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
isRef
isRef用于判断变量是否为ref对象。isRef(数据),返回true或者是false。
import {isRef} from 'vue'
- 1
reactive
接收一个普通对象然后返回该普通对象的响应式代理。
/**
*@reactive:处理的是对象的双向绑定, 对象不能被解构或展开,一旦被解构或者展开,返回的值将失去响应式
*/
export default {
components: {},
props: {
user: { type: String }
},
setup(props) {
console.log(props) // { user: '' }
const formData = reactive({
user: "",
password: "",
companyName: ""
});
return {
formData,
formData.user //解构或展开这里将失去响应式
}
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
isReactive
检测一个数据是否是reactive类型的。可以用isReactive(数据),返回true或者false。
import {isReactive} from 'vue'
- 1
toRefs
toRefs用于将一个reactive对象转化为属性全部为ref对象的普通对象。
const state = reactive({
foo: 1,
bar: 2
})
const stateAsRefs = toRefs(state)
/*
Type of stateAsRefs:
{
foo: Ref<number>,
bar: Ref<number>
}
*/
// toRefs在setup或者Composition Function的返回值时可以保证在使用解构语法之后对象依旧为相应式
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
watch 响应式更改
使用从 Vue 导入的 watch 函数执行相同的操作。它接受 3 个参数:
一个响应式引用或我们想要侦听的 getter 函数
一个回调
可选的配置选项
import { ref, watch } from 'vue'
const counter = ref(0)
watch(counter, (newValue, oldValue) => {
console.log('The new counter value is: ' + counter.value)
})
- 1
- 2
- 3
- 4
- 5
- 6
项目
登录页面
<template>
<div class="login">
<div class="login-mask">
<div class="login-form-wrap">
<div class="login-form">
<div class="login-form-content">
<header>
<!-- <img src="@/assets/logo.png" /> -->
<h1>welcome 登录界面</h1>
</header>
<a-form :model="formData" :rules="formRules" ref="formRef">
<a-form-item name="companyName">
<a-input
size="large"
v-model:value="formData.companyName"
placeholder="请输入公司名称"
/>
</a-form-item>
<a-form-item name="account">
<a-input
size="large"
v-model:value="formData.account"
placeholder="请输入用户名"
/>
</a-form-item>
<a-form-item name="password">
<a-input-password
autofocus="autofocus"
size="large"
visibilityToggle
v-model:value="formData.password"
placeholder="请输入密码"
/>
</a-form-item>
<a-form-item>
<a-button
type="primary"
size="large"
block
@click="login"
:loading="formState.loading"
>登录</a-button
>
</a-form-item>
</a-form>
</div>
</div>
</div>
</div>
</div>
</template>
<script lang="ts">
/**
* @reactive : 处理的是对象的双向绑定, 对象不能被解构或展开,一旦被解构或者展开,返回的值将失去响应式
*
* @ref : 处理js基础类型的双向绑定,其实ref的实现原理也只是对基础类型进行对象化封装,
* 把数据放在{ value: 基础值 }里,再添加一个ref标识属性用来区分
*/
import { defineComponent, reactive, ref, unref, toRaw } from "vue";
import { useRouter, RouteLocationRaw } from "vue-router";
import { notification } from "ant-design-vue";
import API from "../../api/api";
import { Md5 } from "ts-md5";
export default defineComponent({
/** 所有的代码逻辑将在setup方法中实现,并且不再有this */
setup() {
/** 返回值 */
const formData = reactive({
account: "",
password: "",
companyName: ""
});
const formRef = ref<any>(null);
const formState = reactive({
loading: false
});
const formRules = reactive({
companyName: [
{ required: true, message: "请输入公司名称", trigger: "blur" }
],
account: [{ required: true, message: "请输入账号", trigger: "blur" }],
password: [
{ required: true, message: "请输入密码", trigger: "blur" },
{
pattern: /^(?![0-9]+$)(?![a-zA-Z]+$)[0-9A-Za-z]{6,}$/,
max: 12,
min: 6,
message: "密码应该在6-12长度之间字母和数字的组合",
trigger: "blur"
}
]
});
/** 路由 */
const router = useRouter();
const toPage = (path: RouteLocationRaw) => router.push(path);
/** 方法 */
async function handleLogin() {
const form = unref(formRef);
if (!form) return;
formState.loading = true;
try {
const data = await form.validate();
// 调用登录接口API
API.loginAPI
.login(
toRaw({
companyName: data.companyName,
password: Md5.hashStr(data.password),
workerId: data.account
})
)
.then(response => {
console.log("loginInfo: ", response);
localStorage.token = response.data.token;
localStorage.login_userName = data.account;
localStorage.login_companyName = data.companyName;
toPage("/layout");
setTimeout(() => {
notification["success"]({
message: "登录成功",
description: "尊敬的" + data.account + "用户,欢迎回来!"
});
}, 500);
})
.catch(e => {
console.log(e);
});
} catch (error) {
notification["error"]({
message: "登录失败",
description: "请检查您的用户名或者密码是否正确!"
});
} finally {
formState.loading = false;
}
}
/** 返回值 */
return {
formRef,
formData,
formState,
formRules,
login: handleLogin
};
}
});
</script>
<style lang="stylus" scoped>
// 样式就省略吧
</style>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- 74
- 75
- 76
- 77
- 78
- 79
- 80
- 81
- 82
- 83
- 84
- 85
- 86
- 87
- 88
- 89
- 90
- 91
- 92
- 93
- 94
- 95
- 96
- 97
- 98
- 99
- 100
- 101
- 102
- 103
- 104
- 105
- 106
- 107
- 108
- 109
- 110
- 111
- 112
- 113
- 114
- 115
- 116
- 117
- 118
- 119
- 120
- 121
- 122
- 123
- 124
- 125
- 126
- 127
- 128
- 129
- 130
- 131
- 132
- 133
- 134
- 135
- 136
- 137
- 138
- 139
- 140
- 141
- 142
- 143
- 144
- 145
- 146
- 147
- 148
- 149
- 150
- 151
项目地址
GitHub:https://github.com/peiyu-ye/vue3.0-front(哈哈哈,觉得有用给个 Star)