其他章节请看:

vue 快速入门 系列

Vue Router

Vue Router 是 Vue.js 官方的路由管理器。它和 Vue.js 的核心深度集成,让构建单页面应用变得易如反掌。

什么是路由

路由就是根据不同的 url(网址) 返回不同的页面(数据)。如果这个工作在后端做(或者说由后端程序员做),就是后端路由;在前端做就是前端路由。

绝大多数的网站是后端路由。流程就像这样:

  1. 浏览器输入 url,回车
  2. 后端服务器接收到请求
  3. 将请求(url)交给对应的处理逻辑 —— 有一个专门的正则配置列表来分发
  4. 各种操作完成后,最后将页面(数据)返回给浏览器

平时总说的 SPA(单页面应用)就是前后端分离的基础上,再加一层前端路由。

Vue Router 的核心

无论是后端路由还是前端路由,解决的核心问题应该都是一样的。

后端路由常见的 2 种场景:

  • 浏览器输入 url,后端返回相应的页面
  • 在网页中点击 a 标签,跳转到 a 标签指向的页面

Vue Router 与后端路由对应的场景:

  • 根据 url 返回相应的组件

    • 核心1:提供一个 map 的数据结构解决此事
  • 在网页中点击标签,跳转到相应的页面
    • 核心2:提供内置标签 <router-link>,默认是a标签
  • 由于是做单页面应用,也就是只有一个页面,切换页面也就是切换组件,那么组件在哪里显示,这是前端路由需要解决的
    • 核心3:提供<router-view>来解决此事

环境准备

通过 vue-cli 创建项目

// 项目预设 `[Vue 2] less`, `babel`, `router`, `vuex`, `eslint`
$ vue create test-vue-router

启动服务:

$ test-vue-router> npm run serve

页面如果成功显示,说明环境准备完成,下面的例子都是基于这个项目进行。

Tip:保存代码如果遇到 eslint 的干扰(例如下面信息),可以通过配置 lintOnSave 生产构建时禁用 eslint-loader

test-vue-router\src\views\About.vue
7:1 error More than 1 blank line not allowed no-multiple-empty-lines
12:10 error Missing space before function parentheses space-before-function-paren
16:14 error Missing space before function parentheses space-before-function-paren
18:38 error Extra semicolon semi
20:7 error Block must not be padded by blank lines padded-blocks 5 problems (5 errors, 0 warnings)
5 errors and 0 warnings potentially fixable with the `--fix` option.
// vue.config.js
module.exports = {
lintOnSave: process.env.NODE_ENV !== 'production'
}

demo1 - 起步 - 欢迎来到首页

需求:访问 http://localhost:8080/,页面显示 欢迎来到首页

步骤如下:

首先我们查看 router 的核心文件:

// src/router/index.js
// vue-cli自动生成。无需修改
import Vue from 'vue'
import VueRouter from 'vue-router'
import Home from '../views/Home.vue' Vue.use(VueRouter)
// 核心1 - map
const routes = [
{
path: '/', // {1}
name: 'Home',
component: Home // {2}
},
{
path: '/about',
name: 'About',
// route level code-splitting
// this generates a separate chunk (about.[hash].js) for this route
// which is lazy-loaded when the route is visited.
component: () => import(/* webpackChunkName: "about" */ '../views/About.vue')
}
]
// 实例化路由器
const router = new VueRouter({
routes
}) export default router

接着修改 App.vue 和 Home.vue 即可:

// src/views/Home.vue
<template>
<p>欢迎来到首页</p>
</template>
// src/App.vue
<template>
<div id="app">
<!-- 核心3 - <router-view> 渲染路径匹配到的视图组件-->
<router-view/>
</div>
</template>

流程是:

  1. 浏览器输入 http://localhost:8080/
  2. 在 map 中匹配(行{1})
  3. 将 map 中匹配到的组件(行{2})渲染到 <router-view/>

demo2 - 注册

需求:在首页中增加一个注册按钮,点击注册,跳转到注册页。在注册页点击注册,在回到首页。(建议在demo1基础上做)

以下是核心代码:

// views/Home.vue
<template>
<div>
<p>
<!-- 核心2 - to 表示目标路由的链接 -->
<router-link to="/register">注册</router-link>
</p>
<p>欢迎来到首页</p>
</div>
</template>
// router/index.js
// 新增
import Register from '../views/Register' const routes = [
{
path: '/',
component: Home
},
// 新增
{
path: '/register',
component: Register
}
]
// views/Register.vue
<template>
<section>
<p>用户名:<input type="text" /></p>
<p>密码:<input type="password" /></p>
<p><router-link to="/">注册</router-link></p>
</section>
</template>

动态路由匹配

$route.params

我们经常需要把某种模式匹配到的所有路由,全都映射到同一个组件。可以这样:

// router/index
routes: [
// 动态路径参数 以冒号开头
{ path: '/user/:id', component: User }
]

/user/foo/user/bar 都将映射到相同的路由

一个“路径参数”使用冒号 : 标记。当匹配到一个路由时,参数值会被设置到 this.$route.params,可以在每个组件内使用。

需求:创建一个显示文章的组件,根据不同的 id 显示对应的文章,url 是 /article/:id

// router/index.js
// 新增
import Article from '../views/Article' const routes = [
// 新增
{
path: '/article/:id',
component: Article
}
]
// views/Article.vue
<template>
<div>
<p>文章列表页</p>
<p>这是对应 <em>{{ $route.params.id }}</em> 的文章</p>
</div>
</template>

测试:

浏览器输入:http://localhost:8080/article/2

页面输出:
文章列表页 这是对应 2 的文章

Tip$route(路由对象) 对象还提供了其它有用的信息:

  • $route.path,字符串,对应当前路由的路径,总是解析为绝对路径,如 "/foo/bar"
  • $route.query,一个 key/value 对象,表示 URL 查询参数。例如,对于路径 /foo?user=1,则有 $route.query.user == 1,如果没有查询参数,则是个空对象。
  • $route.hash,当前路由的 hash 值 (带 #) ,如果没有 hash 值,则为空字符串
  • $route.fullPath,完成解析后的 URL,包含查询参数和 hash 的完整路径。
  • $route.matched
  • $route.name,当前路由的名称,如果有的话
  • $route.redirectedFrom,如果存在重定向,即为重定向来源的路由的名字

匹配优先级

有时候,同一个路径可以匹配多个路由,此时,匹配的优先级就按照路由的定义顺序:路由定义得越早,优先级就越高。

嵌套路由

嵌套路由也或叫子路由。即一个组件内可以有自己的<router-view>

常见的的一个场景是,有一个组件 Article,里面有个坑位,这个坑位有时(根据url的变化)需要显示 ArticleComponentA 组件,有时显示 ArticleComponentB 组件。

index.js:

// 新增
import ArticleComponentA from '../views/ArticleComponentA'
import ArticleComponentB from '../views/ArticleComponentB' const routes = [
// 新增
{
path: '/article/:id',
component: Article,
children: [
{
// 当 /user/:id/ca 匹配成功,
// ArticleComponentA 会被渲染在 User 的 <router-view> 中
path: 'ca',
component: ArticleComponentA
},
{
// 当 /user/:id/cb 匹配成功
path: 'cb',
component: ArticleComponentB
}
]
}
]
// views/ArticleComponentA.vue
<template>
<div style="border: 1px solid">
<p>我是A</p>
<p>
这是对应 <em>{{ $route.params.id }}</em> 的文章
</p>
</div>
</template>
// views/ArticleComponentA.vue
<template>
<div style="border: 1px solid">
<p>我是B</p>
<p>
这是对应 <em>{{ $route.params.id }}</em> 的文章
</p>
</div>
</template>
// views/Article.vue
<template>
<div>
<p>文章列表页</p>
<!-- 子路由 -->
<router-view></router-view>
</div>
</template>

测试:

浏览器输入:http://localhost:8080/article/1/cb

页面显示:
文章列表页 我是B 这是对应 1 的文章

编程式的导航

除了使用 <router-link> 创建 a 标签来定义导航链接,我们还可以借助 router 的实例方法,通过编写代码来实现。

需求:编写支付组件,显示支付成功,三秒后自动跳转到首页

index.js:

// 新增
import Pay from '../views/Pay' const routes = [
// 新增
{
path: '/pay',
component: Pay
},
]

Pay.vue:

<template>
<div>
<p>支付成功,三秒后自动跳转到首页</p>
</div>
</template> <script>
export default {
created: function(){
setTimeout(()=>{
// 编程式导航
this.$router.push('/')
}, 3000)
}
}
</script>

测试:

浏览器输入: http://localhost:8080/#/pay

页面显示“支付成功,三秒后自动跳转到首页”,过三秒,页面跳转到首页。

命名路由

有时候,通过一个名称来标识一个路由显得更方便一些,特别是在链接一个路由,或者是执行一些跳转的时候。你可以在创建 Router 实例的时候,在 routes 配置中给某个路由设置名称。

需求:给首页路由起一个名字,新建一个组件(NamedRouter),组件中可以通过命名路由,使用链接(<router-link></router-link>)或方法跳转到首页

// views/NamedRouter.vue
<template>
<div>
<p>
<!-- 通过命名路由跳转 -->
<router-link :to="{ name: 'home-page' }">链接跳转</router-link>
</p>
<p>
<button @click="handleClick">编程式跳转</button>
</p>
</div>
</template> <script>
export default {
methods: {
handleClick: function(){
this.$router.push({ name: 'home-page'})
}
}
}
</script>

index.js:

// 新增
import NamedRouter from '../views/NamedRouter' const routes = [
// 修改
{
path: '/',
// 命名路由
name: 'home-page',
component: Home
},
// 新增
// 浏览器输入:http://localhost:8080/namedRouter
{
path: '/namedRouter',
component: NamedRouter
},
]

自行测试即可

命名视图

有时候想同时 (同级) 展示多个视图,而不是嵌套展示,例如创建一个布局,有 sidebar (侧导航) 和 main (主内容) 两个视图,这个时候命名视图就派上用场了。你可以在界面中拥有多个单独命名的视图,而不是只有一个单独的出口。如果 router-view 没有设置名字,那么默认为 default。

用法1-命名视图

直接上代码:

// src/App.vue
<template>
<div id="app">
<!-- 定义两个视图(sidebar 和 main) -->
<router-view class="sidebar" name='sidebar'></router-view>
<router-view class="main" name="main"></router-view>
</div>
</template>
// views/TestMain.vue
<template>
<p>我是 TestMain</p>
</template>
// views/TestSidebar.vue
<template>
<p>我是 TestSidebar</p>
</template>
// router/index.js
// 新增
import TestSidebar from '../views/TestSidebar'
import TestMain from '../views/TestMain' const routes = [
// 修改
{
path: '/',
components: {
main: TestMain,
sidebar: TestSidebar
},
name: 'home-page'
},
...
]

测试:

浏览器访问:http://localhost:8080/

页面显示:
我是 TestSidebar 我是 TestMain

用法2-嵌套命名视图

需求:某组件有两个视图,组件A,组件B分别放在这两个视图中

直接上代码:

// App.vue
<template>
<div id="app">
<router-view />
</div>
</template>
// views/TestHome.vue
<template>
<div class="test-home">
<!-- 定义两个视图(sidebar 和 main) -->
<router-view class="sidebar" name="sidebar"></router-view>
<router-view class="main" name="main"></router-view>
</div>
</template>
// router/index.js
// 新增
import TestSidebar from '../views/TestSidebar'
import TestMain from '../views/TestMain'
import TestHome from '../views/TestHome' const routes = [
// 新增
{
path: '/',
component: TestHome,
children: [
{
// path 为空,则能匹配 /
// 如果 path 不为空(xx1),则只能匹配 /xx1
path: '',
components: {
main: TestMain,
sidebar: TestSidebar
} }
],
// 命名路由
name: 'home-page'
},
...
]

TestMain.vue 和 TestSidebar.vue 不变。

自行测试即可。

重定向和别名

重定向

需求:访问支付(/pay),重定向到主页(/)。

const routes = [
{
path: '/pay',
redirect: '/'
}
]

测试:

输入:http://localhost:8080/#/pay
变成:http://localhost:8080/#/

别名

“重定向”的意思是,当用户访问 /a 时,URL 将会被替换成 /b,然后匹配路由为 /b,那么“别名”又是什么呢?

/a 的别名是 /b,意味着,当用户访问 /b 时,URL 会保持为 /b,但是路由匹配则为 /a,就像用户访问 /a 一样。

“别名”的功能让你可以自由地将 UI 结构映射到任意的 URL,而不是受限于配置的嵌套路由结构。

需求:新增组件(Apple),里面有个子组件(AppleComponentA),给子组件的路由起一个别名,方便访问。

// views/Apple.vue
<template>
<div>
<p>苹果</p>
<router-view></router-view>
</div>
</template>
// views/AppleComponentA.vue
<template>
<p>我是嘎嘎果</p>
</template>
// router/index.js
// 新增
import Apple from '../views/Apple'
import AppleComponentA from '../views/AppleComponentA' const routes = [
// 新增
{
path: '/apple',
component: Apple,
children: [
{
path: 'ca/x1/x2',
// 别名
alias: '/cxx',
component: AppleComponentA
}
]
}
]

运行:

浏览器输入:
http://localhost:8080/apple/ca/x1/x2

http://localhost:8080/cxx 页面输出:
苹果 我是嘎嘎果

路由组件传参

在组件中使用 $route 会使之与其对应路由形成高度耦合,从而使组件只能在某些特定的 URL 上使用,限制了其灵活性。

使用 props 将组件和路由解耦

需求:定义一个组件,通过 props 接收路由参数

// views/RouterToParams.vue
<template>
<p>路由传参 id={{ id }}</p>
</template>
<script> export default {
props:['id']
}
</script>
// router/index.js
// 新增
import RouterToParams from '../views/RouterToParams' const routes = [
// 新增
{
path: '/routerToParams/:id',
component: RouterToParams,
props: true
},
]

运行:

浏览器输入: http://localhost:8080/routerToParams/2

页面输出:
路由传参 id=2

对象模式

如果 props 是一个对象,它会被按原样设置为组件属性。当 props 是静态的时候有用。

改为对象模式,直接上代码:

// router/index.js
const routes = [
{
path: '/routerToParams/:id',
component: RouterToParams,
// props: true
props: { id2: 10 }
},
]
// views/RouterToParams.vue
<template>
<div>
<p>路由传参 id={{ id }}</p>
<p>路由传参 id2={{ id2 }}</p>
</div>
</template>
<script> export default {
props:['id2', 'id']
}
</script>

测试:

浏览器输入:http://localhost:8080/routerToParams/2
页面输出:
路由传参 id= 路由传参 id2=10

函数模式

你可以创建一个函数返回 props。这样你便可以将参数转换成另一种类型,将静态值与基于路由的值结合等等。

改为函数模式,直接上代码:

// router/index.js
const routes = [
{
path: '/routerToParams/:id',
component: RouterToParams,
props: route => ({ id3: route.params.id })
},
]
// views/RouterToParams.vue
<template>
<div>
<p>路由传参 id3={{ id3 }}</p>
</div>
</template>
<script> export default {
props:['id3']
}
</script>

测试:

浏览器输入:http://localhost:8080/#/routerToParams/2

页面显示:
路由传参 id3=2

HTML5 History 模式

vue-router 默认 hash 模式,如果不想要很丑的 hash,我们可以用路由的 history 模式。

改为 history 模式:

// router/index.js
const router = new VueRouter({
mode: 'history',
routes
})

Tip:history 模式还需要一些配置

导航守卫

“导航”表示路由正在发生改变。

正如其名,vue-router 提供的导航守卫主要用来通过跳转或取消的方式守卫导航。有多种机会植入路由导航过程中:全局的, 单个路由独享的, 或者组件级的。

参数或查询的改变并不会触发进入/离开的导航守卫。你可以通过观察 $route 对象来应对这些变化,或使用 beforeRouteUpdate 的组件内守卫。

全局前置守卫

需求:使用 router.beforeEach 注册全局前置守卫,如果访问的是登录(/login)则进入注册页(/register)

// router/index.js
import Register from '../views/Register' const routes = [
{
path: '/register',
component: Register
}
] // 导航
router.beforeEach((to, from, next) => {
if (to.path === '/login') next({ path: '/register' })
// next: Function: 一定要调用该方法来 resolve 这个钩子
else next()
})

测试:

浏览器输入: http://localhost:8080/login 变为 http://localhost:8080/register

其他导航守卫请参考官网:

  • 全局后置守卫
  • 路由独享的守卫
  • 组件内的守卫
  • 全局解析守卫

完整的导航解析流程

  1. 导航被触发。
  2. 在失活的组件里调用 beforeRouteLeave 守卫。
  3. 调用全局的 beforeEach 守卫。
  4. 在重用的组件里调用 beforeRouteUpdate 守卫 (2.2+)。
  5. 在路由配置里调用 beforeEnter。
  6. 解析异步路由组件。
  7. 在被激活的组件里调用 beforeRouteEnter。
  8. 调用全局的 beforeResolve 守卫 (2.5+)。
  9. 导航被确认。
  10. 调用全局的 afterEach 钩子。
  11. 触发 DOM 更新。
  12. 调用 beforeRouteEnter 守卫中传给 next 的回调函数,创建好的组件实例会作为回调函数的参数传入。

路由元信息

Tip:直接根据官网例子来说一下

定义路由的时候可以配置 meta 字段:

const router = new VueRouter({
routes: [
{
path: '/foo',
component: Foo,
children: [
{
path: 'bar',
component: Bar,
// a meta field
meta: { requiresAuth: true }
}
]
}
]
})

那么如何访问这个 meta 字段呢?

首先,我们称呼 routes 配置中的每个路由对象为 路由记录。路由记录可以是嵌套的,因此,当一个路由匹配成功后,他可能匹配多个路由记录

例如,根据上面的路由配置,/foo/bar 这个 URL 将会匹配父路由记录以及子路由记录。

一个路由匹配到的所有路由记录会暴露为 $route 对象 (还有在导航守卫中的路由对象) 的 $route.matched 数组。因此,我们需要遍历 $route.matched 来检查路由记录中的 meta 字段。

下面例子展示在全局导航守卫中检查元字段:

router.beforeEach((to, from, next) => {
if (to.matched.some(record => record.meta.requiresAuth)) {
// this route requires auth, check if logged in
// if not, redirect to login page.
if (!auth.loggedIn()) {
next({
path: '/login',
query: { redirect: to.fullPath }
})
} else {
next()
}
} else {
next() // 确保一定要调用 next()
}
})

如果路由记录中的 meta.requiresAuth 为 true,则需要验证

元数据,用于描述数据的数据。

过渡动效

<router-view> 是基本的动态组件,所以我们可以用 <transition> 组件给它添加一些过渡效果。

Transition 的所有功能(vue 官网中的“进入/离开 & 列表过渡”)在这里同样适用。

请看示意代码:

<template>
<div id="app">
<p>
<router-link to='/login'>登录</router-link> |
<router-link to='/'>首页</router-link>
</p>
<transition name="fade">
<router-view/>
</transition>
</div>
</template>
<style >
.fade-enter-active, .fade-leave-active {
transition: opacity .5s;
}
.fade-enter, .fade-leave-to /* .fade-leave-active below version 2.1.8 */ {
opacity: 0;
}
</style>

点击登录首页就能看到动画。

Tip:上面的用法会给所有路由设置一样的过渡效果,还有单个路由的过渡,以及基于路由的动态过渡。

数据获取

有时候,进入某个路由后,需要从服务器获取数据。例如,在渲染用户信息时,你需要从服务器获取用户的数据。我们可以通过两种方式来实现:

  • 导航完成之后获取:先完成导航,然后在接下来的组件生命周期钩子中获取数据。在数据获取期间显示“加载中”之类的指示。

  • 导航完成之前获取:导航完成前,在路由进入的守卫中获取数据,在数据获取成功后执行导航。

从技术角度讲,两种方式都不错 —— 就看你想要的用户体验是哪种。

Tip:更具体的信息可以参考官网

滚动行为

使用前端路由,当切换到新路由时,想要页面滚到顶部,或者是保持原先的滚动位置,就像重新加载页面那样。 vue-router 能做到,而且更好,它让你可以自定义路由切换时页面如何滚动。

: 这个功能只在支持 history.pushState 的浏览器中可用。

当创建一个 Router 实例,你可以提供一个 scrollBehavior 方法:

const router = new VueRouter({
routes: [...],
scrollBehavior (to, from, savedPosition) {
// return 期望滚动到哪个的位置
}
})

Tip:更具体的信息可以参考官网

其他章节请看:

vue 快速入门 系列

vue 快速入门 系列 —— vue-router的更多相关文章

  1. vue 快速入门 系列 —— vue loader 扩展

    其他章节请看: vue 快速入门 系列 vue loader 扩展 在vue loader一文中,我们学会了从零搭建一个简单的,用于单文件组件开发的脚手架.本篇将在此基础上继续引入一些常用的库:vue ...

  2. vue 快速入门 系列 —— vue 的基础应用(上)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(上) Tip: vue 的基础应用分上下两篇,上篇是基础,下篇是应用. 在初步认识 vue一文中,我们已经写了一个 vue 的 hello- ...

  3. vue 快速入门 系列 —— vue 的基础应用(下)

    其他章节请看: vue 快速入门 系列 vue 的基础应用(下) 上篇聚焦于基础知识的介绍:本篇聚焦于基础知识的应用. 递归组件 组件是可以在它们自己的模板中调用自身的.不过它们只能通过 name 选 ...

  4. vue 快速入门 系列 —— vue loader 上

    其他章节请看: vue 快速入门 系列 vue loader 上 通过前面"webpack 系列"的学习,我们知道如何用 webpack 实现一个不成熟的脚手架,比如提供开发环境和 ...

  5. vue 快速入门 系列 —— vue loader 下

    其他章节请看: vue 快速入门 系列 vue loader 下 CSS Modules CSS Modules 是一个流行的,用于模块化和组合 CSS 的系统.vue-loader 提供了与 CSS ...

  6. vue 快速入门 系列 —— Vue(自身) 项目结构

    其他章节请看: vue 快速入门 系列 Vue(自身) 项目结构 前面我们已经陆续研究了 vue 的核心原理:数据侦测.模板和虚拟 DOM,都是偏底层的.本篇将和大家一起来看一下 vue 自身这个项目 ...

  7. vue 快速入门 系列 —— Vue 实例的初始化过程

    其他章节请看: vue 快速入门 系列 Vue 实例的初始化过程 书接上文,每次调用 new Vue() 都会执行 Vue.prototype._init() 方法.倘若你看过 jQuery 的源码, ...

  8. vue 快速入门 系列 —— vue-cli 上

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 上 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

  9. vue 快速入门 系列 —— vue-cli 下

    其他章节请看: vue 快速入门 系列 Vue CLI 4.x 下 在 vue loader 一文中我们已经学会从零搭建一个简单的,用于单文件组件开发的脚手架:本篇,我们将全面学习 vue-cli 这 ...

随机推荐

  1. servlet中servletContext的五大作用(五)

    1.    获取web的上下文路径 2.    获取全局的参数 3.    作为域对象使用 4.    请求转发 5.    读取web项目的资源文件 package day10.about_serv ...

  2. C# - 音乐小闹钟_BetaV1.0

    时间:2017-11-20 作者:byzqy 介绍: 前段时间看到别人利用Timer控件实现了检查电脑本地时间,然后对时间进行比较,最终实现闹钟功能.感觉有点意思,于是自己也做了一个小闹钟! 先看一下 ...

  3. tensorflow1.12 queue 笔记

    主要参考:https://www.tensorflow.org/api_guides/python/threading_and_queues#Queue_usage_overview 自动方式 For ...

  4. idea控制台中文乱码解决办法

    也可以通过idea右下角的设置,但是properties文件是不能设置的,这个只能在file->setting->file encodings 设置

  5. 源码解析.Net中Middleware的实现

    前言 本篇继续之前的思路,不注重用法,如果还不知道有哪些用法的小伙伴,可以点击这里,微软文档说的很详细,在阅读本篇文章前,还是希望你对中间件有大致的了解,这样你读起来可能更加能够意会到意思.废话不多说 ...

  6. Ajax技术---核心XMLHttpRequest对象

    Ajax 的全称是Asynchronous JavaScript and XML,其中,Asynchronous 是异步的意思,它有别于传统web开发中采用的同步的方式. (一)ajax技术的意义 我 ...

  7. 一、Rabbitmq的简单介绍

    以下只是本人从零学习过程的整理 部分内容参考地址:https://www.cnblogs.com/ysocean/p/9240877.html 1.RabbitMQ的概念 RabbitMQ是实现了高级 ...

  8. 这款打怪升级的小游戏,7 年前出生于 GitHub 社区,如今在谷歌商店有 8 万人打了满分

    今天我在 GitHub 摸鱼寻找新的"目标"时,发现了一个开源项目是 RougeLike 类的角色扮演游戏「破碎版像素地牢」(Shattered Pixel Dungeon)类似魔 ...

  9. angularjs $http.get 和 $http.post 传递参数

    $http.get请求数据的格式 $http.get(URL,{ params: { "id":id } }) .success(function(response, status ...

  10. 255 day03_List、Set、数据结构、Collections

    day03 [List.Set.数据结构.Collections] 主要内容 数据结构 List集合 Set集合 Collections 教学目标 [ ] 能够说出List集合特点 [ ] 能够说出常 ...