JavaWeb,Vue的学习(下)

Router路由

路由(Router)简介

  • 定义:路由就是根据不同的 URL 地址展示不同的内容或页面。
  • 通俗理解:路由就像是一个地图,我们要去不同的地方,需要通过不同的路线进行导航。

路由的作用

  • 单页应用程序(SPA)中,路由可以实现不同视图之间的无刷新切换,提升用户体验;
  • 路由还可以实现页面的认证和权限控制,保护用户的隐私和安全;
  • 路由还可以利用浏览器的前进与后退,帮助用户更好地回到之前访问过的页面。

路由的例子:

有四个组件,分别是Add、List、Update、Home,以Home为例,其他的组件将单词Home换了即可:

Home组件:

<script setup></script><template><div><h1>HOME</h1></div>
</template><style scoped></style>

准备路由配置:

router.js:

// 导入创建路由对象需要使用的函数
import {createRouter,createWebHashHistory} from 'vue-router'
// 导入.vue组件
import Home from '../components/Home.vue'
import List from '../components/list.vue'
import Update from '../components/Update.vue'
import Add from '../components/Add.vue'
// 创建一个路由对象
const router = createRouter({// history属性用于记录路由的历史history:createWebHashHistory(),// routes用于定义多个不同的路径和组件之间的对应关系routes:[{path:"/home",component:Home},{path:"/list",component:List},{path:"/add",component:Add},{path:"/update",component:Update}]
})
//向外暴露路由对象
export default router

main.js:

import { createApp } from 'vue'import App from './App.vue'//在整个App.vue中可以使用路由
import router from './routers/router'
const app = createApp(App)
app.use(router)
app.mount('#app')

主页面:

App.vue:

<script setup></script><template><div>App开头的内容<router-link to="/home">home</router-link><br><router-link to="/list">list</router-link><br><router-link to="/update">update</router-link><router-link to="/add">add</router-link><hr><!-- 该标签会被替换为具体的.vue --><router-view></router-view><hr>App结尾的内容</div>
</template><style scoped></style>

 

点击相应的紫色的单词,下划线中间的组件对应的页面就会发生改变,路由就是可以将不同的组件对应的页面进行切换

要让不同的按钮对应不同的router-view,要使用其name属性,例:

  • App.vue
<script setup>
</script><template><div><h1>App页面</h1><hr/><!-- 路由的连接 --><router-link to="/">home页</router-link> <br><router-link to="/list">list页</router-link> <br><router-link to="/add">add页</router-link> <br><router-link to="/update">update页</router-link> <br><hr/><!-- 路由连接对应视图的展示位置 --><hr>默认展示位置:<router-view></router-view><hr>Home视图展示:<router-view name="homeView"></router-view><hr>List视图展示:<router-view name="listView"></router-view><hr>Add视图展示:<router-view name="addView"></router-view><hr>Update视图展示:<router-view name="updateView"></router-view></div>
</template><style scoped>
</style>

4 准备路由配置

  • src/routers/router.js
// 导入路由创建的相关方法
import {createRouter,createWebHashHistory} from 'vue-router'// 导入vue组件
import Home from '../components/Home.vue'
import List from '../components/List.vue'
import Add from '../components/Add.vue'
import Update from '../components/Update.vue'// 创建路由对象,声明路由规则
const router = createRouter({//createWebHashHistory() 是 Vue.js 基于 hash 模式创建路由的工厂函数。在使用这种模式下,路由信息保存在 URL 的 hash 中,//使用 createWebHashHistory() 方法,可以创建一个路由历史记录对象,用于管理应用程序的路由。在 Vue.js 应用中,//通常使用该方法来创建路由的历史记录对象。//就是路由中缓存历史记录的对象,vue-router提供history: createWebHashHistory(),routes:[{path:'/',/*component指定组件在默认的路由视图位置展示components:Homecomponents指定组件在name为某个值的路由视图位置展示components:{default:Home,// 默认路由视图位置homeView:Home// name为homeView的路由视图位置}*/components:{default:Home,homeView:Home}},{path:'/list',components:{listView : List}},{path:'/add',components:{addView:Add}},{path:'/update',components:{updateView:Update}},]})// 对外暴露路由对象
export default router;

编程式路由

普通路由

  • <router-link to="/list">list页</router-link>这种路由,to中的内容目前是固定的,点击后只能切换/list对象组件(声明式路由)

编程式路由

  • 通过useRouter,动态决定向那个组件切换的路由
  • 在 Vue 3 和 Vue Router 4 中,可以使用 useRouter 来实现动态路由(编程式路由)
  • 这里的 useRouter 方法返回的是一个 router 对象,可以用它来做如导航到新页面、返回上一页面等操作。

例:

<script setup type="module">import {useRouter} from 'vue-router'import {ref} from 'vue'//创建动态路由对象let router = useRouter()let  routePath =ref('')let  showList= ()=>{// 编程式路由// 直接push一个路径//router.push('/list')// push一个带有path属性的对象router.push({path:'/list'})}
</script><template><div><h1>App页面</h1><hr/><!-- 路由的连接 --><router-link to="/">home页</router-link> <br><router-link to="/list">list页</router-link> <br><router-link to="/showAll">showAll页</router-link> <br><router-link to="/add">add页</router-link> <br><router-link to="/update">update页</router-link> <br><!-- 动态输入路径,点击按钮,触发单击事件的函数,在函数中通过编程是路由切换页面 --><button @click="showList()">showList</button> <br><hr/><!-- 路由连接对应视图的展示位置 --><hr>默认展示位置:<router-view></router-view><hr>Home视图展示:<router-view name="homeView"></router-view><hr>List视图展示:<router-view name="listView"></router-view><hr>Add视图展示:<router-view name="addView"></router-view><hr>Update视图展示:<router-view name="updateView"></router-view></div>
</template><style scoped>
</style>

路由传参

路径参数

在路径中使用一个动态字段来实现,称之为路径参数

在router.js文件中,要使用路径参数的组件的path中应该使用占位符(:参数名)

调用具体的参数用:路由对象名.params.参数名

  • 例如: 查看数据详情 /showDetail/1 ,1就是要查看详情的id,可以动态添值

键值对参数

  • 类似与get请求通过url传参,数据是键值对形式的
    • 例如: 查看数据详情/showDetail?hid=1,hid=1就是要传递的键值对参数
    • 在 Vue 3 和 Vue Router 4 中,可以使用 useRoute 这个函数从 Vue 的组合式 API 中获取路由对象。
    • useRoute 方法返回的是当前的 route 对象,可以用它来获取关于当前路由的信息,如当前的路径、查询参数等。

调用具体的参数使用:路由对象名.query.参数名

例:

<script setup type="module">import {useRouter} from 'vue-router'//创建动态路由对象let router = useRouter()//动态路由路径传参方法let showDetail= (id,language)=>{// 尝试使用拼接字符串方式传递路径参数//router.push(`showDetail/${id}/${languange}`)/*路径参数,需要使用params  */router.push({name:"showDetail",params:{id:id,language:language}})}let showDetail2= (id,language)=>{/*uri键值对参数,需要使用query */router.push({path:"/showDetail2",query:{id:id,language:language}})}
</script><template><div><h1>App页面</h1><hr/><!-- 路径参数   --><router-link to="/showDetail/1/JAVA">showDetail路径传参显示JAVA</router-link><button @click="showDetail(1,'JAVA')">showDetail动态路由路径传参显示JAVA</button><hr/><!-- 键值对参数 --><router-link v-bind:to="{path:'/showDetail2',query:{id:1,language:'Java'}}">showDetail2键值对传参显示JAVA</router-link><button @click="showDetail2(1,'JAVA')">showDetail2动态路由键值对传参显示JAVA</button><hr>showDetail视图展示:<router-view name="showDetailView"></router-view><hr>showDetail2视图展示:<router-view name="showDetailView2"></router-view></div>
</template><style scoped>
</style>

路由守卫

在 Vue 3 中,路由守卫是用于在路由切换期间进行一些特定任务的回调函数。路由守卫可以用于许多任务,例如验证用户是否已登录、在路由切换前提供确认提示、请求数据等。Vue 3 为路由守卫提供了全面的支持,并提供了以下几种类型的路由守卫:

  1. 全局前置守卫:在路由切换前被调用,可以用于验证用户是否已登录、中断导航、请求数据等。
  2. 全局后置守卫:在路由切换之后被调用,可以用于处理数据、操作 DOM 、记录日志等。

守卫代码的位置在router.js中

//全局前置路由守卫
router.beforeEach( (to,from,next) => {//to 是目标地包装对象  .path属性可以获取地址//from 是来源地包装对象 .path属性可以获取地址//next是方法,不调用默认拦截! next() 放行,直接到达目标组件//next('/地址')可以转发到其他地址,到达目标组件前会再次经过前置路由守卫console.log(to.path,from.path,next)//需要判断,注意避免无限重定向if(to.path == '/index'){next()}else{next('/index')}} )//全局后置路由守卫
router.afterEach((to, from) => {console.log(`Navigate from ${from.path} to ${to.path}`);
});

Promise

回调函数

回调函数是一种基于事件的,自动调用的函数

非回调函数的代码不会等待回调函数执行完毕,而是直接执行

Promise简介

Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。Promise 提供统一的 API,各种异步操作都可以用同样的方法进行处理。

  • Promise对象代表一个异步操作,有三种状态:Pending(进行中)、Resolved(已完成,又称 Fulfilled)和Rejected(已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是Promise这个名字的由来,它的英语意思就是“承诺”,表示其他手段无法改变。
  • 一旦状态改变,就不会再变,任何时候都可以得到这个结果。Promise对象的状态改变,只有两种可能:从Pending变为Resolved和从Pending变为Rejected。只要这两种情况发生,状态就凝固了,不会再变了,会一直保持这个结果。
  • ES6规定,Promise对象是一个构造函数,用来生成Promise实例。

例:

    <script>/*1.实例化promise对象,并且执行(类似Java创建线程对象,并且start)参数: resolve,reject参数: resolve,reject分别处理成功和失败的两个函数 成功resolve(结果)  失败reject(结果)参数: 在function中调用这里两个方法,那么promise会处于两个不同的状态状态: promise有三个状态pending   正在运行resolved  内部调用了resolve方法rejected  内部调用了reject方法参数: 在第二步回调函数中就可以获取对应的结果*/let promise =new Promise(function(resolve,reject){console.log("promise do some code ... ...")//resolve("promise success")reject("promise fail")})console.log('other code1111 invoked')//2.获取回调函数结果  then在这里会等待promise中的运行结果,但是不会阻塞代码继续运行promise.then(//第一个函数是要执行了resolve之后执行function(value){console.log(`promise中执行了resolve:${value}`)},//第二个函数是要执行了reject之后执行function(error){console.log(`promise中执行了reject:${error}`)})// 3 其他代码执行console.log('other code2222 invoked')</script>

关于Promise catch()

Promise.prototype.catch方法是.then(null, rejection)的别名,用于指定发生错误时的回调函数。

<script>let promise =new Promise(function(resolve,reject){console.log("promise do some code ... ...")// 故意响应一个异常对象throw new Error("error message")})console.log('other code1111 invoked')/*then中的reject()的对应方法可以在产生异常时执行,接收到的就是异常中的提示信息then中可以只留一个resolve()的对应方法,reject()方法可以用后续的catch替换then中的reject对应的回调函数被后续的catch替换后,catch中接收的数据是一个异常对象*/promise.then(function(resolveValue){console.log(`promise中执行了resolve:${resolveValue}`)}//,//function(rejectValue){console.log(`promise中执行了reject:${rejectValue}`)}).catch(function(error){console.log(error)})console.log('other code2222 invoked')
</script>

async和await

async和await是ES6中用于处理异步操作的新特性。通常,异步操作会涉及到Promise对象,而async/await则是在Promise基础上提供了更加直观和易于使用的语法。

async 用于标识函数的

  1. async标识函数后,async函数的返回值会变成一个promise对象
  2. 如果函数内部返回的数据是一个非promise对象,async函数的结果会返回一个成功状态 promise对象
  3. 如果函数内部返回的是一个promise对象,则async函数返回的状态与结果由该对象决定
  4. 如果函数内部抛出的是一个异常,则async函数返回的是一个失败的promise对象

例:

<script>/*async 用于标识函数的1. async标识函数后,async函数的返回值会变成一个promise对象2. 如果函数内部返回的数据是一个非promise对象,async函数的结果会返回一个成功状态 promise对象3. 如果函数内部返回的是一个promise对象,则async函数返回的状态与结果由该对象决定4. 如果函数内部抛出的是一个异常,则async函数返回的是一个失败的promise对象*/async function fun1(){//return 10//throw new Error("something wrong")let promise = Promise.reject("heihei")return promise}let promise =fun1()promise.then(function(value){console.log("success:"+value)}).catch(function(value){console.log("fail:"+value)})
</script>

await

  1. await右侧的表达式一般为一个promise对象,但是也可以是一个其他值
  2. 如果表达式是promise对象,await返回的是promise成功的值
  3. await会等右边的promise对象执行结束,然后再获取结果,后续代码也会等待await的执行
  4. 如果表达式是其他值,则直接返回该值
  5. await必须在async函数中,但是async函数中可以没有await
  6. 如果await右边的promise失败了,就会抛出异常,需要通过 try ... catch捕获处理

例:

<script>/*1. await右侧的表达式一般为一个promise对象,但是也可以是一个其他值2. 如果表达式是promise对象,await返回的是promise成功的值3. await会等右边的promise对象执行结束,然后再获取结果,后续代码也会等待await的执行4. 如果表达式是其他值,则直接返回该值5. await必须在async函数中,但是async函数中可以没有await6. 如果await右边的promise失败了,就会抛出异常,可以通过 try ... catch捕获处理*/async function fun1(){return 10}async function fun2(){try{let res = await fun1()//let res = await Promise.reject("something wrong")}catch(e){console.log("catch got:"+e)}console.log("await got:"+res)}fun2()
</script>

Axios

Axios 是一个基于 promise 网络请求库,作用于node.js 和浏览器中。 它是 isomorphic 的(即同一套代码可以运行在浏览器和node.js中)。在服务端它使用原生 node.js http 模块, 而在客户端 (浏览端) 则使用 XMLHttpRequests。

特性:

  • 从浏览器创建 XMLHttpRequests
  • 从 node.js 创建 http 请求
  • 支持 Promise API
  • 拦截请求和响应
  • 转换请求和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF

例:

<script setup type="module">import axios from 'axios'import { onMounted,reactive } from 'vue';let jsonData =reactive({code:1,content:'奥里给'})let getLoveMessage =()=>{axios({method:"post", // 请求方式url:"<https://api.uomg.com/api/rand.qinghua?format=json>",  // 请求的urldata:{ // 当请求方式为post时,data下的数据以JSON串放入请求体,否则以key=value形式放url后username:"123456"}}).then( function (response){//响应成功时要执行的函数console.log(response)Object.assign(jsonData,response.data)}).catch(function (error){// 响应失败时要执行的函数console.log(error)})}/* 通过onMounted生命周期,自动加载一次 */onMounted(()=>{getLoveMessage()})
</script><template><div><h1>今日鸡汤:{{jsonData.content}}</h1><button  @click="getLoveMessage">获取今日鸡汤</button></div>
</template><style scoped>
</style>

响应的数据中包含以下信息:

{// `data` 由服务器提供的响应data: {},// `status` 来自服务器响应的 HTTP 状态码status: 200,// `statusText` 来自服务器响应的 HTTP 状态信息statusText: 'OK',// `headers` 是服务器响应头// 所有的 header 名称都是小写,而且可以使用方括号语法访问// 例如: `response.headers['content-type']`headers: {},// `config` 是 `axios` 请求的配置信息config: {},// `request` 是生成此响应的请求// 在node.js中它是最后一个ClientRequest实例 (in redirects),// 在浏览器中则是 XMLHttpRequest 实例request: {}
}

如果要对其取值使用,使用then方法:

<script setup type="module">import axios from 'axios'import { onMounted,reactive } from 'vue';let jsonData =reactive({code:1,content:'奥里给'})let getLoveWords = async ()=>{return await axios({method:"post",url:"<https://api.uomg.com/api/rand.qinghua?format=json>",data:{username:"123456"}})}let getLoveMessage =()=>{let {data}  = await getLoveWords()Object.assign(message,data)}/* 通过onMounted生命周期,自动加载一次 */onMounted(()=>{getLoveMessage()})
</script><template><div><h1>今日鸡汤:{{jsonData.content}}</h1><button  @click="getLoveMessage">获取今日鸡汤</button></div>
</template><style scoped>
</style>

Axios get和post方法

配置添加语法

axios.get(url[, config])axios.get(url,{上面指定配置key:配置值,上面指定配置key:配置值
})axios.post(url[, data[, config]])axios.post(url,{key:value //此位置数据,没有空对象即可{}},{上面指定配置key:配置值,上面指定配置key:配置值
})

测试get参数

<script setup type="module">import axios from 'axios'import { onMounted,ref,reactive,toRaw } from 'vue';let jsonData =reactive({code:1,content:'奥里给'})let getLoveWords= async ()=>{try{return await axios.get('<https://api.uomg.com/api/rand.qinghua>',{params:{// 向url后添加的键值对参数format:'json',username:'zhangsan',password:'123456'},headers:{// 设置请求头'Accept' : 'application/json, text/plain, text/html,*/*'}})}catch (e){return await e}}let getLoveMessage =()=>{let {data}  = await getLoveWords()Object.assign(message,data)}/* 通过onMounted生命周期,自动加载一次 */onMounted(()=>{getLoveMessage()})
</script><template><div><h1>今日鸡汤:{{jsonData.content}}</h1><button  @click="getLoveMessage">获取今日鸡汤</button></div>
</template><style scoped>
</style>

测试post参数

<script setup type="module">import axios from 'axios'import { onMounted,ref,reactive,toRaw } from 'vue';let jsonData =reactive({code:1,content:'奥里给'})let getLoveWords= async ()=>{try{return await axios.post('<https://api.uomg.com/api/rand.qinghua>',{//请求体中的JSON数据username:'zhangsan',password:'123456'},{// 其他参数params:{// url上拼接的键值对参数format:'json',},headers:{// 请求头'Accept' : 'application/json, text/plain, text/html,*/*','X-Requested-With': 'XMLHttpRequest'}})}catch (e){return await e}}let getLoveMessage =()=>{let {data}  = await getLoveWords()Object.assign(message,data)}/* 通过onMounted生命周期,自动加载一次 */onMounted(()=>{getLoveMessage()})
</script><template><div><h1>今日鸡汤:{{jsonData.content}}</h1><button  @click="getLoveMessage">获取今日鸡汤</button></div>
</template><style scoped>
</style>

Axios 拦截器

如果想在axios发送请求之前,或者是数据响应回来在执行then方法之前做一些额外的工作,可以通过拦截器完成

// 添加请求拦截器 请求发送之前
axios.interceptors.request.use(function (config) {// 在发送请求之前做些什么return config;},function (error) {// 对请求错误做些什么return Promise.reject(error);}
);// 添加响应拦截器 数据响应回来
axios.interceptors.response.use(function (response) {// 2xx 范围内的状态码都会触发该函数。// 对响应数据做点什么return response;},function (error) {// 超出 2xx 范围的状态码都会触发该函数。// 对响应错误做点什么return Promise.reject(error);}
);
  • 定义src/axios.js提取拦截器和配置语法
import axios from 'axios'//  创建instance实例
const instance = axios.create({baseURL:'<https://api.uomg.com>',timeout:10000
})//  添加请求拦截
instance.interceptors.request.use(// 设置请求头配置信息config=>{//处理指定的请求头console.log("before request")config.headers.Accept = 'application/json, text/plain, text/html,*/*'return config},// 设置请求错误处理函数error=>{console.log("request error")return Promise.reject(error)}
)
// 添加响应拦截器
instance.interceptors.response.use(// 设置响应正确时的处理函数response=>{console.log("after success response")console.log(response)return response},// 设置响应异常时的处理函数error=>{console.log("after fail response")console.log(error)return Promise.reject(error)}
)
// 默认导出
export default instance
  • App.vue
<script setup type="module">// 导入我们自己定义的axios.js文件,而不是导入axios依赖import axios from './axios.js'import { onMounted,ref,reactive,toRaw } from 'vue';let jsonData =reactive({code:1,content:'奥里给'})let getLoveWords= async ()=>{try{return await axios.post('api/rand.qinghua',{username:'zhangsan',password:'123456'},//请求体中的JSON数据{params:{format:'json',}}// 其他键值对参数)}catch (e){return await e}}let getLoveMessage =()=>{// 这里返回的是一个fullfilled状态的promisegetLoveWords().then((response) =>{console.log("after getloveWords")console.log(response)Object.assign(jsonData,response.data)})}/* 通过onMounted生命周期,自动加载一次 */onMounted(()=>{getLoveMessage()})
</script><template><div><h1>今日鸡汤:{{jsonData.content}}</h1><button  @click="getLoveMessage">获取今日鸡汤</button></div></template><style scoped>
</style>

 

Pinia

当我们有多个组件共享一个共同的状态(数据源)时,多个视图可能都依赖于同一份状态。来自不同视图的交互也可能需要更改同一份状态,这时候要用到Pinia

npm install pinia完后,就可以开始使用Pinia。

例:

定义pinia store对象

import {defineStore } from 'pinia'//定义数据并且对外暴露
// store就是定义共享状态的包装对象
// 内部包含四个属性: id 唯一标识 state 完整类型推理,推荐使用箭头函数 存放的数据 getters 类似属性计算,存储放对数据
// 操作的方法  actions 存储数据的复杂业务逻辑方法
// 理解: store类似Java中的实体类, id就是类名, state 就是装数据值的属性  getters就是get方法,actions就是对数据操作的其他方法
export const definedPerson = defineStore({id: 'personPinia', //必须唯一state:()=>{ // state中用于定义数据return {username:'张三',age:0,hobbies:['唱歌','跳舞']}},getters:{// 用于定义一些通过数据计算而得到结果的一些方法 一般在此处不做对数据的修改操作// getters中的方法可以当做属性值方式使用getHobbiesCount(){return this.hobbies.length},getAge(){return this.age}},actions:{ // 用于定义一些对数据修改的方法doubleAge(){this.age=this.age*2}}}
)

在main.js配置pinia组件到vue中

import { createApp } from 'vue'
import App from './App.vue'
import router from './routers/router.js'
// 导pinia
import { createPinia } from 'pinia'
// 创建pinia对象
let pinia= createPinia()let app =createApp(App)
app.use(router)
// app中使用pinia功能
app.use(pinia)
app.mount('#app')

5 Operate.vue 中操作Pinia数据

<script setup type="module">import { ref} from 'vue';import { definedPerson} from '../store/store';// 读取存储的数据let person= definedPerson()let hobby = ref('')</script><template><div><h1>operate视图,用户操作Pinia中的数据</h1>请输入姓名:<input type="text" v-model="person.username"> <br>请输入年龄:<input type="text" v-model="person.age"> <br>请增加爱好:<input type="checkbox" value="吃饭"  v-model="person.hobbies"> 吃饭<input type="checkbox" value="睡觉"  v-model="person.hobbies"> 睡觉<input type="checkbox" value="打豆豆"  v-model="person.hobbies"> 打豆豆 <br><!-- 事件中调用person的doubleAge()方法 --><button @click="person.doubleAge()">年龄加倍</button> <br><!-- 事件中调用pinia提供的$reset()方法恢复数据的默认值 --><button @click="person.$reset()">恢复默认值</button> <br><!-- 事件中调用$patch方法一次性修改多个属性值 --><button @click="person.$patch({username:'奥特曼',age:100,hobbies:['晒太阳','打怪兽']})">变身奥特曼</button> <br>显示pinia中的person数据:{{person}}</div>
</template>
<style scoped>
</style>

6 List.vue中展示Pinia数据

<script setup type="module">import { definedPerson} from '../store/store';// 读取存储的数据let person= definedPerson()
</script><template><div><h1>List页面,展示Pinia中的数据</h1>读取姓名:{{person.username}} <br>读取年龄:{{person.age}} <br>通过get年龄:{{person.getAge}} <br>爱好数量:{{person.getHobbiesCount}} <br>所有的爱好:<ul><li v-for='(hobby,index) in person.hobbies' :key="index" v-text="hobby"></li></ul></div>
</template><style scoped>
</style>

7 定义组件路由router.js

// 导入路由创建的相关方法
import {createRouter,createWebHashHistory} from 'vue-router'// 导入vue组件
import List  from '../components/List.vue'
import Operate  from '../components/Operate.vue'
// 创建路由对象,声明路由规则
const router = createRouter({history: createWebHashHistory(),routes:[{path:'/opearte',component:Operate},{path:'/list',component:List},]})// 对外暴露路由对象
export default router;

8 App.vue中通过路由切换组件

<script setup type="module"></script><template><div><hr><router-link to="/opearte">显示操作页</router-link> <br><router-link to="/list">显示展示页</router-link> <br><hr><router-view></router-view></div>
</template><style scoped>
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/248450.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【Java程序设计】【C00184】基于SSM的旅游网站管理系统(论文+PPT)

基于SSM的旅游网站管理系统&#xff08;论文PPT&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于ssm的旅游网站管理系统 本系统分为前台用户、后台管理员2个功能模块。 前台用户&#xff1a;当游客打开系统的网址后&#xff0c;首先看到的就是首…

手机屏幕生产厂污废水处理需要哪些工艺设备

随着手机行业的快速发展&#xff0c;手机屏幕生产厂的规模也越来越大&#xff0c;但同时也带来了大量的污废水排放问题。为了保护环境和人类的健康&#xff0c;手机屏幕生产厂需要采取适当的工艺设备来处理污废水。本文将介绍手机屏幕生产厂污废水处理所需的工艺设备。 首先&am…

LeetCode —— 43. 字符串相乘

&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️Take your time ! &#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️&#x1f636;‍&#x1f32b;️…

OpenCV 2 - 矩阵的掩膜操作

1知识点 1-1 CV_Assert(myImage.depth() == CV_8U); 确保输入图像是无符号字符类型,若该函数括号内的表达式为false,则会抛出一个错误。 1-2 Mat.ptr(int i = 0); 获取像素矩阵的指针,索引 i 表示第几行,从0开始计行数。 1-3 const uchar* current = mylmage.ptr(row); 获得…

锁定 MinIO 操作员权限

虽然您可以使用 deployment 或 statefulset 在 Kubernetes 上部署 MinIO&#xff0c;但在 Kubernetes 上部署 MinIO 的推荐方法是通过官方的 MinIO Operator。为什么&#xff1f; MinIO Operator 简化了 Kubernetes 集群上的 MinIO 管理&#xff0c;不仅在初始部署期间&#x…

【LVGL源码移植环境搭建】

LVGL源码移植&环境搭建 ■ LVGL源码移植■ 下载LVGL源码■ 修改LVGL文件夹■■■■ 视频链接 Ubuntu模拟器环境建置 ■ LVGL源码移植 ■ 下载LVGL源码 LVGL源码 我们以选择v8.2.0为例&#xff0c;选择8.2.0下载 ■ 修改LVGL文件夹 1.我们只需要关注这5个文件即可&…

世界坐标系转换为平面地图坐标

将世界坐标系转换为平面地图坐标的方法通常涉及地图投影。地图投影是一种将地球(一个三维球体)上的点转换为平面(二维)地图上的点的方法。 这里介绍几种常见的地图投影方法: 墨卡托投影(Mercator Projection): 这是最常见的投影方式之一,尤其用于航海地图。它将经纬度…

解决:AttributeError: ‘str’ object has no attribute ‘capabilities’

解决&#xff1a;AttributeError: ‘str’ object has no attribute ‘capabilities’ 文章目录 解决&#xff1a;AttributeError: str object has no attribute capabilities背景报错问题报错翻译报错位置代码报错原因解决方法方法一&#xff1a;使用Service对象方法二&#x…

线性代数----------学习记录

线性代数发展历程 &#xff08;1&#xff09;线性方程组&#xff1a;例如二元一次方程组&#xff1b; &#xff08;2&#xff09;行列式&#xff1a;determinant,克莱默&#xff0c;莱布尼兹&#xff1b; &#xff08;3&#xff09;矩阵&#xff1a;方程个数与未知数的个数可…

vxe-table3.0的表格树如何做深层查找,返回搜索关键字的树形结构

vxe-table2.0版本是提供深层查找功能的&#xff0c;因为他的数据源本身就是树形结构&#xff0c;所以深层查找查询出来也是树形结构。 但是vxe-table3.0版本为了做虚拟树功能&#xff0c;将整个数据源由树形垂直结构变成了扁平结构&#xff0c;便不提供深层查询功能&#xff0c…

WAP在线封装APP工具:革新移动体验的技术

一、融合式设计&#xff1a;打破原生与网页应用的界限WAP封装App工具的最新版本已经能够实现无缝融合网页内容与原生应用功能。这些工具不仅仅是简单地将网页“包装”成APP&#xff0c;而是通过创新的融合式设计&#xff0c;让用户在使用过程中几乎感受不到两者之间的差异。例如…

综合案例 - 商品列表

文章目录 需求说明1.my-tag组件封装&#xff08;完成初始化&#xff09;2.may-tag封装&#xff08;控制显示隐藏&#xff09;3.my-tag组件封装&#xff08;v-model处理&#xff1a;信息修改&#xff09;4.my-table组件封装&#xff08;整个表格&#xff09;①数据不能写死&…

工业交换机的详细介绍

工业交换机是一种用于工业领域的网络通信设备&#xff0c;其设计专注于满足工业环境下的高可靠性、高带宽和低延迟的要求。与传统的家用交换机相比&#xff0c;工业交换机具有更强的耐高温、抗震动、抗干扰等特性&#xff0c;能够适应恶劣的工业环境。同时&#xff0c;工业交换…

宠物处方单子怎么开,宠物门诊处方管理软件教程

宠物处方单子怎么开&#xff0c;宠物门诊处方管理软件教程 一、前言 宠物店电子处方软件操作教程以 佳易王宠物店电子处方管理系统V16.0为例说明。 如图&#xff0c;在开处方的时候&#xff0c;点击导航栏菜单&#xff0c;兽医处方按钮 点击 增加新单&#xff0c;填写宠物及…

大模型重塑车载语音交互:赛道巨头如何引领新周期?

车载语音交互赛道正进入新一轮竞争周期。 高工智能汽车注意到&#xff0c;传统车载语音交互赛道当前基本已进入成熟期&#xff0c;主要为任务型助手&#xff0c;包括从单轮对话到多轮对话&#xff0c;单音区到多音区&#xff0c;从单一的导航、多媒体娱乐等座舱功能扩展智能驾…

正则表达式(RE)

什么是正则表达式 正则表达式&#xff0c;又称规则表达式&#xff08;Regular Expression&#xff09;。正则表达式通常被用来检索、替换那些符合某个规则的文本 正则表达式的作用 验证数据的有效性替换文本内容从字符串中提取子字符串 匹配单个字符 字符功能.匹配任意1个…

在centos 7 中 安装 配置 并 远程连接 MySQL5.7

目录 安装MySQL 1.卸载CentOS7系统自带的mariadb 2.安装依赖库 3.上传MySQL并解压 4.安装MySQL 配置MySQL 1.修改登录密码 2.修改字符集 3.配置远程连接 前言&#xff1a; 安装MySQL版本&#xff1a;mysql-5.7.30-1.el7.x86_64.rpm-bundle 文件需求后台私信 以下7条为…

(蓝桥杯每日一题)求最长回文串

问题描述 给出一个长度为 n 的小写字符串&#xff0c;求一个最长的子串 S&#xff0c;满足SXY,X&#xff0c;Y>1&#xff0c;且X,Y 均为回文串。 输入格式 输入包括一行: 第一行是一个长度为 n 的小写字符串。 输出格式 输出包括一行&#xff1a; 一行一个整数&#xff0c;表…

STM32连接阿里云物联网平台

文章目录 引言一、STM32连接阿里云物联网平台思路二、ESP8266烧录固件三、使用AT指令连接阿里云物联网平台四、STM32环形串口缓冲区驱动程序五、STM32连接阿里云驱动程序 引言 连续写了两篇关于阿里云连接的文章&#xff0c;都是使用Arduino ESP8266 & Arduino ESP32的方式…

关于如何将Win幻兽帕鲁服务端存档转化为单人本地存档的一种方法(无损转移)

本文转自博主的个人博客&#xff1a;https://blog.zhumengmeng.work,欢迎大家前往查看。 原文链接&#xff1a;点我访问 **起因&#xff1a;**最近大火的开放世界缝合体游戏幻兽帕鲁的大火也是引起了博主的注意&#xff0c;然后博主和周边小伙伴纷纷入手&#xff0c;博主也是利…