vue3.0学习记录和实战项目

作者 : admin 本文共5593个字,预计阅读时间需要14分钟 发布时间: 2021-10-27 共4人阅读

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)


滴石it网-Java学习中高级和架构师教程_Java企业级开发项目实战下载 » vue3.0学习记录和实战项目

常见问题FAQ

发表评论

开通VIP 享更多特权,建议使用QQ登录