Vite 法语意为 "快速的",发音 /vit/,下一代前端开发与构建的工具,等于现在的webpack。
第一感觉:npm run dev 的时候跑项目飞快
创建vue3项目
# npm 版本, 安装vu3之前需要检查npm版本号,对号入座:
npm -v
# npm 6.x
npm init vite@latest my-vue-app --template vue
# npm 7+, 需要额外的双横线:
npm init vite@latest my-vue-app -- --template vue
安装依赖
npm i
运行项目
npm run dev
VSC安装vue3配套插件Volar
相信使用 vscode 和 vue2的同学对 vetur 这个插件一定不会陌生。
认识页面 template script style
<script setup>
</script>
<template>
</template>
<style scoped>
</style>
从上面的代码可以看到,<script setup></script>标签和<template></template>标签顺序已经更换了,但我还是习惯vue2顺序,且<script setup></script>标签中必须使用setup关键字定义。
vue3响应式视图更新数据 ref
不同于vue的data和methods,vue3是这样创建响应式对象的,在vue3中需要用到ref才能触发视图的更新。
<template>
{{msg}}
<button @click="changeName">更换名字</button>
</template>
<script setup>
import {ref} from 'vue'
let msg = ref('李白')
function changeName(){
msg.value = '杜甫'
}
</script>
<template>
{{user.username}}
{{user.age}}
<button @click="changeAge">更换</button>
</template>
<script setup>
import {ref} from 'vue'
let user = ref({
username:'李白',
age: 18
})
function changeAge(){
user.value.age = 14
}
</script>
从上面2个demo来看,我们vue3的数据响应式需要如此来搞,是不是发现似乎有些繁琐?逻辑有些古怪?
响应式reactive 取代ref,恢复正常的写法,相当于vue2的data
<template>
{{user.username}}
{{user.age}}
<button @click="changeName">更换</button>
</template>
<script setup>
import {reactive} from 'vue'
const user = reactive({
username:'李白',
age: 18
})
function changeName(){
user.username = '王安石'
}
</script>
reactive解包写法
<template>
<button @click="changeName">更换</button>
{{user.username}}
{{user2.username}}
</template>
<script setup>
import {ref,reactive} from 'vue'
const user = ref({
username:'李白',
})
const user2 = reactive(user.value)
function changeName(){
user2.username = '杜甫'
}
</script>
这里关注到 {{user2.username}}
事件对象和传递参数
<template>
{{user}}
<button @click="changeName('江山',$event)">更换</button>
</template>
<script setup>
import {ref} from 'vue'
let user = ref('李白')
function changeName(username,event){
user.value = username
//console.log(event);
console.log(username,event);
}
</script>
计算属性
反序输出字符串
<template>
{{reMsg}}
</template>
<script setup>
import {ref,computed} from 'vue'
let msg = ref('hello')
const reMsg = computed(() => {
return msg.value.split('').reverse().join('')
})
</script>
侦听属性
<template>
{{msg}}
{{user.name}}
</template>
<script setup>
import {ref,reactive,watch} from 'vue'
let msg = ref('hello')
let user = reactive({
name:'雷柏',
age: 20
})
watch(msg,(newValue,oldValue)=>{
console.log(newValue);
console.log(oldValue);
})
watch(
()=>user.name,
(newValue,oldValue)=>{
console.log(newValue);
console.log(oldValue);
}
)
</script>
父子组件传值:子组件用defineProps接收父组件传过来的值
值得注意的是,vue3中引入组件不在需要注入,直接Import 引入,使用即可
子组件
<template>
{{title}} --- {{content}}
</template>
<script setup>
import { defineProps } from 'vue';
const props = defineProps({
title: String,
content: String
})
</script>
<style scoped>
</style>
父组件
<template>
<HelloWorld :title="article.title" :content="article.content"></HelloWorld>
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import { reactive } from 'vue';
let article = reactive({
title: '满江红',
content: '岁岁年年花相似'
})
</script>
父子组件传值:子组件发布自定义事件,通知父组件修改值 defineEmits
子组件发布事件
<template>
{{title}} --- {{content}}
<button @click="btn">修改</button>
</template>
<script setup>
import { defineProps,defineEmits } from 'vue';
const props = defineProps({
title: String,
content: String
})
const emit = defineEmits(['modifyContent','modifyTitle'])
function btn(){
emit('modifyContent')
emit('modifyTitle')
}
</script>
<style scoped>
</style>
父组件修改值
<template>
<HelloWorld
:title="article.title"
:content="article.content"
@modifyContent = "changeContent()"
@modifyTitle = "changeTitle()"
></HelloWorld>
</template>
<script setup>
import HelloWorld from './components/HelloWorld.vue'
import { reactive } from 'vue';
let article = reactive({
title: '满江红',
content: '岁岁年年花相似'
})
function changeContent(){
article.title = '秦时明月'
}
function changeTitle(){
article.content = '巴山楚水凄凉地'
}
</script>
路由的创建与使用 vue3需要4.0版本的路由,store也是
安装:
npm i vue-router
创建路由脚本:src目录下>创建router目录>index.js
编写脚本:/src/router/index.js
import {
createRouter,
createWebHashHistory,
createWebHistory
} from 'vue-router'
import Home from '../views/Home.vue'
import About from '../views/About.vue'
import Buycart from '../views/Buycart.vue'
const routes = [
{
path: '/home',
component: Home,
name: 'home'
},
{
path: '/about',
component: About,
name: 'about'
},
{
path: '/buycart',
component: Buycart,
name: 'buycart'
},
{
path: '/product',
component: () =>import('../views/Product.vue'),
name: 'product'
}
]
const router = createRouter({
history: createWebHistory(),
routes,
})
export default router
main.js
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
createApp(App).use(router).mount('#app') //use必须要在mount之前
路由使用
<template>
<div>
<router-view></router-view>
<router-link to="/home">跳转首页</router-link>
<button @click="router.push('/product')">跳转至产品页面</button>
<button @click="goTo">跳转至产品页面</button>
</div>
</template>
<script setup>
import { useRoute,useRouter } from 'vue-router';
let route = useRoute()
let router = useRouter()
function goTo(){
console.log(route);
router.push('/product')
}
</script>
<style scoped>
</style>
安装vuex,需要下一代版本,官网默认也是4.0x版本
npm i vuex@next --save
创建目录/src/store/index.js
import { createStore } from 'vuex'
// 创建一个新的 store 实例
const store = createStore({
state () {
return {
count: 0
}
},
mutations: {
increment (state,payload) {
state.count += payload
}
},
getters:{
totalPrice(state) {
return state.count*99.9
}
},
actions:{
asyncAdd(store,payload){
setTimeout(()=>{
store.commit('increment',payload)
},1000)
}
}
})
export default store
main.js引入
import { createApp } from 'vue'
import App from './App.vue'
import router from './router/index'
import store from './store/index'
createApp(App).use(router).use(store).mount('#app') //use必须要在mount之前
页面使用
<template>
<div>
<h1>购物车</h1>
<h2>商品数量{{store.state.count}}</h2>
<h2>商品总价{{store.getters.totalPrice}}</h2>
<button @click="addProd">添加商品数量+2</button>
<button @click="asyncAddProd">异步添加商品数量+10</button>
</div>
</template>
<script setup>
import { useStore } from 'vuex';
let store = useStore()
function addProd(){
store.commit('increment',2)
}
function asyncAddProd(){
store.dispatch('asyncAdd',10)
}
</script>
suspense内置新增组件,defineAsyncComponent异步封装组件
调用组件
<template>
<!-- suspense内置新增组件,数据加载回来的时做些什么,数据没回来之前做些什么 -->
<suspense>
<template #fallback>
<h1>Loading</h1>
</template>
<template #default>
<HomeCom></HomeCom>
</template>
</suspense>
</template>
<script setup>
import * as api from '../api/index'
// vue3异步请求
import { onMounted,defineAsyncComponent } from 'vue';
//异步请求组件
const HomeCom = defineAsyncComponent(()=>import('../components/HomeCom.vue'))
onMounted(async() =>{
let res = await api.getHomepage()
//console.log(res);
})
</script>
组件
<template>
<h1>首页</h1>
<ul>
<li v-for="(item,i) in hero">
<h3>{{item.category}}</h3>
</li>
</ul>
</template>
<script setup>
import * as api from '../api/index'
import { reactive } from 'vue'
let res = await api.getHomepage()
const hero = reactive(res.hero)
</script>
网友评论