NUXT.js

Nuxt.js 是一个基于 Vue.js 的通用应用框架。 通过对客户端/服务端基础架构的抽象组织,##Nuxt.js 主要关注的是应用的 UI渲染。

  • nuxt不仅仅用于服务端渲染也可用于spa应用开发;
  • 利用nuxt提供的基础项目结构、路由生成、中间件、插件等特性可大幅提高开发效率
  • nuxt可用于网站静态化
    Nuxt.js官方文档
    https://zh.nuxtjs.org/guide
    nuxt安装
    运行 create-nuxt-app
  • npx create-nuxt-app <项目名>
    

    components:组件目录 components 用于组织应用的 Vue.js 组件。Nuxt.js 不会扩展增强该目 录下 Vue.js 组件,即这些组件不会像⻚面组件那样有 asyncData 方法的特性。

    layouts:布局目录 layouts 用于组织应用的布局组件。 middleware:中间件目录用于存放应用的中间件。

    pages:⻚面目录 pages 用于组织应用的路由及视图。Nuxt.js 框架读取该目录下所有的 .vue 文件并自动生成对应的路由配置。

    plugins:插件目录 plugins 用于组织那些需要在 根vue.js应用 实例化之前需要运行的 Javascript 插件。

    static:静态文件目录 static 用于存放应用的静态文件,此类文件不会被 Nuxt.js 调用 Webpack 进行构建编译处理。 服务器启动的时候,该目录下的文件会映射至应用的根路径 / 下。

    store:用于组织应用的 Vuex 状态树文件。 Nuxt.js 框架集成了 Vuex 状态树 的相关功能配置, 在 store 目录下创建一个 index.js 文件可激活这些配置。 nuxt.config.js:该文件用于个性化配置Nuxt应用。

    pages目录中所有 *.vue 文件自动生成应用的路由配置,新建:
    pages/admin.vue 商品管理⻚ pages/login.vue 登录⻚
    添加路由导航,layouts/default.vue

    <nuxt-link to="/">首⻚</nuxt-link> <!--别名:n-link,NLink,NuxtLink--> <NLink to="/admin">管理</NLink> <n-link to="/cart">购物⻋</n-link>

    商品列表,index.vue

      <template>
    <h2>商品列表</h2> <ul>
          <li v-for="good in goods" :key="good.id" >
            <nuxt-link :to="`/detail/${good.id}`">
              <span>{{good.text}}</span>
    <span>¥{{good.price}}</span> </nuxt-link>
    </li> </ul>
    </template>
    <script>
    export default {
      data() {
    return { goods: [
    {id:1, text:'Web',price:8999}, {id:2, text:'Python',price:8999},
    </script>
    

    以下划线作为前缀的 .vue文件 或 目录会被定义为动态路由,如下面文件结构

    pages/
    --| detail/
    ----| _id.vue
    

    会生成如下路由配置:

    pages/
    --| detail/
    ----| _id.vue
        path: "/detail/:id?",
        component: _9c9d895e,
        name: "detail-id"
    

    如果detail/里面不存在index.vue,:id将被作为可选参数

    创建内嵌子路由,你需要添加一个 .vue 文件,同时添加一个与该文件同名的目录用来存放子视图组 件。
    构造文件结构如下:

    pages/
    --| detail/
    ----| _id.vue
    --| detail.vue
    

    生成的路由配置如下:

    path: '/detail', component: 'pages/detail.vue', children: [ {path: ':id?', name: "detail-id"}

    测试代码,detail.vue

    <template> <h2>detail</h2> <nuxt-child></nuxt-child> </template>

    要扩展 Nuxt.js 创建的路由,可以通过 router.extendRoutes 选项配置。例如添加自定义路由:

    // nuxt.config.js export default { router: { extendRoutes (routes, resolve) { routes.push({ name: "foo", path: "/foo", component: resolve(__dirname, "pages/custom.vue") }); }

    下图展示了Nuxt.js 如何为指定的路由配置数据和视图

    <template>
      <div class="container">
    <h1 v-if="error.statusCode === 404">⻚面不存在</h1> <h1 v-else>应用发生错误异常</h1>
    <p>{{error}}</p>
    <nuxt-link to="/">首 ⻚</nuxt-link>
    </template>
    <script>
    export default {
      props: ['error'],
      layout:'blank'
    </script>
    

    ⻚面组件就是 Vue 组件,只不过 Nuxt.js 为这些组件添加了一些特殊的配置项 给首⻚添加标题和meta等,index.vue

    export default {
     head() {
    return {
    title: "课程列表",
    // vue-meta利用hid确定要更新meta
    meta: [{ name: "description", hid: "description", content: "set page
    meta" }],
         link: [{ rel: "favicon", href: "favicon.ico" }],
    }; },
    export default {
      async asyncData({ $axios, error }) {
          const {ok, goods} = await $axios.$get("/api/goods");
          if (ok) {
              return { goods };
    // 错误处理
    error({ statusCode: 400, message: "数据查询失败" }); },
    </script>
    

    测试代码:获取商品详情,/index/_id.vue

    <template>
       <pre v-if="goodInfo">{{goodInfo}}</pre>
    </template>
    <script>
    export default {
     async asyncData({ $axios, params, error }) {
    if (params.id) {
    // asyncData中不能使用this获取组件实例
    // 但是可以通过上下文获取相关数据
    const { data: goodInfo } = await $axios.$get("/api/detail", { params });
         if (goodInfo) {
           return { goodInfo };
    error({ statusCode: 400, message: "商品详情查询失败" }); } else {
         return { goodInfo: null };
    </script>
    中间件会在一个⻚面或一组⻚面渲染之前运行我们定义的函数,常用于权限控制、校验等任务。 范例代码:管理员⻚面保护,创建middleware/auth.js

    export default function({ route, redirect, store }) { // 上下文中通过store访问vuex中的全局状态 // 通过vuex中令牌存在与否判断是否登录 if (!store.state.user.token) { redirect("/login?redirect="+route.path);

    注册中间件,admin.vue

    <script>
       export default {
           middleware: ['auth']
    //全局注册
    </script>
      router: {
     middleware: ['auth']
    

    状态管理 vuex

    应用根目录下如果存在 store 目录,Nuxt.js将启用vuex状态树。定义各状态树时具名导出state, mutations, getters, actions即可。
    范例:用户登录及登录状态保存,创建store/user.js

    export const state = () => ({ token: '' export const mutations = { init(state, token) { state.token = token; export const getters = { isLogin(state) { return !!state.token; export const actions = { login({ commit, getters }, u) { return this.$axios.$post("/api/login", u).then(({ token }) => { if (token) { commit("init", token); return getters.isLogin;

    登录⻚面逻辑,login.vue

    <template> <h2>用户登录</h2> <el-input v-model="user.username"></el-input> <el-input type="password" v-model="user.password"></el-input> <el-button @click="onLogin">登录</el-button> </template> <script> export default { data() { return { user: { username: "", password: "" }, methods: { onLogin() { this.$store.dispatch("user/login", this.user).then(ok=>{ if (ok) { const redirect = this.$route.query.redirect || '/' this.$router.push(redirect); } }); </script>

    Nuxt.js会在运行应用之前执行插件函数,需要引入或设置Vue插件、自定义模块和第三方模块时特别有 用。
    范例代码:接口注入,利用插件机制将服务接口注入组件实例、store实例中,创建plugins/api-inject.js

    范例:添加请求拦截器附加token,创建plugins/interceptor.js

    export default ({ $axios }, inject) => {
     inject("login", user => {
       return $axios.$post("/api/login", user);
    

    注册插件,nuxt.config.js

    plugins: [
     "@/plugins/api-inject"
    

    范例:添加请求拦截器附加token,创建plugins/interceptor.js

    export default function({ $axios, store }) { $axios.onRequest(config => { if (store.state.user.token) { config.headers.Authorization = "Bearer " + store.state.user.token; return config;

    注册插件,nuxt.config.js

    plugins: ["@/plugins/interceptor"]
    

    nuxtServerInit

    通过在store的根模块中定义 nuxtServerInit 方法,Nuxt.js 调用它的时候会将⻚面的上下文对象作 为第2个参数传给它。当我们想将服务端的一些数据传到客户端时,这个方法非常好用。
    范例:登录状态初始化,store/index.js

    export const actions = { nuxtServerInit({ commit }, { app }) { const token = app.$cookies.get("token"); if (token) { console.log("nuxtServerInit: token:"+token); commit("user/init", token);

    安装依赖模块:cookie-universal-nuxt npm i -S cookie-universal-nuxt
    注册, nuxt.config.js

    modules: ["cookie-universal-nuxt"],
    

    nuxtServerInit只能写在store/index.js nuxtServerInit仅在服务端执行

    服务端渲染应用部署

    先进行编译构建,然后再启动 Nuxt 服务

     npm run build
    npm start
    

    生成内容在.nuxt/dist中