- Java锁的逻辑(结合对象头和ObjectMonitor)
- 还在用饼状图?来瞧瞧这些炫酷的百分比可视化新图形(附代码实现)⛵
- 自动注册实体类到EntityFrameworkCore上下文,并适配ABP及ABPVNext
- 基于Sklearn机器学习代码实战
前端路由的一个大背景就是当下流行的单页应用SPA,一些主流的前端框架,如vue、react、angular都属于SPA,那什么是SPA呢?
SPA (single-page application)单页面应用,就是浏览器只加载了一个URL地址,一个页面,应用的所有功能、交互都在这个页面内进行。而实现单页面应用的基础就是 ajax ,通过异步请求动态的切换页面内容、实现交互,页面整体没有刷新。这避免了页面URL跳转,用户体验也不会中断,就像原生应用一样,体验比较好。越来越多的系统在使用SPA,尤其是WebApp中使用广泛.
与 SPA 单页应用对应的就是多页应用 MPA ,当然两者不是非此即彼的,主要基于业务需求,是可以共存的.
区别 | 单页面应用(SPA) | 多页面应用(MPA) |
---|---|---|
页面组成 | 一个主页,包含多个页面片段 | 多个主页面 |
刷新方式 | 局部刷新 | 整页刷新 |
url模式 | hash 哈希模式 、 history 历史模式 |
history 历史模式 |
SEO搜索引擎优化 | 难实现,采用页面静态化方式优化 | 容易实现 |
数据传递 | 同一应用内,容易 | 通过url、cookie、localStorage等传递,复杂 |
渲染性能 | 首次加载资源多稍慢,切换快,体验良好 | 切换加载资源,速度慢,用户体验差 |
转场动画 | 容易实现 | 好像实现不了 |
维护成本 | 相对容易 | 相对复杂 |
SPA的主要表现就是 更新视图 而不重新请求页面,要实现前端的页面的自主路由控制,而不会刷新页面,涉及两种主流的技术: hash 模式、 history 模式,这算是前端路由的核心原理,简单了解一下吧! 。
hash ( /hæʃ/ )是URL地址中#号后面的内容(包括#),原本的作用是用于HTML页面内部定位的描点,描点的变化不会导致页面重新加载。HTTP请求中也不会带#,所以刷新也不影响,这是浏览器端的本地行为.
hash
的变化不会刷新页面,只会触发浏览器定位锚点,这是 hash
实现前端路由的基本原理。 hash
: window.location.hash
hash
变更事件 : window.hashchange
监听 hash
变化。 hash
会进入浏览器历史记录。 http://www.xxx.cn/#/about http://www.xxx.cn/#/pro-info-list 。
所以,实现过程就比较简单了! 。
❶ 监测hash变化 :通过 hashchange 事件监测 hash 变化 .
❷ 加载资源 :根据 hash 值匹配不同资源进行加载、切换,在Vue中切换的其实就是不同的组件.
🌰hash-简易路由示例: codepen 。
<div id="app2">
<ul id="nav" v-once>
<li v-for="item in navs" v-if="item.title"><a v-bind:href="'#/'+item.url">{{item.title}}</a></li>
</ul>
<div id="main">
<keep-alive>
<component v-bind:is="currentComponent"></component>
</keep-alive>
</div>
</div>
<script>
//components
const NotFound = { template: '<p>404!Page not found</p>' };
const Home = { template: '<p>首页<br>Home page</p>' };
const Product = { template: '<p>产品页面<br>Product page<br><input></p>' };
const About = { template: '<p>关于我们<br>About page</p>' };
//导航路由数据
function Route(title, url, name, component) {
this.title = title; this.url = url; this.component = component; this.name = name;
}
let routes = [
new Route("首页", "home", 'home', Home), new Route("商品", "protect", 'protect', Product),
new Route("招聘", "hr", null, null), new Route("关于", "about", 'about', About),
new Route(null, "not-found", 'not-found', NotFound)];
let components = {};
routes.forEach(item => { components[item.name] = item.component });
//app
let app2 = new Vue({
el: "#app2",
data: { currentRoute: window.location.hash, navs: Object.freeze(routes) },
computed: {
currentComponent: function () {
const com = this.navs.filter(item => '#/' + item.url === this.currentRoute)[0];
if (com && com.component) {
document.title = com.title;
return com.name;
}
return 'not-found';
}
},
components: components,
created: function () {
window.addEventListener("hashchange", () => {
this.currentRoute = window.location.hash;
});
}
});
</script>
history 是历史对象,存放当前文档页面(或框架)的会话历史记录(不是浏览器的所有历史记录).
history 属性/方法 | 描述 |
---|---|
length | 会话历史列表的记录数量 |
state | 表示历史堆栈顶部记录的状态值,可以是任意可序列化JavaScript对象,限制为2MB |
pushState (stateObj, title[, url]) | 向当前会话的历史堆栈中添加一条记录 |
replaceState (stateObj, title[, url]) | 修改 history 对象的当前(栈顶)记录 |
back () | 返回到(历史列表中)上一个URL地址。 |
forward () | 前进,加载(历史列表中)下一个URL地址 |
go (number) | 加载指定 相对当前网页 索引位置的历史列表URL地址,go(-1)等同于back() |
pushState 、 replaceState 是HTML5在 history 上新增的API,用来新增、修改当前文档的历史记录,这两个API就是用来实现SPA单页应用前端路由的关键。他们的参数相同: (stateObj, title[, url]) 。
popstate
事件时作为参数传递,不需要可以为null,通过 history.state
可以获取到当前会话的 state
。 url
会更新到浏览器地址栏,但并不会加载该 url
地址,也不检查是否存在,页面也不会刷新 !对,要的就是你不刷新。 基于这两个API的特性来实现前端路由。用 pushState 还是 replaceState 呢?两者作用一样的,唯一的不同就是 pushState 会产生历史记录,可用于前进、后退.
① 监测url地址变化 , 。
popstate
事件 :当 state
变化时触发该事件,在事件中获取当前 url
地址。pushState、replaceState并不会触发 popstate
事件,前进、后退、跳转才会触发。 click
事件, pushState()
更新 url
。 ② 加载资源 :根据 url 值匹配不同资源进行加载、切换.
📢注意 ,页面第一次加载的时候,不会触发 popstate 事件.
history-简易路由示例: codepen 。
<div id="app3">
<ul id="nav" v-once>
<li v-for="item in navs" v-if="item.title">
<a href="#" v-on:click.prevent="navClick(item)">{{item.title}}</a></li>
</ul>
<div id="main">
<keep-alive>
<component v-bind:is="currentComponent"></component>
</keep-alive>
</div>
</div>
<script>
//components
const NotFound = { template: '<p>404!Page not found</p>' };
const Home = { template: '<p>首页<br>Home page</p>' };
const Product = { template: '<p>产品页面<br>Product page<br><input></p>' };
const About = { template: '<p>关于我们<br>About page</p>' };
//导航路由数据
function Route(title, url, name, component) {
this.title = title; this.url = url; this.component = component; this.name = name;
}
let routes = [
new Route("首页", "home", 'home', Home), new Route("商品", "protect", 'protect', Product),
new Route("招聘", "hr", null, null), new Route("关于", "about", 'about', About),
new Route(null, "not-found", 'not-found', NotFound)];
let components = {};
routes.forEach(item => { components[item.name] = item.component });
//拦截history.pushState,触发一个事件。不拦截换其他方式也可以,比如点击事件里。
history.pushState = (function (type) {
let origin = history[type]; //用闭包来存储原来的方法
return function () {
let out = origin.apply(this, arguments);
let event = new Event(type); //触发一个自定义事件pushState
event.arguments = arguments;
window.dispatchEvent(event);
return out;
}
})('pushState');
//app
let app3 = new Vue({
el: "#app3",
data: { currentRoute: history.state?.url, navs: Object.freeze(routes) },
computed: {
currentComponent: function () {
const com = this.navs.filter(item => item.url === this.currentRoute)[0];
if (com && com.component) {
document.title = com.title;
return com.name;
}
return 'not-found';
}
},
components: components,
methods: {
navClick: function (route) {
history.pushState({ url: route.url }, null, route.url);
}
},
created: function () {
window.addEventListener("popstate", () => {
this.currentRoute = history.state?.url; //也可以用location.pathname获取前端url
});
window.addEventListener("pushState", () => { //监听自定义事件pushState
this.currentRoute = history.state?.url;
});
}
})
</script>
📢 刷新页面 时会重新加载当前(本地路由的) url 地址,可能就404了,这就需要服务端支持,修改下nginx代理也是可以解决的。 ❗ history与hash的主要区别 ,就是不会出现一个 # ,看上去更加美观?好像也没啥区别吧! 。
Vue Router是Vue官方推出的路由组件,与Vue深度集成,支持 hash 、 history 两种模式.
Vue2.*
版本 ▶ 对应 vue-router3.*
版本, vue-router3.* 中文文档 Vue3.*
版本 ▶ 对应 vue-router4.*
版本, vue-router4.* 中文文档 <script>
标签直接引用 vue-router.js
:
<script src="https://unpkg.com/vue@2/dist/vue.js"></script>
<script src="https://unpkg.com/vue-router@3/dist/vue-router.js"></script>
// 注册插件
Vue.use(VueRouter);
vue-cli
脚手架搭建 vue
的开发框架,集成了 vue-router
组件。 Vue.use(VueRouter)
✔️ Router 选项 | 描述 |
---|---|
routes | 路由记录配置信息, Array<RouteConfig> |
mode | 路由模式,默认 hash ,选项: hash 、 history 、abstract(NodeJS环境) |
base | url的基本路径, "/app/" ,只有history模式有效? |
linkActiveClass | <route-link> 激活的 class 名称,默认值为 router-link-active |
linkExactActiveClass | 精确匹配激活的 class ,默认值为 router-link-exact-active ( exact /ɪɡˈzækt/ 精确) |
scrollBehavior | 路由切换完成后的 滚动行为回调 ,函数 Func(to, from, savedPosition) |
parseQuery/stringifyQuery | 自定义查询字符串的解析/反解析函数 |
//创建路由器
let vrouter = new VueRouter({ routes: vroutes, mode: 'hash', base: '/vsystem/' });
✔️ routes.route RouteConfig |
初始化时配置用的 路由记录 RouteConfig ,在后续代码中使用的为 路由对象 |
---|---|
path | 路由url路径 path: '/user' |
component | Component 组件,可用函数方式 import 懒加载组件,提高初始化的性能 |
components | 命名视图组件,当有多个命名视图 <router-view> 时,也要配置对应的组件 |
name | 给路由取个名字,自己用,没其他用途,可作为显示的中文标题 |
redirect | 重定向路由,重定向到另外的path、route。如果带有query会解析路由出错? |
alias | path的别名,可一个或多个(数组 Array<string> )别名,渲染组件一样 |
parent | 父级路由,根级的 parent 为 undefined |
children | 子路由 Array<RouteConfig> ,组件内用 <router-view> 组件作为嵌套组件的容器 |
props | 用于给Vue组件参数 Props 传值:boolean | Object | Function - true :自动传递动态路径参 route.params ; - 对象,函数 :把它们的结果赋值给组件props参数(按key) |
beforeEnter (to, from, next) | 执行路由前的一个钩子,私有的钩子,目的同全局的守卫钩子 beforeEach |
meta | 路由元信息,自定义的个性化配置,在路由钩子中可以访问处理。 meta:{title:'注册'} |
✔️运行态的 $ route 路由对象 |
组件内 this.$route 访问,钩子函数、导航函数中的to、from、location都是此路由对象 |
---|---|
path | 路由url路径 |
fullPath | 解析后的完整url,包含query |
params | 存放动态路径参数,{key:value }对象,组件内使用 this.$route.params.id |
query | url查询参数,{key:value }对象 |
hash | 当前路由的哈希 hash 值 |
name | 路由名称 |
meta | 元数据记录 |
matched | 匹配到的路由记录列表 |
interface RouteConfig = {
path: string,
component?: Component,
name?: string, // 命名路由
components?: { [name: string]: Component }, // 命名视图组件
redirect?: string | Location | Function,
props?: boolean | Object | Function,
alias?: string | Array<string>,
children?: Array<RouteConfig>, // 嵌套路由
beforeEnter?: (to: Route, from: Route, next: Function) => void,
meta?: any,
// 2.6.0+
caseSensitive?: boolean, // 匹配规则是否大小写敏感?(默认值:false)
pathToRegexpOptions?: Object // 编译正则的选项
}
//$route路由对象
{
name: "user-box", // 路由名称
fullPath: "/user/21/vip?key=admin",
hash: "", // 当前路由的哈希
matched: [{… }],
meta: {},
params: { id: '21', type: 'vip' },
path: "/user/21/vip",
query: { key: 'admin' }
}
🌰简单的示例:
<style>
.router-link-active{ background-color: rgb(168, 240, 140); }
.nav-item{ margin: 0 10px; }
</style>
<div id="app">
<router-link v-for="r in this.$router.options.routes" :to="r.path" class="nav-item">{{r.name}}</router-link>
<router-view></router-view> <!-- 显示路由组件视图的容器,其实是就是一个动态组件 -->
</div>
<script>
//路由配置RouteConfig
let vroutes = [
{ path: '/user', name: '用户管理', component: { template: '<div>user component</div>' } },
{ path: '/login', name: '登录', component: { template: '<div>login component</div>' } }];
//创建路由器
let vrouter = new VueRouter({ routes: vroutes, mode: 'hash', base: '/vsystem/' });
//app
let app = new Vue({
el:"#app",
router: vrouter,
})
</script>
✔️router实例- 属性 | 描述 |
---|---|
app、apps | Vue根实例,所有apps实例 |
options | 参数选项 |
currentRoute | 当前激活的路由信息对象 |
mode | 路由模式:"hash" | "history" | "abstract" |
START_LOCATION | 初始导航的路由地址,route对象 |
✔️Router实例- 方法 | 描述 |
全局的导航守卫 | beforeEach、beforeResolve、afterEach |
编程式导航 | push(route)、replace(route)、go(index)、back()、forward() |
resolve() | ❓解析目标位置 |
addRoute (parent?, RouteConfig) | 添加路由记录、子路由,还有批量添加的 addRoutes(routes) |
getRoutes () | 获取所有活跃的路由记录列表 Array<RouteConfig> |
onReady(callback,errorback) | 完成初始化后调用,初始化错误则调用errorback |
onError(callback) | 路由过程中出错时触发,算是一个全局路由异常捕获 |
Vue.use(VueRouter)
router
路由器实例,并配置路由记录。 router
,在根Vue组件上注入 router
实例,然后所有地方都可以用 this.$router
访问了. <router-link>
显示路由导航, <router-view>
显示组件视图。 this.$router
,Vue中任意地方可以访问的路由器。 this.$route
,组件所属的 route
路由对象。 🌰创建一个路由:
<style>
#app4 a { margin: 0 5px; }
.router-link-active { background-color: blueviolet; color: #FFF; }
</style>
<div id="app4">
<p>{{$router.mode}}-->{{$router.currentRoute.name}}</p>
<div>
<router-link to="/user/001">用户001</router-link>
<router-link to="/login">登录</router-link>
<a href="#" @click.prevent="$router.push('/user/002')">a-用户0002</a>
</div>
<hr>
<router-view></router-view>
</div>
<script>
// 注册插件
Vue.use(VueRouter);
let isAuthenticated = true;
//组件
const UserBox = { Prop: ['userId'], template: '<p>用户信息:{{$route.params}}</p>' };
const Login = { template: '<p>用户登录:<br>用户名:<input></p>' };
//路由配置
let vroutes = [
{ path: '/user/:userId', name: '用户管理', component: UserBox },
{ path: '/login', name: '登录', component: Login, meta: { type: 'vip' } },
{ path: '/*', redirect: '/login' }];
//创建路由器
let vrouter = new VueRouter({ routes: vroutes, mode: 'hash', base: '/vsystem/' });
//路由器的钩子:做一个登录权限验证,并更新文档标题
vrouter.beforeEach((to, from, next) => {
if (to.name !== 'Login' && !isAuthenticated) next({ name: 'Login' });
else next();
document.title = to.name;
});
//app
let app4 = new Vue({
el: "#app4",
router: vrouter, //注入路由器,内部通过 this.$router 访问
})
</script>
path 为路由的地址,当浏览器 url 地址与 path 匹配时,就会激活当前route路由对象,并显示器对应组件 component/components .
let u1 = { path: '/home', component: Home };
let u2 = { path: '/about', component: About };
let u3 = { path: '/user/register', component: Register };
let u3 = { path: '/*', component: NotFound404 };
//动态路径
let u1 = { path: '/user/:id/:type', component: UserBox }
//匹配的路径
<router-link to="/user/1/vip">用户1</router-link>
🔸 : 动态路径参数 : path 中可以设置动态参数,冒号 : 开头,后面的为参数,支持多个顺序组装: path:'/path/:参数1/:参数2' 。这里的参数有什么用呢?
$route.params
中。 $route.params.id
。 props:true
,参数值 $route.params
会传递给组件的参数 Props
。 🔸 * 通配符 : * 通配符匹配任意字符,可放到最后面匹配404,或重定向到默认路由。v4版本里删了,改用正则.
🔸 优先级 :如果相同的path,匹配哪个呢?按照代码的顺序,先到先得.
<router-link>
: 路由导航组件 ,绑定路由配置,执行路由跳转。 <router-link>
也是一个组件,实际是一个 <a>
元素。 <router-view>
: 路由视图组件 ,用来显示渲染匹配的视图组件,内部是一个Vue动态组件。如果需要动画和缓存,可以外面嵌套 <transition>
、 <keep-alive>
使用。 ✔️ <router-link> |
描述 |
---|---|
to | path,路由的目标地址,字符串、路由对象。 |
replace | 默认 false = push ,执行导航是用 replace ,还是 push ,对应 history 的两个Api |
append❓ | 是否添加基路径 base ,默认 false |
tag | 最终渲染的的标签,默认 a 。 v4中删掉了,用v-slot实现自定义 |
active-class | 激活的类class名 |
exact | 是否精确匹配连接地址,默认false。就是说默认是模糊匹配连接地址的,只要包含就激活了 |
event | 触发路由的事件类型,默认 click 。不怎么常用,v4版本中删掉了 |
v-slot | 作用域插槽,用来接收暴露出来的数据, <router-link> 支持插槽 |
✔️ <router-view> |
|
name | 命名视图,当有多个就需要名字了,如切换框架布局。在路由记录 components 中配置映射关系 |
<style>
#app a{ margin: 0 10px; }
.router-link-active { background-color: rgb(168, 240, 140); }
/* 动画css */
.v-enter, .v-leave-to { opacity: 0; }
.v-enter { transform: translateX(30px); }
.v-enter-active, v-leave-active { transition: all 1s; }
</style>
<div id="app">
<div>
<h4>router-link</h4>
<router-link to='/user/1/vip'>用户管理1</router-link>
<router-link to='/login'>登录</router-link>
<!-- url变了,但没有触发路由 -->
<a href="#user/2/vvip">a-用户2</a>
<a href="#" @click.prevent="$router.push('/user/003/vvip')">a-用户3</a>
</div>
<div>
<h4>v-for绑定</h4>
<router-link v-for="r in this.$router.options.routes" :to="r.path">{{r.name}}</router-link>
</div><hr>
<transition>
<keep-alive>
<router-view style="margin:10px"></router-view>
</keep-alive>
</transition>
</div>
<script>
//路由配置RouteConfig
let vroutes = [
{ path: '/user/:id/:type', name: '用户管理', component: { template: '<div>user component{{$route.params}}</div>' } },
{ path: '/login', name: '登录', component: { template: '<div>login component<br><input></div>' } }];
//创建路由器
let vrouter = new VueRouter({ routes: vroutes, mode: 'hash', base: '/vsystem/' });
//app
let app = new Vue({
el: "#app",
router: vrouter,
})
</script>
📢 当 <router-link> 需要监听原生事件时,要加上原生修饰符 @click.native="nav_click" 。
除了使用申明式导航 <router-link> 组件,也可也使用编程式的导航方法自定义实现导航,就是调用router提供的导航方法.
router实例-导航方法 | |
---|---|
push (location, onComplete?, onAbort?) | location 可以是url字符,也可以是route对象 |
replace (location, onComplete?, onAbort?) | 同上,不会添加 history 记录, |
go(index)、back()、forward() | 和浏览器的history操作一样的,历史页面里跳转 |
path
,则会忽略 params
(param /ˈpærəm/ 参数)。 this.$router.push('/user').then(onComplete).catch(onAbort) 。
<div>
<h4>a标签,编程式导航</h4>
<a href="#" @click.prevent="$router.push({path:'user/21/vip',query:{key:'admin'}})">用户1</a>
<a href="#" @click.prevent="navClick">click登录</a>
<a @.prevent href="#/login?key=hello">原生a</a>
<br>
<a href="#" @click.prevent="$router.back()">后退</a>
<a href="#" @click.prevent="$router.forward()">前进</a>
</div>
<script>
let app = new Vue({
el: "#app",
router: router,
methods: {
navClick() {
if (this.$router.currentRoute.path == '/login')
return;
this.$router.push('/login', null, () => { }); //提供一个空的onAbort
this.$router.replace('/login');
this.$router.push('/user').then(onComplete).catch(onAbort); //promise方式使用
//设置了path,params的设置就忽略了
this.$router.push({ path: '/login', query: { key: 'admin' }, params: { id: 100 } });
//也可以用name进行导航。注意后面的catch,因为push、replace都是用promise执行的
this.$router.push({ name: '登录', query: { key: 'admin' }, params: { id: 12 } }).catch(s => { });
}
}
})
</script>
⚠️ 这里遇到一个小问题 ,就是通过编程事件导航的 <a> 链接重复点击报错:NavigationDuplicated 。
原来是 vue-router 的一个问题, 3.* 版本中引入了promise时也引入了这个bug,如果路由没变化(重复)就会抛出一个异常的 promise 。 v4.* 版本都出来了,这个bug还没修复! <router-link> 正常,只有导航编程才会.
🟢解决方法 :
- 判断一下当前路由是否已存在。
- 提供一个空的
onAbort
回调,或者promise
的方式捕获异常。- 改造一下
VueRouter.prototype
的push
方法。
在导航过程中提供多种守卫(钩子函数),需要注意的是,动态 path 参数、 <keep-alive> 都会复用组件,此时组件的生命周期就不完整了,需要根据实际情况选择合适的地方.
✔️router实例- 全局钩子守卫 | 描述 |
---|---|
beforeEach (to, from, next) | 导航执行前,可通过 next 取消。可用来验证登陆权限,如果没认证则跳转到登陆 |
beforeResolve (to, from, next) | beforeEach 执行后,也是前置守卫 |
afterEach (to, from) | 导航已经离开时触发,这里没有next(不可取消路由),因为已经离开了 |
✔️ 路由配置记录 route-的独有钩子 | |
beforeEnter (to, from, next) | 执行路由前调用 |
✔️ Vue组件 中新增的-钩子守卫 | Vue组件的钩子 |
beforeRouteEnter (to, from, next) | 进入前:组件路由被confirmed(已确认)前,组件还没创建,不能获取 this |
beforeRouteUpdate (to, from, next) | 只有动态 path 参数复用组件时才触发,更新当前路由。 |
beforeRouteLeave (to, from, next) | 路由将要离开该组件前触发, this 可用, next(false) 可取消。 |
🔸钩子的参数 : (to, from, next) 。
to: Route
:目标路由对象。 from: Route
:当前导航路由对象,也是要离开的。 next: Function
:本次路由怎么执行?内置的回调,必须调用。
nex()/next(true)
:允许执行,并继续,全部钩子执行完毕,导航状态为confirmed(已确认)。 next(false)
:🚫 不执行 ,中断当前导航,重置导航到from。 next({route})
:❗中断当前导航,并进行一个新的导航到 route
。 特殊next(callback)
: beforeRouteEnter
的 next
接收一个回调函数,参数为组件 vm
,可用来请求一些ajax数据,回调会在组件创建后调用。 🟢导航守卫-钩子的生命周期流程图, 守卫钩子测试代码: CodePen 。
🔸使用意见 :
beforeEach
,若只是针对某个特定路由,则用路由记录的独有钩子 beforeEnter
。 watch
监测路由对象 $route
的变化也是一个途径。 history
: createWebHistory()
、 createWebHashHistory()
。
const router = createRouter({
history:createWebHashHistory() / createWebHashHistory(),
routes: [],
})
base
放到了上面的创建函数参数里。 router.onReady()
改为 IsReady()
,该方法返回一个 Promise
。 <router-view>
支持了插槽 v-slot
,支持就算了,关键是影响有点大。
<keep-alive>
和 <transition>
只能通过插槽嵌入到 <router-view>
里面,不像之前是放到外面的。 <router-view>
组件的模板也只能通过 v-slot
+ 动态组件来实现了。
<router-view v-slot="{ Component }">
<transition>
<keep-alive>
<component :is="Component" />
</keep-alive>
</transition>
</router-view>
<router-link>
的 tag
没了,通过插槽实现。 ❓如何构建多级菜单的导航?基本思路:
❓多标签怎么实现,可以管理使用多个标签?基本思路:
©️版权申明 :版权所有@安木夕,本文内容仅供学习,欢迎指正、交流,转载请注明出处! 原文编辑地址-语雀 。
最后此篇关于vue-router路由之路-极简教程的文章就讲到这里了,如果你想了解更多关于vue-router路由之路-极简教程的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
我正在做一个关于代码学院的教程,我在这里收到一个错误,说“看起来你的函数没有返回‘唉,你没有资格获得信用卡。资本主义就是这样残酷。’”当收入参数为 75 时。”但是该字符串在控制台中返回(由于某种原因
我正在阅读 Go 的官方教程,但很难理解 Channel 和 Buffered Channels 之间的区别。教程的链接是 https://tour.golang.org/concurrency/2和
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题? Update the question所以它是on-topic对于堆栈溢出。 9年前关闭。 Improve this que
已关闭。此问题不符合Stack Overflow guidelines 。目前不接受答案。 要求我们推荐或查找工具、库或最喜欢的场外资源的问题对于 Stack Overflow 来说是偏离主题的,因为
作为 iOS 新手,有大量书籍可以满足学习基础知识的需求。现在,我想转向一些高级阅读,例如 OAuth 和 SQLite 以及动态 API 派生的 TableView 等。您可以推荐任何资源吗? 最佳
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
关闭。这个问题是opinion-based .它目前不接受答案。 想要改进这个问题? 更新问题,以便 editing this post 可以用事实和引用来回答它. 关闭 8 年前。 Improve
关闭。这个问题不符合Stack Overflow guidelines .它目前不接受答案。 我们不允许提问寻求书籍、工具、软件库等的推荐。您可以编辑问题,以便用事实和引用来回答。 关闭 8 年前。
前言 很多同学都知道,我们常见的CTF赛事除了解题赛之外,还有一种赛制叫AWD赛制。在这种赛制下,我们战队会拿到一个或多个服务器。服务器的连接方式通常是SSH链接,并且可能一个战队可能会同时有
Memcached是一个自由开源的,高性能,分布式内存键值对缓存系统 Memcached 是一种基于内存的key-value存储,用来存储小块的任意数据(字符串、对象),这些数据可以是数据库调用、A
Perl 又名实用报表提取语言, 是 Practical Extraction and Report Language 的缩写 Perl 是由 拉里·沃尔(Larry Wall)于19
WSDL 是 Web Services Description Language 的缩写,翻译成中文就是网络服务描述语言 WSDL 是一门基于 XML 的语言,用于描述 Web Services 以
关闭。这个问题不满足Stack Overflow guidelines .它目前不接受答案。 想改善这个问题吗?更新问题,使其成为 on-topic对于堆栈溢出。 6年前关闭。 Improve thi
我正在寻找解释在 WPF 中创建自定义用户控件的教程。 我想要一个控件,它结合了一个文本 block 、一个文本框和一个启动通用文件打开对话框的按钮。我已经完成了布局,一切都连接好了。它有效,但它是三
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
我接近 fourth page of the Django tutorial 的开始看着vote查看,最后是这样的: # Always return an HttpResponseRedirect a
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用资料或专业知识的支持,但这个问题可能会引发辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the
是否有任何好的 Qt QSS 教程,或者在某个地方我可以看到样式小部件的示例?如果某处可用,我想要一些完整的引用。除了有关如何设置按钮或某些选项卡样式的小教程外,我找不到任何其他内容。 最佳答案 Qt
就目前而言,这个问题不适合我们的问答形式。我们希望答案得到事实、引用或专业知识的支持,但这个问题可能会引起辩论、争论、投票或扩展讨论。如果您觉得这个问题可以改进并可能重新打开,visit the he
我是一名优秀的程序员,十分优秀!