做外贸产品上什么网站,域名网站建设,内江规划建设教育培训中心网站,知名广州网站建设目录 vue3简介整体上认识vue3项目创建Vue3工程使用官方脚手架创建Vue工程[推荐] 主要⼯程结构 数据双向绑定vue2语法的双向绑定简单表单双向绑定复杂表单双向绑定 CompositionAPI替代OptionsAPICompositionAPI简单不带双向绑定写法CompositionAPI简单带双向绑定写法setup简写⽅… 目录 vue3简介整体上认识vue3项目创建Vue3工程使用官方脚手架创建Vue工程[推荐] 主要⼯程结构 数据双向绑定vue2语法的双向绑定简单表单双向绑定复杂表单双向绑定 CompositionAPI替代OptionsAPICompositionAPI简单不带双向绑定写法CompositionAPI简单带双向绑定写法setup简写⽅式脚本单独写到ts⽂件中 Vue3中的数据双向绑定ref定义基础类型响应式数据reactive定义对象型响应式数据ref也可以定义对象型响应式数据(不推荐)通过toRef或toRefs函数将转出来的数据具备响应式能力标签的ref属性/ref绑定标签通过ref将当前DOM元素绑定给响应式变量父组件拿到自定义组件里的值子组件接收父组件传来的数据 VUE3⽣命周期Vue-Router组件路由机制基础使⽤路由⼯作模式replace嵌套路由路由传参query传参params传参 Pinia集中式状态存储理解状态创建store使⽤store操作数据storeToRefs声明响应式数据store的混合式写法 快速上⼿Element-Plus vue3快速上手指南 你只要会基础的HTMLJSCSS那么就可以上手Vue了。如果你会Java那么上手Vue非常轻松。如果你会Vue2那么上手Vue3会更加舒服。 vue3简介
官网地址https://vuejs.org/。中文官网 https://cn.vuejs.org/
Vue是什么易学易用性能出色适用场景丰富的 Web 前端框架。
Vue2已经于2023年12月31日停止维护。建议升级到Vue.js3.0版本。打包更小内存更少渲染更快。好消息是vue3向下兼容vue2的语法
Vue3于2020年9月18日发布代号One Piece 海贼王。久经磨砺
Vue3新特性组合式API(重点)更好的支持TypeScript(熟悉)状态存储框架Pinia(重点)新组件(了解)。。。。。详见官网
整体上认识vue3项目
创建Vue3工程
前置安装NodeJS。NodeJS版本最好在18.0以上。下载地址https://nodejs.org/en pslts长期支持的版本
vite简介类似于maven可以打包
1、所有功能组件都可以后续手动添加。 关于TypeScript在Vue中的TypeScript可以认为是在JS的基础上增加面向对象的能力。可以定义接口、类、抽象类等。
2、 npm install过程中会去node仓库下载很多依赖库放到项目本地node-modules目录。建议将npm源设定为淘宝提供的国内镜像可以下载快一点。
npm config get registry https://registry.npmmirror.com使用官方脚手架创建Vue工程[推荐]
找一个空的文件夹
D:\WorkspaceOfIdea\vue3npm create vuelatest
Need to install the following packages:
create-vue3.10.3
Ok to proceed? (y) yVue.js - The Progressive JavaScript Framework√ 请输入项目名称 ... vue-project
√ 是否使用 TypeScript 语法 ... 否 / 是√
√ 是否启用 JSX 支持 ... 否√ / 是
√ 是否引入 Vue Router 进行单页面应用开发 ... 否√ / 是
√ 是否引入 Pinia 用于状态管理 ... 否√ / 是
√ 是否引入 Vitest 用于单元测试 ... 否√ / 是
√ 是否要引入一款端到端End to End测试工具 » 不需要
√ 是否引入 ESLint 用于代码质量检测 ... 否 / 是√
√ 是否引入 Prettier 用于代码格式化 ... 否√ / 是
√ 是否引入 Vue DevTools 7 扩展用于调试? (试验阶段) ... 否√ / 是正在初始化项目 D:\WorkspaceOfIdea\vue3\vue-project...项目初始化完成可执行以下命令cd vue-projectnpm installnpm run devD:\WorkspaceOfIdea\vue3cd vue-projectD:\WorkspaceOfIdea\vue3\vue-projectnpm installD:\WorkspaceOfIdea\vue3\vue-projectnpm run dev vue-project0.0.0 devviteVITE v5.2.11 ready in 702 ms➜ Local: http://localhost:5173/➜ Network: use --host to expose➜ press h enter to show help
浏览器访问http://localhost:5173/
主要⼯程结构
ps官⽅建议开发IDE vscode。提供了辅助开发插件 vue-official。 在这之前有个插件叫volar现在已经停⽤
主要代码结构如下图
典型的Vue项⽬都是在index.html这⼀个单⻚⾯⾥形成各种交互这也就是所谓的SPA(Single Page
Application)Vue3的核⼼是通过createApp函数创建⼀个应⽤实例在这个实例中构建各种应⽤。(main.ts中)每个vue⽂件就是⼀个⻚⾯上的组件组件可以嵌套使⽤。vue中的组件分为template⻚⾯模板script脚本和style样式三个部分。Vue2中要求template下必
须有⼀个唯⼀的根元素Vue3中则没有了这个限制。数据双向绑定
双向绑定是Vue最为核⼼的功能。简单理解就是template中的⻚⾯数据和script中的脚本数据进⾏绑定其
中任何⼀个数据发⽣了变化另⼀个数据也随之发⽣变化。vue2语法的双向绑定
简单表单双向绑定
App.vue
templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/template
script langts
export default {//数据data() {return {userName: 王⼀,salary: 15000}},//⽅法methods: {addSalary() {this.salary 1000}}}
/script
style scoped
/style复杂表单双向绑定
数据双向绑定可以说是整个Vue的核⼼。例如我们可以⽤数据双向绑定实现⼀些更为复杂的表单。 App.vue
templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button button clickchangeShowUserInfo查看个⼈信息/buttonhr /div classuserInfo v-showshowUserInfoh2个⼈信息/h2p年龄input typenumber v-modeluserInfo.age //pp性别input typeradio value1 v-modeluserInfo.sex男input typeradio value2 v-modeluserInfo.sex⼥/pp岗位select v-modeluserInfo.departmentoption valuedev开发/optionoption valuetest测试/optionoption valuemaintain运维/option/select/pp技术: span v-forskill in userInfo.skills :keyskill{{ skill }}/span/pp新技术 input v-modelnewSkill / button clicklearnNewSkill学习新技术/button/pp个⼈信息汇总{{ userInfo }}/p/div/div/templatescript langts
export default {data() {return {userName: roy,salary: 15000,userInfo: {age: 0,sex: 1,skills: [java, vue, python],department: },newSkill: ,showUserInfo: false}},methods: {addSalary() {this.salary 1000},learnNewSkill() {if (this.newSkill)this.userInfo.skills.push(this.newSkill)},changeShowUserInfo() {this.showUserInfo !this.showUserInfo}}
}
/scriptstyle scoped
.userInfo {background-color: bisque;width: 80%;
}.userInfo span {background-color: yellow;margin-left: 10px;border: 1px;border-radius: 5px;
}
/styleCompositionAPI替代OptionsAPI
Vue2中常⽤的这种编写⽅式称为OptionsAPI配置式。其实现⽅式是⽤⼀个统⼀的配置对象来实现全部代码逻辑。在这个对象中通过data、methods、computed等配置选项来控制逻辑。
OptionsAPI是Vue2时的标准API编写⽅式。Vue3向下兼容了Vue2的API。因此Vue2的⽼项⽬在Vue3中基本可以⽆缝迁移。 实际上OptionsAPI是在CompositionAPI的基础上实现的。关于Vue的基础概念和知识在这两种API之间是通⽤的 。另外官⽅建议如果采⽤Vue构建完整的SPA应⽤那么更建议使⽤CompositionAPI。
但是OptionsAPI所有逻辑都混在⼀起不便于维护和复⽤。 Vue3另外通过了⼀种更⽅便的APIComposition API混合式API。
上⾯同样的示例⽤Composition API的写法如下
CompositionAPI简单不带双向绑定写法
templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/templatescript langtsexport default {setup() {//现在声明的变量还不具备双向绑定let userName 王⼀let salary 15000function addSalary() {salary 1000console.log(salary salary)}//模板要⽤哪些就返回哪些return { userName, salary, addSalary }}}
/scriptstyle scoped
/style1、setup是Vue3中的⼀个⽣命周期函数他会在组件加载时执⾏。后⾯会细讲⽣命周期。
2、setup可以返回对象或者函数。如果是⼀个对象则对象中的属性、⽅法等可以在模板中直接使⽤(常
⽤)。如果返回⼀个函数则通过函数的返回值直接渲染⻚⾯不经过模板。例如 setup(){return ()直
接渲染}
3、setup是⼀个普通的函数不能使⽤this。 OptionsAPI中可以通过this访问脚本本身的数据 同时 setup中
不处理this意味着setup编写可以更灵活不需要依赖当前⻚⾯上下⽂
4、此时声明的userName salary等变量不具备双向绑定。Vue3对双向绑定做了重新设计后⾯会详细分
享。CompositionAPI简单带双向绑定写法
templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/templatescript langts
import { ref } from vue;export default {setup() {//现在声明的变量具备了双向绑定let userName ref(王⼀)let salary ref(15000)function addSalary() {salary.value 1000console.log(salary salary)}//模板要⽤哪些就返回哪些return { userName, salary, addSalary }}}
/scriptstyle scoped
/stylesetup简写⽅式
5、setup有⼀种简写的⽅式script setup langts。这样就不需要写函数了标签内部直接写函数体。在
标签内部声明的对象函数等都会直接return出去。 项⽬中常⽤templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/templatescript setup langts
import { ref } from vue;let userName ref(王⼀)let salary ref(15000)function addSalary() {salary.value 1000console.log(salary salary)}
/scriptstyle scoped
/style在CompositionAPI中由于setup是⼀个不同的函数不需要处理this。这也意味着setup函数编写可以更加灵活不需要依赖当前⻚⾯上下⽂。例如将示例中的脚本单独写到⼀个ts⽂件中。
脚本单独写到ts⽂件中
component文件夹下新建MySalary.ts
import { onMounted, ref } from vue
export default function () {//之前声明的变量还不具备双向绑定。现在添加ref函数才具备了响应式const userName ref(王⼀)const salary ref(15000)function addSalary() {salary.value 1000console.log(salary salary.value)}onMounted(() {console.log(加载了外部脚本)});return { userName, salary, addSalary }
}然后在App.vue中就可以直接引⽤脚本
templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/templatescript setup langts
import MySalary from ./components/MySalary;
let {userName,salary,addSalary} MySalary()
/scriptstyle scoped
/style如果App.vue的逻辑越来越复杂通过这种⽅式就更易于将相关的属性和⽅法整理到⼀起从⽽实现⼀个特定的业务功能。
1、ref函数让变量具备了双向绑定功能。后⾯详细分析。
2、复杂⻚⾯可以⽤这种⽅式。⼀般情况下显然是将MySalary的模板和脚本封装到⼀起这就是⾃定义组
件了。Vue3中的数据双向绑定
ref包裹后可以在模板中直接使用在js中要加上.value因为ref包裹后是一个RefImpl对象 ref先后用不同值包裹两次后value值改变但没有和控件建立绑定关系原来控件上的旧值也失去了响应式能力改了别的ref后vue会重新扫描所有的ref控件会和之前的ref重新绑定
ref定义基础类型响应式数据
语法 let userNameref(初始值)。
返回值⼀个RefImpl的实例对象值被包裹在对象的value属性中。
注意点脚本中要⽤ref对象的value属性访问值例如userName.value。但是模板中可以直接⽤。ref对象本身不是响应式的value属性是响应式的。例如js中修改值要通过userName.valuexxx⽽不能userNamexxx。vue-official插件中可以选择⾃动添加value属性。(需要⼿动勾选)templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/templatescript setup langts
import { ref } from vue;let userName ref(王⼀) //基础类型⽤ref声明响应式let salary ref(15000)function addSalary() {salary.value 1000 //脚本中操作数据要加.valueconsole.log(salary salary)}
/scriptstyle scoped
/stylereactive定义对象型响应式数据
语法 let salaryInfo reactive({userName:“王⼀”,salary:15000}) 返回值reactive包裹后变成了⼀个Proxy实例对象具有双向绑定能⼒。
templatediv姓名input v-modelsalaryInfo.userName / {{ salaryInfo.userName }} br /薪⽔input typenumber v-modelsalaryInfo.salary / {{ salaryInfo.salary }} br /button clickaddSalary提交/button/div
/templatescript setup langts
import { reactive } from vue;let salaryInfo reactive({userName:roy,salary:10000})function addSalary() {salaryInfo.salary 1000console.log(salary salaryInfo.salary)}
/scriptstyle scoped
/styleref也可以定义对象型响应式数据(不推荐)
ref包裹完对象类型数据后封装成reactive包裹的对象对象里拆出来的属性不会有双向绑定能力
templatediv姓名input v-modelsalaryInfo.userName / {{ salaryInfo.userName }} br /薪⽔input typenumber v-modelsalaryInfo.salary / {{ salaryInfo.salary }} br /button clickaddSalary提交/button/div
/templatescript setup langts
import { ref } from vue;let salaryInfo ref({userName:roy,salary:10000})function addSalary() {salaryInfo.value.salary 1000console.log(salary salaryInfo.value.salary)}
/scriptstyle scoped
/style通过toRef或toRefs函数将转出来的数据具备响应式能力
对象型响应数据如果将其中的各个属性拆解出来是不具备响应式的。如果需要响应式属性可以使⽤toRefs或者toRef函数进⾏转换
将对象的属性换成ref包裹的属性
templatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/templatescript setup langts
import { reactive, toRef } from vue;let salaryInfo reactive({userName:roy,salary:10000})// toRef将对象的某个属性转为⼀个响应式数据let userName toRef(salaryInfo,userName)let salary toRef(salaryInfo,salary)function addSalary() {salaryInfo.salary 1000console.log(salaryInfo)}
/scriptstyle scoped
/styletemplatediv姓名input v-modeluserName / {{ userName }} br /薪⽔input typenumber v-modelsalary / {{ salary }} br /button clickaddSalary提交/button/div
/templatescript setup langts
import { reactive, toRef, toRefs } from vue;let salaryInfo reactive({userName:roy,salary:10000})// toRefs将对象的所有属性⼀起转换成响应式数据let {userName,salary} toRefs(salaryInfo)function addSalary() {salaryInfo.salary 1000console.log(salaryInfo)}
/scriptstyle scoped
/style标签的ref属性/ref绑定标签
ref不仅可以通过v-model的形式形成双向绑定也可以在元素上加上ref 在定义模板时可以通过ref属性将当前DOM元素绑定给响应式变量。
通过ref将当前DOM元素绑定给响应式变量
templatediv姓名input refname abcaaaaa / br /button clickshowRes提交/button/div
/templatescript setup langts
import { reactive, toRef, toRefs, ref } from vue;let name ref()function showRes(){console.log(name) //RefImpl ref对象console.log(name.value) //input dom元素console.log(name.value.value) //输⼊框的值console.log(name.value.getAttribute(abc)) //⾃定义属性的值}
/scriptstyle scoped
/style父组件拿到自定义组件里的值
如果只是针对普通元素还体现不出Ref的作⽤。如果配合⾃定义组件则更能体现Ref属性的作⽤。例如针对薪⽔信息可以⾃⼰写⼀个简单组件把多个输⼊框整合到⼀起。
components下新建MySalaryInfo.vue
!-- ⾃定义的薪⽔信息输⼊组件 --
template姓名input v-modeluserNamebr /薪⽔input typenumber v-modelsalary
/templatescript langts
//组件名默认是⽂件名。如果不希望⽤⽂件名也可以⾃定义
export default {name: SalaryInfo
}
/scriptscript setup langts
import { ref } from vue;//响应式数据默认值let userName ref(unknown)let salary ref(1000)//子组件对外暴露属性。只有暴露出去组件外部才能访问defineExpose({ userName, salary })
/scriptstyle/styleApp.vue
templateMySalaryInfo refsalaryInfo /button clickshowRes查看薪⽔信息/button !--2--
/templatescript setup langts
import { reactive, toRef, toRefs, ref } from vue;
//引⼊⼦组件
import MySalaryInfo from /components/MySalaryInfo.vue; //1
//获取绑定对象
let salaryInfo ref() //3
function showRes() {console.log(salaryInfo) //RefImpl ref对象 //4console.log(salaryInfo.value) //Proxy ⼦组件的响应式数据console.log(salaryInfo.value.userName) //⼦组件的输⼊框的值console.log(salaryInfo.value.salary) //⼦组件的输⼊框的值
}
/scriptstyle scoped/style子组件接收父组件传来的数据
MySalaryInfo.vue 接收值
!-- ⾃定义的薪⽔信息输⼊组件 --
template姓名input v-modelsalaryInfo.userNamebr /薪⽔input typenumber v-modelsalaryInfo.salarybr /{{ salaryInfo }}
/templatescript langts
//组件名默认是⽂件名。如果不希望⽤⽂件名也可以⾃定义
export default {name: SalaryInfo
}
/scriptscript setup langts
defineProps([ //可以接收外面传进来的值salaryInfo
])
/scriptstyle
/styleApp.vue 父组件修改值然后往子组件传值
templatedivMySalaryInfo :salary-infosalaryInfo/MySalaryInfobutton clickshowRes修改薪⽔/button/div
/templatescript setup langts
import { reactive, toRef, toRefs, ref } from vue;
//引⼊⼦组件
import MySalaryInfo from /components/MySalaryInfo.vue;
//获取绑定对象
let salaryInfo reactive({ userName: roy, salary: 10000 })
function showRes() {salaryInfo.salary 1000
}
/scriptstyle scoped/styleTypeScript版 但是上面的salaryInfo传到子组件时子组件并不知道它是什么类型也不知道它有什么属性可以引入ts对salaryInfo类型做限制 src下新建types文件夹和salaryInfo.ts
export interface SalaryInfo{userName:string,salary:number
}子组件引入和定义泛型 MySalaryInfo.vue
!-- ⾃定义的薪⽔信息输⼊组件 --
template姓名input v-modelsalaryInfo.userNamebr /薪⽔input typenumber v-modelsalaryInfo.salarybr /{{ salaryInfo }}
/templatescript langts
//组件名默认是⽂件名。如果不希望⽤⽂件名也可以⾃定义
export default {name: SalaryInfo
}
/scriptscript setup langts
import type { SalaryInfo } from /types/salaryInfo;defineProps{salaryInfo:SalaryInfo}( //接收外面传进来的值
)
/scriptstyle
/styleVUE3⽣命周期
每个 Vue 组件实例在创建时都需要经历⼀系列的初始化步骤⽐如设置好数据侦听编译模板挂载实例DOM以及在数据改变时更新 DOM。在此过程中它也会运⾏被称为⽣命周期钩⼦的函数让开发者有机会在特定阶段运⾏⾃⼰的代码。
⽣命周期有四个阶段创建挂载更新销毁。每个阶段有⼀前⼀后两个函数
OptionsAPI的⽣命周期函数
创建阶段 beforeCreate 、 created
挂载阶段 beforeMount 、 mounted
更新阶段 beforeUpdate 、 updated
销毁阶段 beforeDestroy 、 destroyedCompositionAPI的⽣命周期函数
创建阶段 setup
挂载阶段 onBeforeMount 、 onMounted
更新阶段 onBeforeUpdate 、 onUpdated
卸载阶段 onBeforeUnmount 、 onUnmounted示例
templatediv薪⽔input typenumber v-modelsalary / br /button clickaddsum薪⽔1000/button/div
/template!-- vue3写法 --
script langts setup
import {ref,onBeforeMount,onMounted,onBeforeUpdate,onUpdated,onBeforeUnmount,onUnmounted
} from vue
// 数据
let salary ref(0)
// ⽅法
function addsum() {salary.value 1000
}
console.log(setup)
// ⽣命周期钩⼦
onBeforeMount(() {console.log(挂载之前)
})
onMounted(() {console.log(挂载完毕)
})
onBeforeUpdate(() {console.log(更新之前)
})
onUpdated(() {console.log(更新完毕)
})
onBeforeUnmount(() {console.log(卸载之前)
})
onUnmounted(() {console.log(卸载完毕)
})
/scriptVue-Router组件路由机制
Vue项⽬虽然只有index.html⼀个⻚⾯但是可以通过多路由机制实现多⻚⾯跳转的效果。访问不同链接展示不同的⻚⾯内容形成多⻚⾯的效果。 Vue官⽅提供了Vue-Router组件实现路由管理官⽹地址https://router.vuejs.org/zh/ 。该组件可以在创建Vue项⽬时选择引⼊。如果创建时没有安装也可以⼿动安装。
npm install vue-router4vue3要求使⽤router组件最新版本。⽬前最新版本是4
基础使⽤
页面准备 HomePage.vueAboutPage.vueNewsPage.vue
template首页
/templatescript setup langts
/scriptstyle
/stylemain.ts
import ./assets/main.cssimport { createApp } from vue
import App from ./App.vueimport { createRouter,createWebHistory } from vue-router
import HomePage from ./pages/HomePage.vue
import AboutPage from ./pages/AboutPage.vue
import NewsPage from ./pages/NewsPage.vue// 1.配置路由规则
const routes [{ path: /,redirect: /home}, //默认跳转到⾸⻚{ path: /home, component: HomePage }, { path: /about, component: AboutPage }, //命名路由{ path: /news, component: NewsPage, name:news },
]// 2.创建路由器
const router createRouter({history: createWebHistory(),//路由器⼯作模式routes,
})// 3.加载路由器
// createApp(App).mount(#app)
const app createApp(App)
//加载路由器
app.use(router)
app.mount(#app)App.vue
templatediv idapph1Hello App!/h1p!-- 路由链接--router-link to/home⾸⻚/router-link !-- 直接字符串跳转 --router-link :to{ path: /about }关于/router-link !-- 对象跳转 --router-link :to{ name: news }新闻/router-link !-- 具名跳转 --/pdiv classcontentrouter-view / !-- 路由出⼝路由匹配到的组件将渲染在这⾥ --/div/div
/template!-- vue3写法 --
script langts setup
/scriptstyle
a {margin: 10px;
}
.content {background: yellowgreen;widows: 10%;height: 400px;border: 1cap;border-radius: 10px;
}
/style路由⼯作模式
在router配置中的history项为路由⼯作模式。Vue提供了两种⼯作模式
history模式 访问路径URL不带#斜杠链接接近传统⽹站。缺点容易产⽣404错误。
const router createRouter({history:createWebHistory(), //history模式/******/
})hash模式 访问路径URL带有#。缺点对SEO不太友好。⽐较适合内部系统。
const router createRouter({history:createWebHashHistory(), //hash模式/******/
})replace
route-link标签可以添加replace属性。有两种可选配置 push和replace push 追加浏览器历史记录(默认值)。追加历史记录后可以使⽤浏览器的返回按钮跳回历史⻚ replace 替换浏览器历史记录。替换历史记录后浏览器的返回按钮不可⽤。
嵌套路由
页面准备 NewsDetail1.vueNewsDetail2.vue
!-- NewsDetail1.vue --
templatep新闻ID 1/pp新闻标题 1 /pp新闻内容 1 /p
/template
script langts setup
/script
style/stylemain.ts
import NewsDetail1 from ./pages/NewsDetail1.vue
import NewsDetail2 from ./pages/NewsDetail2.vueconst routes [{ path: /, redirect: /home }, //默认跳转到⾸⻚{ path: /home, component: HomePage },{ path: /about, component: AboutPage }, //命名路由{path: /news,component: NewsPage,name: news,children: [ //⼦路由{path: 1,component: NewsDetail1,name: xinwen1},{path: 2,component: NewsDetail2,name: xinwen2}]},
]NewsPage.vue
templatediv classnews!-- 导航区 --ulliRouterLink to/news/1新闻1/RouterLink/liliRouterLink to/news/2新闻2/RouterLink/li/ul!-- 展示区 --div classnews-contentRouterView/RouterView/div/div
/template这样就实现了新闻⻚内的嵌套路由。点击新闻标题会跳到对应的新闻详情⻚。
路由传参
上⾯的示例显然太呆板现实的场景当然是希望查出⼀个完整的新闻列表然后每个新闻⻚都是展示新闻列表中的内容⽽不是每个组件内固定的内容。这也就需要进⾏路由传参也就是NewsDetail中的内容是从新闻列表中传递进来的。
Vue3中提供了两种传参⽅式query传参和param传参。
query传参
NewsPage.vue传参
!-- 字符串传参 --
router-link to/news/1?id1title新闻1contentasdfasdf新闻1/RouterLink!-- 对象传参 --
RouterLink:to{path:/news/1,query:{id:1,title:新闻1,content:asdfasdf}}新闻1
/RouterLinkNewsDetail.vue接收参数
!-- NewsDetail1.vue --
templatep新闻ID {{ query.id }}/pp新闻标题{{ query.title }}/pp新闻内容{{ query.content }} /p
/template
script langts setup
import { useRoute } from vue-router
import { toRef } from vue
let route useRoute()
// 获取和打印query参数
console.log(route.query)
// 双向绑定数据
let query toRef(route, query)
/script
style/styleparams传参
params传参⽅式表示所有参数都拼接到URL上。 ⾸先需要在route配置中预设占位符
main.ts
{ path: /news, component: NewsPage, name:news,children:[ //⼦路由{path: 1,component: NewsDetail1},{name:xinwen2, // 对应params传参方式2path: 2/:id/:title/:content, // Param传参URL预设占位符?表示参数可有可没有component: NewsDetail2}]
},然后传参时在RouteLink中直接传到预设的URL或者⽤name属性指定⽬标。 NewsPage.vue
!-- params传参方式1 --
RouterLink to/news/2/2/新闻2/qowuieoiurrparam路径传参/RouterLink
!-- params传参方式2 --
RouterLink:to{name:xinwen2, !-- main.ts里也要加name属性 --params:{id:2,title :新闻2,content :qowiueoiqu}}param对象传参
/RouterLink接下来NewsDetail2.vue中通过路由的params属性接收参数
!-- NewsDetail2.vue --
templatep新闻ID {{ params.id }}/pp新闻标题{{ params.title }}/pp新闻内容{{ params.content }} /p
/template
script langts setup
import { useRoute } from vue-router
import { toRef } from vue
let route useRoute()
// 接收并打印query参数
console.log(route.params)
// 双向绑定数据
let params toRef(route, params)
/script
style/stylePinia集中式状态存储
理解状态
在任意Vue⻚⾯之间共享的存储数据。简单理解在当前Vue项⽬中使⽤的MySQL数据库。例如登录信息只要完成了登录所有Vue⻚⾯都能读取到当前登录⽤户。
Vue2中提供的集中状态存储框架是VuexVue3中新提供了Pinia。如果你使⽤的还是Vue2那么主要下Vuex和Pinia不能⼀起使⽤。
创建store
Pinia可以在创建应⽤时选择引⼊。如果创建时没有引⼊那就需要⼿动引⼊⼀下。
npm install piniaPinia的使⽤⽅式和Route组件基本相似。需要在启动的ts⽂件中使⽤use函数引⼊。 main.ts
import {createPinia} from pinia
//加载pinia
const pinia createPinia()
app.use(pinia)接下来使⽤pinia需要创建Store。⼀个Store可以理解为MySQL中的⼀个库保存⼀部分数据。Pinia的Store中有三个概念 stategetter , action。这三个概念也可以类⽐于熟悉的MVC。state相当于是数据getter相当于是服务⽤来获取并返回数据action相当于Controller组织业务逻辑。
创建定义store的⽂件 store/user.ts
import { defineStore } from piniaexport const userStore defineStore(userStore, {//action封装修改state的业务动作actions: {changeUsername(value: string) {if (value value.length 10) {this.username value}}},//getters读取state的计算值getters: {getUsername(): string {return this.username.toUpperCase()}},//state定义要保存的数据结构state() {return {//给定默认值username: --}}
})使⽤store操作数据
App.vue中修改stroe的数据
templatediv idapph1Hello App!/h1/div
/templatescript langts setup
//获取store
import { userStore } from /store/User;
const user userStore()
//修改store中的值
//1、直接修改某⼀个state
user.username roy
//2、批量修改完整的state
user.$patch({username: roy2
})
//3、通过action进⾏修改 推荐⽅式
user.changeUsername(roy)
console.log(user.username)
console.log(user.getUsername)
/scriptstyle/stylepinia的使⽤⼏乎没有⻔槛相⽐vuex要简单很多所以官⽅对Pinia的定义是符合直觉的状态管理库。因此在使⽤pinia时更应该是注意使⽤规范。
storeToRefs声明响应式数据
script langts setup
//获取store
import { userStore } from /store/User;
import { storeToRefs } from pinia;
import { toRefs } from vue;const user userStore()//storeToRefs转换后只有username和getUsername
let userInfo storeToRefs(user)
console.log(userInfo)
//toRefs转换后包含了很多隐藏⽅法和属性⽐如$patch
let userInfo2 toRefs(user)
console.log(userInfo2)/scriptstore的混合式写法
store也有⼀种混合式的写法将各种组件混合到⼀起。
import { defineStore } from pinia
import { reactive } from vue
export const userStore defineStore(userStore,(){//相当于是stateconst userInfo reactive({username:---})//相当于actionfunction changeUsername(value:string){if(value value.length10){userInfo.username value}}//相当于gettersfunction getUsername():string{return userInfo.username.toUpperCase()}//不⽤区分什么类型返回出去的就可以⽤return {userInfo,changeUsername,getUsername}
})在App.vue中也可以像使⽤普通对象⼀样使⽤store中的⽅法和对象。
templatediv idapp!-- 注意对象拆包过程 --h1Hello {{ res.userInfo.value.username }}/h1
/div
/template
!-- vue3写法 --
script langts setup
//获取store
import { userStore } from /store/user2;
import { storeToRefs } from pinia;
const user userStore()
//修改store中的值
//通过action进⾏修改 推荐⽅式
user.changeUsername(roy)
// 获取store中的数据
console.log(user.userInfo)
// 通过getter获取state数据 推荐⽅式
console.log(user.getUsername())
//混合式store转成Ref后只有数据的ref
let res storeToRefs(user)
console.log(res)
/script
style
/style这种⽅式相当于在做MVC开发时将Controller\Service\Dao这些组件写到⼀起。 复杂项⽬当中不太建议这样⽤。但是如果别⼈这么⽤了你要能看懂。
快速上⼿Element-Plus
ElementUI是饿了么开源的⼀套基于Vue2的经典UI库。针对Vue3升级成为了ElementPlus。熟悉ElementPlus库不但可以节省⼤量前端项⽬的开发时间同时也是深⼊了解Vue3复杂组件开发的很好途径。
ElementPlus官⽹地址https://element-plus.org/zh-CN/ 。 ⽬前还在迭代更新过程当中。
1、安装ElementPlus
npm install element-plus --save2、引⼊ElementPlus main.ts
import { createApp } from vue
import App from ./App.vue
import ElementPlus from element-plus
import element-plus/dist/index.css
const app createApp(App)
app.use(ElementPlus)
app.mount(#app)3、使⽤ElementPlus组件 参⻅官⽅⽂档。
templatediv classmb-4el-buttonDefault/el-buttonel-button typeprimaryPrimary/el-buttonel-button typesuccessSuccess/el-buttonel-button typeinfoInfo/el-buttonel-button typewarningWarning/el-buttonel-button typedangerDanger/el-button/div
/template
!-- vue3写法 --
script langts setup
import { ElButton } from element-plus;
/script
style
/style或者你也可以直接使⽤element-plus提供的Demohttps://github.com/element-plus/element-plus-vite-starter 。 ⾥⾯有更多现成的案例。
ElementUI针对Vue2还推出过⼀个vue-admin模版⾥⾯案例更丰富集成度也更⾼。很多企业内部项⽬都可以直接拿来⽤。有兴趣可以了解⼀下。⽽针对Vue3只推出了⼀个将ElementUI从Vue2升级到Vue3的迁移⼯具尚未提供Vue3的版本。
类似的UI框架还有很多给⼤家例举⼏个常⽤的 Ant Design Vue(https://www.antdv.com/docs/vue/getting-started-cn) 经典⽼框架 Native UI(https://www.naiveui.com/zh-CN/light) 仅⽀持Vue3的⼀个新的UI库 Tdesign(https://tdesign.tencent.com/) 腾讯开源的前端UI框架 包含桌⾯与移动端 NutUI(https://nutui.jd.com/#/) 京东开源的前端UI框架 uvuewui(https://www.uviewui.com/) 适合移动端uni-app开发