Vue 3 基础|更新
VUE 3
VUE 3 官网:https://cn.vuejs.org/guide/quick-start.html
快速回顾
安装相关依赖
npm install -g @vue/cli vue-router
vue 架构回顾
创建一个项目,执行vue create your_project
后生成一系列文件夹。主要修改 src
文件夹就行。
src
├── App.vue
├── assets
│ └── logo.png
├── components
│ └── HelloWorld.vue
└── main.js
文件回顾:
main.js
用于注册router
,store
, 全局css
, 插件等,如:
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import ElementPlus from 'element-plus'
import 'element-plus/dist/index.css'
const app = createApp(App)
app.use(router)
.use(Element, {
size: Cookies.get('size') || 'medium',
})
app.mount('#app')
App.vue
该文件中主要用于配置大致架构,比如简单的使用 <router-view />
:
<template>
<div id="app">
<router-view />
</div>
</template>
<script>
export default {
name: 'App'
}
</script>
// main.js
import { createSSRApp } from "vue";
import App from "./App.vue";
export function createApp() {
const app = createSSRApp(App);
return {
app,
};
}
router.js
中配置 router 信息,具体可查看: vue-router。简单的 router 模板示例:
import xxx from ''
import Component2 from ''
import {createRouter}
常见问题
API 风格
vue 分为响应式和选项式两种 API 风好,两种风格的差异主要在 script
部分。
相关信息
当你在模板中使用了一个 ref,然后改变了这个 ref 的值时,Vue 会自动检测到这个变化,并且相应地更新 DOM。这是通过一个基于依赖追踪的响应式系统实现的。当一个组件首次渲染时,Vue 会 追踪 在渲染过程中使用的每一个 ref。然后,当一个 ref 被修改时,它会 触发 追踪它的组件的一次重新渲染。
通常,响应式会结合 <script setup>
使用,以此来暴露状态和方法:
<script setup>
import { ref } from 'vue'
const count = ref(0)
function increment() {
count.value++
}
</script>
<template>
<button @click="increment">
{{ count }}
</button>
</template>
变量或对象声明:
import { ref, reactive } from 'vue'
const count = ref(0)
// const isActive = ref(true)
count.value = 1
const state = reactive({ count ,other: 1}) // 用 reactive 追踪嵌套的变量
console.log(state.count) // 0
计算属性 computed
import { computed } from 'vue'
// 一个计算属性 ref
const publishedBooksMessage = computed(() => {
return xxx
})
定义传参 props
监听事件 emit
,加入要触发 'enlarge-text'
事件。
<!-- BlogPost.vue -->
<script setup>
defineProps(['title'])
defineEmits(['enlarge-text'])
</script>
<template>
<div class="blog-post">
<h4>{{ title }}</h4>
<button @click="$emit('enlarge-text')">Enlarge text</button>
</div>
</template>
调用父组件中调用 BlogPost
时,可以定义 enlarge-text
触发时,采取的行动:
<BlogPost
...
@enlarge-text="postFontSize += 0.1"
/>
条件渲染
通过 v-bind 可以动态渲染 class,来控制 styles 等。
<!-- class 绑定 -->
<div :class="{ red: isRed }"></div>
<div :class="[classA, classB]"></div>
<div :class="[classA, { classB: isB, classC: isC }]"></div>
v-bind
可以涵盖 class 部分的修改,可以使用 js 语法来实现添加或者删除 attr
。
<!-- 动态 attribute 名,比如复制 id="123" -->
<button :[key]="value"></button>
<!-- 在 script 部分定义 key 和 value -->
<!-- style 绑定 -->
<div :style="{ fontSize: size + 'px' }"></div>
<!-- 传递子父组件共有的 prop -->
<MyComponent v-bind="$props" />
列表渲染
<script setup>
const items = ref([{ message: 'Foo' }, { message: 'Bar' }])
</script>
<li v-for="item in items">
{{ item.message }}
</li>
或渲染对象:
<script setup>
const myObject = reactive({
title: 'How to do lists in Vue',
author: 'Jane Doe',
publishedAt: '2016-04-10'
})
</script>
<li v-for="(value, key) in myObject">
{{ key }}: {{ value }}
</li>
内置功能 Teleport
Transition
和 Teleport
可以用于实现一些全屏窗口切换的功能,比如搜索栏,状态提示栏,广告等。官方指南
详情
<button @click="open = true">Open Modal</button>
<Teleport to="body">
<transition>
<div v-if="open" class="modal">
<p>Hello from the modal!</p>
<button @click="open = false">Close</button>
</div>
</transition>
</Teleport>
<style>
</style>
动态渲染 component
如果某个组件的渲染时间非常长,那么可以使用动态 component 和 keepAlive 优化
详情
<script>
import Foo from './Foo.vue'
import Bar from './Bar.vue'
export default {
components: { Foo, Bar },
data() {
return {
view: 'Foo'
}
}
}
</script>
<template>
<KeepAlive include="a,b">
<component :is="view" />
</KeepAlive>
</template>
页面资源和 HOOK
整个 DOM 渲染的周期(渲染前,后;更新前,后)都可以添加钩子。官方链接。常用的有 mounted
, updated
等。
export default {
mounted() {
console.log(`the component is now mounted.`)
// this.some_methods()
}
}
import { onMounted, ref } from 'vue'
mounted(()=>{
console.log(`the component is now mounted.`)
// some_methods()
})
axios
请求发送
可以将 axios 包装成一个方法,而后通过 http
统一发送各种请求。
详情
setup_axios.js
import axios from 'axios'
const instance = axios.create({
baseURL: 'xxx',
timeout:1000,
headers: {'X-ucsom-Header': 'foobar'}
})
class RequestHandler {
getAll(input) {
return instance.get(`/sub_path/${input}`)
}
postMethod() {
return instance.post(`/sub_path`.{your_json:your_json})
}
}
export default new RequestHandler();
在 vue 组件中调用:
import RequestHandler from 'setup_axios.js'
some_method (){
RequestHandler.getAll(this.input).then(res=>{this.data = res.data}).catch()
}
元素监听
可以通过 watch 来监听某个定义好的参数. 官方指南。但监听器默认监听的是指针变动情况,如果需要监听嵌套的内容,需要加上 deep:true
export default {
data() {
return {
question: '',
answer: 'Questions usually contain a question mark. ;-)'
}
},
watch: {
// 每当 question 改变时,这个函数就会执行
question {
handler(newQuestion, oldQuestion){
if (newQuestion.includes('?')) {
this.getAnswer()
}
},
deep: true
}
}
}
<script setup>
import { ref, watch } from 'vue'
const question = ref('')
const answer = ref('Questions usually contain a question mark. ;-)')
// 可以直接侦听一个 ref
watch(question, async (newQuestion, oldQuestion) => {
if (newQuestion.indexOf('?') > -1) {
answer.value = 'Thinking...'
try {
const res = await fetch('https://yesno.wtf/api')
answer.value = (await res.json()).answer
} catch (error) {
answer.value = 'Error! Could not reach the API. ' + error
}
}
})
</script>
<template>
<p>
Ask a yes/no question:
<input v-model="question" />
</p>
<p>{{ answer }}</p>
</template>