Vue SSR 渲染 Nuxt3 入门学习

SPA应用:也就是单页应用,这些多是在客户端的应用,不利于进行SEO优化(搜索引擎优化)。

SSR应用:在服务端进行渲染,渲染完成后返回给客户端,每个页面有独立的URL,对SEO友好。

Nuxt3是基于Vue3发布的SSR框架

nuxt3 特性:

  • 更轻量:以现代浏览器为基础的情况下,服务器部署和客户端产物最多减小75倍。
  • 更快:用动态服务端代码来优化冷启动。
  • Hybird:增量动态生成和其他高级模式现在都成为可能。
  • Suspense: 导航前后可在任何组件中获取数据。
  • Composition API : 使用Composition API 和 Nuxt3的composables 实现真正的可复用性。
  • Nuxt CLI : 权限的零依赖体验,助你轻松搭建项目和集成模块。
  • Nuxt Devtools :专属调试工具,更多的信息和快速修复,在浏览器中高效工作。
  • Nuxt Kit :全新的基于 TypeScript 和跨版本兼容的模块开发。
  • Webpack5 : 更快的构建速度和更小的构建包,并且零配置。
  • Vite:用Vite作为你的打包器,体验轻量级的快速HMR。
  • Vue3 : 完全支持Vue3语法,这一点特别关键。
  • TypeScript:由原生TypeScript和ESM构成,没有额外配置步骤。

开始动手

//  1, 构建第一个项目, 多使几次,容易网络问题构建不成功
npx nuxi init nuxt-app
//  2. cd 进入 nuxt-app 安装依赖包使用 npm 或者 yarn
npm i  /  yarn
// 3, 启动 nuxt.js
npm run dev


项目跑起来后点击链接打开展示出这个 nuxt 页面,项目就跑起来了

nuxt 的目录结构

- .nuxt               // 自动生成的目录,用于展示结果
- node_modules        // 项目依赖包存放目录
- .gitignore          // Git的配置目录,比如一些文件不用Git管理就可以在这个文件中配置
- app.vue             // 项目入口文件,你可以在这里配置路由的出口
- nuxt.config.ts      // nuxt项目的配置文件 ,这个里边可以配置Nuxt项目的方法面面
- package-lock.json   // 锁定安装时包的版本,以保证其他人在 npm install时和你保持一致
- package.json        // 包的配置文件和项目的启动调式命令配置
- README.md           // 项目的说明文件
- tsconfig.json       // TypeScript的配置文件

随着我们的开发目录也会越来越多,比如常用的还有下面三个目录。

- pages               // 开发的页面目录
- components          // 组件目录
- assets              // 静态资源目录
- layouts             // 项目布局目录

接下来写个 HelloWorld 网页
在根目录下创建一个 components 文件夹用来存放组件
1, 在 components 文件下新建 HelloWorld.vue 组件

// HelloWorld.vue
<template><h1>HelloWorld</h1>
</template>

2, 在 app.vue 中使用组件,没错! 不用引入! 可以直接使用

// app.vue<template><hello-world></hello-world>
</template>

3, 页面效果

约定路由

如何在 Nuxt 中展示页面还有路由?
1.首先先在根目录新建一个 pages 文件夹,里面创建一个 Index.vue 和 About.vue

<!--Index.vue  --><!--About.vue同理  --><template><div><h1>Index.vue</h1><!-- 使用NuxtLink 来跳转到其他的路由 --><!-- 文件名叫About.vue对应的路由就是 /About--><NuxtLink to="/About">About.vue</NuxtLink></div>
</template><script setup>
import {} from "vue";
</script><style scoped></style>

2.在 app.vue 中添加 NuxtPage 路由组件

<template><div><hello-world></hello-world><!-- 路由组件 --><NuxtPage></NuxtPage></div>
</template>

页面输入 /Index 就能展示出页面了


Nuxt 框架不鼓励我们使用 a 标签来跳转路由,推荐使用 NuxtLink 来跳转,比如在 index 页跳转到 about 页

<!-- index.vue -->
<template><div><h1>Index.vue</h1><!-- 使用NuxtLink 来跳转到其他的路由 --><!-- 文件名叫About.vue对应的路由就是 /About--><NuxtLink to="/About">About.vue</NuxtLink></div>
</template>

nuxt 动态路由的写法

nuxt 里面的动态路由需要创建 文件名[路由参数] 这种格式的vue文件,例如 list-[id].vue

<!-- list-[id].vue-->
<template><div><!--渲染到页面上-->{{$route.params.id}}</div>
</template>

在index.vue里面写入需要跳转的路由

<!-- index.vue-->
<template><div><div>index.vue</div><NuxtLink to="/about">跳转关于</NuxtLink><!--跳转到动态路由--><NuxtLink to="/list-4">跳转列表页</NuxtLink></div>
</template><script setup>
import {} from "vue";
</script><style scoped></style>

运行项目,已经获取到 id 了

那我们需要两个或者多个动态参数怎么办?
在根目录下新建一个文件夹,格式跟创建动态路由网页一样, 文件夹名[动态参数],例如 goods-[name]

在 index.vue 写入跳转链接, list-[id].vue 里面获取name参数

<!-- index.vue-->
<template><div><div>index.vue</div><NuxtLink to="/about">跳转关于</NuxtLink><!--跳转到动态路由--><NuxtLink to="/goods-phone/list-4">跳转列表页</NuxtLink></div>
</template>
<!-- list-[id].vue-->
<template><div><!--渲染到页面上-->{{$route.params.id}}{{$route.params.name}}</div>
</template>

就可以拿到 name 参数跟 id 参数了

nuxt 嵌套路由的写法

跟动态路由类似,在根目录创建一个与父页面同名的文件夹,比如父页面是 parent.vue, 那就在根目录创建一个 parent 文件夹

在 parent.vue 父页面里面加入 NuxtChild 组件,即可在父页面里面动态展现子页面

<template><div><div class="parent">我是parent.vue 父页面</div><!-- 跳转路由 --><NuxtLink to="/parent/child">展示/parent/child页面</NuxtLink>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<NuxtLink to="/parent/son">展示/parent/son页面</NuxtLink><!-- 子页面的展示 --><NuxtChild></NuxtChild></div>
</template><script setup>
import {} from "vue";
</script><style scoped></style>

在 parent 文件夹里面新增子页面 child.vue 跟 son.vue 文件

<!-- child.vue -->
<template><div class="child">这里是child.vue页面</div>
</template><script setup>
import {} from "vue";
</script><style scoped></style>

运行起来就可以实现嵌套了

使用 layout 布局模板

nuxt3 提供了一种布局架构给我们,可以在整个应用中使用,可以用来放重复的常见的UI,代码模式,提高代码重用性,降低代码复杂度,把通用的代码提取出来,页面使用的时候会异步导入进来。

layout 的使用
在根目录创建一个 layouts 布局文件夹,然后在 layouts 文件夹下面创建一个 input.vue 模板


在 input.vue 中使用 slot 插槽

<template><div class="input"><!-- icon图标 --><slot name="icon"></slot><input type="text" /><button><!-- 按钮字体 --><slot name="btn-text"></slot></button></div>
</template><script setup>
import {} from "vue";
</script><style scoped></style>

在根目录中创建一个 form.vue 页面, 并且使用 NuxtLayout 组件, name 对应的是 layout 文件里面模板的名字

<template><div><!-- 使用NuxtLayout组件, name对应模板的名字 --><NuxtLayout name="input"><template #icon><!-- icon图标 --><i>X</i></template><!-- 按钮文字 --><!-- 使用 template 加上 #插槽名字 --><template #btn-text>提交</template></NuxtLayout></div>
</template><script setup>
import {} from 'vue'
</script><style scoped></style>

运行项目,我们已经传入 x 图标跟动态传递文字了

nuxt 组件的使用

在根目录中创建 components 文件夹, 把要复用的组件编写在里面,在components中创建 footer.vue

<!-- footer.vue-->
<template><div class="footer"><div>copy right 2022 zheng_jia_jun</div></div>
</template><script setup>
import {} from "vue";
</script><style scoped></style>

创建好后直接在需要使用该组件的页面里面使用即可,推荐大写组件

<template><div><h1>Index.vue</h1><!-- 跳转导航 --><NuxtLink to="/About">About.vue</NuxtLink><!--底部组件--><Footer></Footer></div>
</template><script setup>
import {} from "vue";
</script><style scoped></style>

页面上即可使用, layouts 里面的布局也是同理,就不做演示了

多层级组件的使用

我们在开发的时候组件肯定要用文件夹分类起来,不可能直接写在 components目录,需要将不同功能的组件分类在各自的文件夹中,看示例
这个时候在页面中导入就不是 icon 这样子的了,nuxt 规定 文件夹+加上文件名字 导入

<template><div><h1>Index.vue</h1><!-- 跳转导航 --><NuxtLink to="/About">About.vue</NuxtLink><Footer></Footer><!-- 使用嵌套组件 --><NavIcon></NavIcon></div>
</template><script setup>
</script><style scoped></style>

组件懒加载

在组件的前面加上 Lazy前缀即可使用懒加载,懒加载组件的目的是在项目打包的时候包更小。简单理解可以理解为只有在组件显示在页面上时才进行加载。 比如我们需要点击按钮显示或者隐藏某个组件

<!-- index.vue -->
<template><div><h1>Index.vue</h1><!-- 跳转导航 --><NuxtLink to="/About">About.vue</NuxtLink><Footer></Footer><!-- 使用嵌套组件 --><NavIcon></NavIcon><!-- 使用懒加载的组件 --><LazyNavIcon v-show="isShow"></LazyNavIcon><button @click="isShow = !isShow">切换显示隐藏</button></div>
</template><script setup>
import {ref} from "vue";
// 默认不显示
const isShow = ref(false)
</script><style scoped></style>

nuxt 中使用复用型逻辑代码,composables 文件夹的使用

开发中我们经常重复使用一些逻辑代码,会把他们封装在一个utils 文件夹下,Nuxt 也提供了一个 composables 文件夹,在此文件夹下创建的一级目录文件会将里面的方法自动导入到全局应用,就是在每个页面里面都可以使用到这个代码。

// time.ts
// export 的话使用时用的是对应导出的名字 getTime
// export default 默认导出的话用的是 time.ts 这个文件的名字 time
export function getTime(){let time = new Date()return time.toUTCString()
}

然后在每个页面中即可使用这些方法,这个方法写太多的话影响性能,因为每个方法都会导入到全局

<!-- index.vue -->
<template><div><h1>Index.vue</h1><!-- 在代码中使用 composables 的逻辑代码 --><div>{{getTime()}}</div></div>
</template><script setup>
// 使用componables 通用逻辑代码
console.log(getTime())
// 实现搜索功能
inputSearch()
</script><style scoped></style>

在 Nuxt 中 服务端获取请求数据

因为Nuxt3是SSR的方案,所以你可能不仅仅只是想要在浏览器端发送请求获取数据,还想在服务器端就获取到数据并渲染组件。

Nuxt3 提供了4种方式使得你可以在服务器端异步获取数据,他们只能在生命周期函数里面使用

  • useAsyncData
  • useFetch
  • useLazyAsyncData
  • useLazyFetch

后面两个 Lazy 只是在前面两个的配置上配置了 { lazy: true }, 其他的功能都跟默认一样

<!-- http.vue -->
<template><div>http.vue</div>
</template><script setup>
import {} from "vue";
// api
let url = "https://interface.meiriyiwen.com/article/today?dev=1";
// 官方推荐使用 await 来解决异步问题
let res = await useAsyncData("getList",() => {return $fetch(url);},{lazy: true,}
);
console.log(res);// 使用 useFetch 请求
useFetch(url, {method: "get",id: 1,
}).then((res) => {console.log("useFetch:",res);
});
</script><style scoped>
</style>

返回的参数格式

// useFetch 的返回对象同理
const {data: Ref<DataT>,// 返回的数据结果pending: Ref<boolean>,// 是否在请求状态中refresh: (force?: boolean) => Promise<void>,// 强制刷新数据error?: any // 请求失败返回的错误信息
} = useAsyncData(key: string, // 唯一键,确保相同的请求数据的获取和去重fn: () => Object,// 一个返回数值的异步函数options?: { lazy: boolean, server: boolean }// options.lazy,是否在加载路由后才请求该异步方法,默认为false// options.server,是否在服务端请求数据,默认为true// options.default,异步请求前设置数据data默认值的工厂函数(对lazy:true选项特别有用)// options.transform,更改fn返回结果的函数// options.pick,只从数组中指定的key进行缓存
)

Nuxt 中使用全局或者局部中间件

在根目录下创建 middleware 文件夹, 并且在里面创建中间件, 如果文件加上 .global 后缀的话,就是全局的中间件,不加的话就是自定义在哪些页面的中间件


定义好 default.global.ts 全局中间件就已经可以使用了

// default.global.ts
// 一个简单的路由守卫
export default function defineNuxtRouterMiddleware(to, from) {console.log("要去往的路径:" + to.path)console.log("我来的路径:" + from.path)if (to.path == '/About') {// 停止导航abortNavigation()console.log('暂无权限跳转到/about')return navigateTo('/Index')}
}
// listen.ts 自定义页面使用
export default function defineListenMiddleware(to, from) {console.log("监听用户操作")
}

自定义在指定的页面使用中间件,需要使用 MiddlePageMeta配置

<template><div>middleware.vue</div>
</template><script setup>
import {ref} from "vue";definePageMeta({// 专属这个页面的监听器middleware: ["listen"],
});
</script><style scoped></style>

nuxt 中使用 useState 创建状态

Nuxt 提供可组合的 useState 来创建跨组件的并且对 SSR 友好的响应式状态。
useState 是对 ssr 友好的共享状态替代品,它的值将会在服务端渲染后保留,并且使用唯一的键在各个组件中共享。

useState 只允许在 setup生命周期函数里面使用

useState参数

  • key :唯一的键确保数据请求能够正确并且不被重复
  • init :给 state 初始化时候的一个默认值
  • T :(仅用作于 typescript )描述 state 的类型
useState<T>(key: string, init?: () => T): Ref<T>

示例

<script setup>
// 创建对ssr友好的响应式状态
const counter = useState("counter", () => Math.round(Math.random() * 1000));
</script><template><div>Counter: {{ counter }} Name: {{ name }}<button @click="counter++">+</button><button @click="counter--">-</button></div>
</template>

使用 useState 创建共享状态

如果我们要使用共享状态,可以利用 componsables 文件夹,在这个文件夹里面创建一个 states.ts, 然后定义不同的共享状态分别导出

// /componsables/states.ts
// 全局共享状态
export const useInfo = () => useState("info",() => {return {id: 1,name: '用户1'}
})
// 用户的 token
export const useToken = () => useState("token",()=> "tokenXXXXXXXXXXXXXXX")

在页面中使用

<!-- state.vue -->
<script setup>
// 使用共享状态
const info = useInfo();
const token = useToken();
</script><template><div><div class="user-info"><p>{{ info.id }}{{ info.name }}</p><p>token: {{ token }}</p></div></div>
</template>

页面中已经可以访问到共享状态了

运行时获取配置 RuntimeConfig

Nuxt 提供了一个 API,用于在应用程序和 API 路由中定义运行时配置。为了向应用程序公开配置跟环境变量,我们需要把配置定义在 nuxt.config.ts 里面,配置分为 公开跟私有配置,可以使用,publicRuntimeConfig 或者 privateRuntimeConfig 选项(根据用户是否能访问这些部分配置来使用)

// nuxt.config.ts
import { defineNuxtConfig } from 'nuxt'// https://v3.nuxtjs.org/api/configuration/nuxt.config
// 定义 config
export default defineNuxtConfig({// 公开的配置publicRuntimeConfig: {Base_Url: 'https://zhengjiajun.com:55'},// 传递给服务端的,不公开的,返回服务端会把 public 跟 private 两个对象合并上传,private会覆盖publicprivateRuntimeConfig: {Base_Url: 'https://zhengjiajun.com:66'}
})


服务端获取到的是 66 端口,privateRuntimeConfig 会覆盖 publicRuntimeConfig

访问存放的 RuntimeConfig
在 Nuxt 应用程序的 Vue 实例中,需要调用 useRuntimeConfig() 来访问运行时配置。

<!-- config.vue -->
<template><div>configUrl: {{config.Base_Url}}</div>
</template><script setup>
import {ref} from 'vue'
// 获取config
const config = useRuntimeConfig()
console.log(config.Base_Url)
</script><style scoped></style>

在路由api中使用 nuxt.config

// /server/api/hello.ts
export default (req, res) => {// 使用 useRuntimeConfigreturn `hello-${useRuntimeConfig().Base_Url}`
}

nuxt 获取 NuxtApp 上下文

在组合函数、组件以及插件中通过 useNuxtApp 访问 nuxtApp 实例。

<template><div><div>nuxtapp</div><NuxtLink to="/Index">/index</NuxtLink></div>
</template><script setup>
// 导入 useNuxtApp
import { useNuxtApp } from "#app";
// 获取 nuxtapp 上下文
const NuxtApp = useNuxtApp();
// 类似于注入
NuxtApp.provide("jun", ()=>"注入");
// 通过NuxtAPP."$名字" 即可在应用中访问
console.log(NuxtApp.$jun);
</script><style scoped></style>

运行项目

nuxt 中使用 useCookie

<template><div>cookie.vue</div>
</template><script setup>
import {} from "vue";
// 添加一个 cookie
const userId = useCookie("userId", {// 设置默认值default: () => "123456",// 10秒后过期// 单位秒。默认不设置最大超时时间。maxAge: 10,// 默认不设置该值。 大部分客户端将它视为“持久化的cookie”expires: new Date('2022-7-20'),// secure 只允许 https 链接传递 cookie,默认为falsesecure: false,// httpOnly 设置 是否允许客户端通过 js 获取到 cookie,默认为falsehttpOnly: false,// 允许访问该 cookie 的域名 不设置默认是当前浏览器域名domain: "localhost",//    Cookie的使用路径。如果设置为“/sessionWeb/”,// 则只有contextPath为“/sessionWeb”的程序可以访问该Cookie。// 如果设置为“/”,则本域名下contextPath都可以访问该Cookie。注意最后一个字符必须为“/”。path: "/",
});
console.log(userId);
// 判断浏览器cookie是否已经有 userId
userId.value = userId.value || Math.round(Math.random() * 1000);
</script><style scoped></style>

nuxt 中 路由 api 使用 cookie
通过 h3 包中的 useCookie 跟 setCookie 在服务器 API 路由中访问跟设置 cookie

// server/api/cookie.ts
import { useCookie, setCookie } from "h3"export default defineEventHandler(event => {// 查看有没有这个 cookielet counter = useCookie(event, 'counter') || 0// 设置 cookie + 1setCookie(event, 'counter', ++counter)// 返回 json 格式return { counter }
})

在 localhost:3000/api/cookie 即可看到效果

Nuxt3 中创建使用插件

Nuxt 将自动读取"plugins"目录中的文件并加载它们。如果仅想在服务器端或客户端加载插件时,可以在文件名中使用.server或.client后缀。
plugins 目录跟 componables 目录一样,只渲染一级目录的插件,例如

plugins| - myPlugin.ts| - myOtherPlugin| --- supportingFile.ts| --- componentToRegister.vue| --- index.ts

只注册 myPlugin.ts 和 myOtherPlugin/index.ts

创建插件 在根目录下创建 plugins ,新建 helps.ts

// 使用 defineNuxtPlugin 创建插件
import { defineNuxtPlugin } from "#app";
// nuxt3 规定只能给插件传递 nuxtApp 上下文参数,
// 可以对 nuxtApp 做您想要做的操作比如做一个加法函数
export default defineNuxtPlugin((nuxtApp) => {return {// 如果需要注入 nuxtApp,可以直接返回 provie 对象即可使用// 跟 nuxtApp.provide(add,() => (a,b) => a+b)  相同provide:  {add: (a,b) => a + b  }}
})

在页面中访问 nuxtApp 注入的 add 函数

<template><div>1 + 2 = {{useNuxtApp().$add(1,2)}}</div>
</template><script setup>
import {} from 'vue'
</script><style scoped></style>

效果已经出来了

nuxt3 中 使用 路由 api 接口

Nuxt 将自动读取~/server/api目录中的任何文件,以创建 API 端点。
每个文件都应导出一个处理 API 请求的默认函数。它可以直接返回承诺或 JSON 数据(或使用 )。
在 根目录下创建 server/api/getList.ts

// 每个文件都应导出一个处理 API 请求的默认函数。它可以直接返回承诺或 JSON 数据
// server/api/getList.ts
export default async (req, res) => {let url = "https://interface.meiriyiwen.com/article/today?dev=1";// 获取异步数据let data ;await fetch(url, {method: 'get'}) .then(response => response.json()).then(res => data = res);// 返回数据return {data}
}

访问 http://localhost:3000/api/getList 即可看到返回数据

Vue SSR 渲染 Nuxt3 入门学习相关推荐

  1. Nuxt.js开启SSR渲染快速入门

    Nuxt.js开启SSR渲染快速入门 第一节:nuxt.js相关概述 nuxt.js简单的说是Vue.js的通用框架,最常用的就是用来作SSR(服务器端渲染).Vue.js是开发SPA(单页应用)的, ...

  2. 新手入门指导:Vue 2.0 的建议学习顺序

    起步 1. 扎实的 JavaScript / HTML / CSS 基本功.这是前置条件. 2. 通读官方教程 (guide) 的基础篇.不要用任何构建工具,就只用最简单的 <script> ...

  3. 【服务端渲染】之 Vue SSR

    前言 笔记来源:拉勾教育 大前端高薪训练营 阅读建议:内容较多,建议通过左侧导航栏进行阅读 Vue SSR 基本介绍 Vue SSR 是什么 官方文档:https://ssr.vuejs.org/ V ...

  4. vue入门学习(基础篇)

    vue入门学习总结: vue的一个组件包括三部分:template.style.script. vue的数据在data中定义使用. 数据渲染指令:v-text.v-html.{{}}. 隐藏未编译的标 ...

  5. 从0带您打造企业级 Vue 服务器渲染 Nuxt.js (一) 入门

    写在开始前 公司团队技术栈一直主要使用 Vue,由于 SPA 模式开发有几大痛点,团队在2017年开始尝试 SSR(服务端渲染). 记得刚开始 Nuxt.js 还没有到1.0(坑哭了),到目前为止团队 ...

  6. 服务器端渲染-Vue SSR搭建

    阅读建议:建议通过左侧导航栏进行阅读 文章简介:本文是Vue.js服务器端渲染的另一种解决方案-SSR(Server-Side Rendering)学习笔记 Vue SSR是什么 官方文档解释:Vue ...

  7. Vue SSR 从入门到 Case Study

    最近两个项目同时开发,使用了Vue2的SSR,这样后端渲染页面首屏可以加快页面呈现,增加SEO和用户体验,但是项目上线后却发现了严重的性能问题,于是在三天内两次重大调整,最后只能放弃Vue SSR,本 ...

  8. Vue.js学习系列七——Vue服务器渲染Nuxt学习

    我又回来啦~这次我们来学习Vue的服务器渲染SSR. 关于SSR的文章网上很多,一开始看得我云里雾里.然后去Vue.js 服务器渲染指南和nuxt官网看了看,发现文章大多都是搬运官网的内容,真正讲的清 ...

  9. Day7:Vue入门学习——传智播客学习笔记【微服务电商】

    本节依旧是前端内容,但还是了解一下基础的入门知识 学习目标 会创建Vue实例,知道Vue的常见属性 会使用Vue的生命周期的钩子函数 会使用vue常见指令 会使用vue计算属性和watch监控 会编写 ...

最新文章

  1. [译]深入理解JVM
  2. python 链栈及基本操作
  3. java日期格式化代码的写法_Java中的`DateTimeFormatter`格式化代码中的`uuuu`与`yyyy`?...
  4. C# 使用 SqlBulkCopy 类批量复制数据到数据库
  5. haproxy配置代理tomcat和nginx_Nginx负载均衡配置实例
  6. 别再 select * 了,送你 12 个查询技巧!
  7. childNodes属性 和 nodeType属性
  8. linq where的应用
  9. python内置函数每个执行一次
  10. 2009年程序员考试大纲
  11. 微信小程序跳转微信公众号
  12. 10g gtx 光纤通信测试_光纤通信系统仿真实验
  13. 苏轼一生最智慧的20首诗词,不读懂不足以谈人生
  14. 12306订票候补是个坑_12306候补购票好几天了都没兑现成功是不是凉凉了?
  15. 最新ubuntu搭建公网个人邮件服务器(基于postfix,dovecot,mysql)
  16. C++如何输入/输出
  17. 微信公众平台订阅号和服务号的区别详解
  18. 通读cheerio API
  19. 会计 复式记账 财务会计 系统设计 数据库建模(待翻译)
  20. 华为手机honor5c root 方法备份

热门文章

  1. Android实现豆瓣FM的首页效果
  2. 跟益达学Solr5之使用IK分词器
  3. 利用mysql的几种提权方式
  4. 1075 习题5-3-4 求最小公倍数
  5. 排队论(Queuing theory)简介
  6. java编程的英文_Java编程基础常见英语词汇总编
  7. CSS实现水平局中、垂直局中详解
  8. js中如何求平面两点之间的距离
  9. 新思创OA办公自动化解决方案
  10. 全球KYC服务商ADVANCE.AI顺利加入深跨协 推动跨境电商行业有序发展