Udemy - Nuxt JS with Laravel API - Building SSR Vue JS Apps 笔记5 Project - A simple Nuxt app

Making Api Request The Vue Way

新建pages/posts/index.vue文件:

<template>
   <div>
     <h2>Making API request - the Vue way</h2>
     <div v-for="post in posts" :key="post.id">
     <span>
       {{post.title}}
     </span>
     </div>
   </div>
 </template>

<script>
   import axios from 'axios';

  export default {
     name: "index.vue",
     data() {
       return {
         posts: [],
       }
     },
     mounted() {
       axios.get('https://jsonplaceholder.typicode.com/todos')
         .then(response => {
           console.log(response);
           this.posts = response.data;
         })
         .catch(function (error) {
           console.log(error);
         })
     },
   }
 </script>

<style scoped>

</style>

或者:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <div v-for="post in posts" :key="post.id">
    <span>
      {{post.title}}
    </span>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';

  export default {
    name: "index.vue",
    data() {
      return {
        posts: [],
      }
    },
    mounted() {
      let that = this;
      axios.get('https://jsonplaceholder.typicode.com/todos')
        .then(function (response) {
          console.log(response);
          that.posts = response.data;
        })
        .catch(function (error) {
          console.log(error);
        })
    },
  }
</script>

<style scoped>

</style>

因为要用到axios,前期未安装:

看package.json:

批注 2020-05-13 090652

执行安装axios:

npm i axios

或者

npm install axios

i是install的简写;

这里提供一个在线的REST API测试服务,https://jsonplaceholder.typicode.com/

修改components/Nav.vue:

<template>
  <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
    <a class="navbar-brand" href="#">Nuxt App</a>
    <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav"
            aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
      <span class="navbar-toggler-icon"></span>
    </button>
    <div class="collapse navbar-collapse" id="navbarNav">
      <ul class="navbar-nav">
        <li class="nav-item active">
          <nuxt-link to="/" class="nav-link">Home</nuxt-link>
        </li>
        <li class="nav-item">
          <nuxt-link to="/users" class="nav-link">Users</nuxt-link>
        </li>
        <li class="nav-item">
          <nuxt-link to="/posts" class="nav-link">Posts</nuxt-link>
        </li>
      </ul>
    </div>
  </nav>
</template>

<script>
  export default {
    name: "Nav"
  }
</script>

<style scoped>

</style>

打开 http://localhost:3000/posts 结果:

批注 2020-05-13 092124

但是注意,这个并不是SSR 服务端渲染的,可以右键查看 view pagesource:

批注 2020-05-13 092655

源代码中并无页面内容元素。

而要服务端渲染又能处理这种axios异步请求的,请看下面的AsyncData

Nuxt AsyncData Method

批注 2020-05-13 093411

AsyncData method runs on both client and server side

posts/index.vue修改如下:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <div v-for="post in posts" :key="post.id">
    <span>
      {{post.title}}
    </span>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';

  export default {
    name: "index.vue",
    data() {
      return {
        posts: [],
      }
    },
    // mounted() {
    //   axios.get('https://jsonplaceholder.typicode.com/todos')
    //     .then(response => {
    //       console.log(response);
    //       this.posts = response.data;
    //     })
    //     .catch(function (error) {
    //       console.log(error);
    //     })
    // },
    asyncData(context) {
      console.log(context);
    },
  }
</script>

<style scoped>

</style>

刷新http://localhost:3000/posts 页面,查看terminal中:

nuxt-asyncdata

console.log结果出现在了server side,

当从 http://localhost:3000/ 点击 导航按钮 posts 后,浏览器控制台出现:

批注 2020-05-13 094618

console.log结果出现在了client side 而server side没有新结果。

也就是说,asyncData方法会在client side 和 server side 运行。

初次刷新页面的时候,会在服务器端执行,而后期跳转页面的时候,会在客户端执行。

Using AsyncData Method

修改posts/index.vue:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <div v-for="post in posts" :key="post.id">
    <span>
      {{post.title}}
    </span>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';

  export default {
    name: "index.vue",
    data() {
      return {
        posts: [],
      }
    },
    // mounted() {
    //   axios.get('https://jsonplaceholder.typicode.com/todos')
    //     .then(response => {
    //       console.log(response);
    //       this.posts = response.data;
    //     })
    //     .catch(function (error) {
    //       console.log(error);
    //     })
    // },
    asyncData(context) {
      return {
        posts: [
          {id: 1, title: 'a'},
          {id: 2, title: 'b'},
          {id: 3, title: 'c'},
        ]
      }
    },
  }
</script>

<style scoped>

</style>

http://localhost:3000/posts 结果如下:

批注 2020-05-13 095553

修改posts/index.vue:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <div v-for="post in posts" :key="post.id">
    <span>
      {{post.title}}
    </span>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';

  export default {
    name: "index.vue",
    data() {
      return {
        posts: [],
      }
    },
    // mounted() {
    //   axios.get('https://jsonplaceholder.typicode.com/todos')
    //     .then(response => {
    //       console.log(response);
    //       this.posts = response.data;
    //     })
    //     .catch(function (error) {
    //       console.log(error);
    //     })
    // },
    asyncData(context) {
      return axios.get('https://jsonplaceholder.typicode.com/todos')
        .then(response => {
          return {
            posts: response.data
          };
        })
        .catch(error => {

        });

    },
  }
</script>

<style scoped>

</style>

打开 http://localhost:3000/posts 结果:

批注 2020-05-13 100145

查看页面源代码结果:

批注 2020-05-13 100242

嗯,相比直接vue,对SEO更友好了。

我们来看看搜索引擎会看到什么结果:

关键词 html5 outliner 找一个工具站,我这里用 https://gsnedders.html5.org/outliner/

把上面页面的源代码全部复制然后粘贴到 工具站中:

批注 2020-05-13 100615

点击Outline this! 结果如下:

批注 2020-05-13 100835

如果把span换成h4后结果如下:

批注 2020-05-13 100942

Async Await to make API Request

修改posts/index.vue如下:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <div v-for="post in posts" :key="post.id">
    <span>
      {{post.title}}
    </span>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';

  export default {
    name: "index.vue",
    data() {
      return {
        posts: [],
      }
    },
    // mounted() {
    //   axios.get('https://jsonplaceholder.typicode.com/todos')
    //     .then(response => {
    //       console.log(response);
    //       this.posts = response.data;
    //     })
    //     .catch(function (error) {
    //       console.log(error);
    //     })
    // },
    async asyncData(context) {
      let res = await axios.get('https://jsonplaceholder.typicode.com/todos');
      return {posts: res.data};
    },

  }
</script>

<style scoped>

</style>

或修改asyncData为:

async asyncData(context) {
  let {data} = await axios.get('https://jsonplaceholder.typicode.com/todos');
  return {posts: data};
},

如果需要修改页面的title:

默认定义在nuxt.config.js中:

批注 2020-05-13 104948

不过我们可以给每一个Page都定义:

修改pages/posts/index.vue如下:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <div v-for="post in posts" :key="post.id">
    <span>
      {{post.title}}
    </span>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';

  export default {
    name: "index.vue",
    data() {
      return {
        posts: [],
      }
    },
    // mounted() {
    //   axios.get('https://jsonplaceholder.typicode.com/todos')
    //     .then(response => {
    //       console.log(response);
    //       this.posts = response.data;
    //     })
    //     .catch(function (error) {
    //       console.log(error);
    //     })
    // },
    async asyncData(context) {
      let {data} = await axios.get('https://jsonplaceholder.typicode.com/todos');
      return {posts: data};
    },
    head: {
      title: 'List of posts',
    }

  }
</script>

<style scoped>

</style>

即增加:

批注 2020-05-13 105054

打开 http://localhost:3000/posts 结果:

批注 2020-05-13 105133

fetch方法可以查看官方文档。

https://nuxtjs.org/api/pages-fetch#__layout

Vue Component

新建components/Card.vue文件:

<template>
  <div>
    <div class="card bg-light mb-3" style="max-width: 18rem;">
      <div class="card-header">{{post.id}}</div>
      <div class="card-body">
        <h5 class="card-title">{{post.title}}</h5>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "Card",
    props: {
      post: Object,
    }
  }
</script>

<style scoped>

</style>

pages/posts/index.vue文件修改如下:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <Card v-for="post in posts" :key="post.id" :post="post"></Card>
  </div>
</template>

<script>
  import axios from 'axios';
  import Card from "../../components/Card";

  export default {
    name: "index.vue",
    components: {
      Card,
    },
    data() {
      return {
        posts: [],
      }
    },
    // mounted() {
    //   axios.get('https://jsonplaceholder.typicode.com/todos')
    //     .then(response => {
    //       console.log(response);
    //       this.posts = response.data;
    //     })
    //     .catch(function (error) {
    //       console.log(error);
    //     })
    // },
    async asyncData(context) {
      let {data} = await axios.get('https://jsonplaceholder.typicode.com/todos');
      return {posts: data};
    },
    head: {
      title: 'List of posts',
    }

  }
</script>

<style scoped>

</style>

打开 http://localhost:3000/posts 结果如下:

批注 2020-05-13 111824

Show Post by ID

新建pages.posts/_id/index.vue文件:

<template>
  <div>
    {{$route.params.id}}
  </div>
</template>

<script>
  export default {
    name: "index.vue"
  }
</script>

<style scoped>

</style>

修改components/Card.vue文件:

<template>
  <div>
    <div class="card bg-light mb-3" style="max-width: 18rem;">
      <div class="card-header">{{post.id}}</div>
      <div class="card-body">
        <h5 class="card-title">
          <nuxt-link :to="{name:'posts-id',params:{id:post.id}}">{{post.title}}</nuxt-link>
        </h5>
      </div>
    </div>
  </div>
</template>

<script>
  export default {
    name: "Card",
    props: {
      post: Object,
    }
  }
</script>

<style scoped>

</style>

至于:to参数设置name:’post-id’因为:

批注 2020-05-13 113049

现在 http://localhost:3000/posts 页面:

批注 2020-05-13 113200

点击打卡后:

批注 2020-05-13 113243

Getting Individual Post

修改posts/_id/index.vue文件:

<template>
  <div class="container">
    <h1>{{post.title}}</h1>
    <pre>{{post.body}}</pre>
    <nuxt-link to="/posts">Back to posts page</nuxt-link>
  </div>
</template>

<script>
  import axios from "axios";

  export default {
    name: "index.vue",
    async asyncData(context) {
      let {data} = await axios.get(`https://jsonplaceholder.typicode.com/todos/${context.params.id}`);
      return {post: data};
    },
  }
</script>

<style scoped>

</style>

设置每个post的title 使用动态设置

head(){

return{

title:…

}

}

pages/posts/_id/index.vue:

<template>
  <div class="container">
    <h1>{{post.title}}</h1>
    <pre>{{post.body}}</pre>
    <nuxt-link to="/posts">Back to posts page</nuxt-link>
  </div>
</template>

<script>
  import axios from "axios";

  export default {
    name: "index.vue",

    // async asyncData(context) {
    //   let {data} = await axios.get(`https://jsonplaceholder.typicode.com/posts/${context.params.id}`);
    //   return {post: data};
    // },
    async asyncData({params}) {
      let {data} = await axios.get(`https://jsonplaceholder.typicode.com/posts/${params.id}`);
      return {post: data};
    },

    // head: {
    //   title: this.post.title,
    // }
    head() { //动态设置title
      return {
        title: this.post.title,
      }
    }
  }
</script>

<style scoped>

</style>

pages/posts/index.vue:

<template>
  <div>
    <h2>Making API request - the Vue way</h2>
    <div class="container row">
      <Card class="ml-auto mr-auto" v-for="post in posts" :key="post.id" :post="post"></Card>
    </div>
  </div>
</template>

<script>
  import axios from 'axios';
  import Card from "../../components/Card";

  export default {
    name: "index.vue",
    components: {
      Card,
    },
    data() {
      return {
        posts: [],
      }
    },
    // mounted() {
    //   axios.get('https://jsonplaceholder.typicode.com/todos')
    //     .then(response => {
    //       console.log(response);
    //       this.posts = response.data;
    //     })
    //     .catch(function (error) {
    //       console.log(error);
    //     })
    // },
    async asyncData(context) {
      let {data} = await axios.get('https://jsonplaceholder.typicode.com/posts');
      return {posts: data};
    },
    head: {
      title: 'List of posts',
    }

  }
</script>

<style scoped>

</style>


源代码:https://github.com/dzkjz/nuxt-learning-lesson

批注 2020-05-13 120717

posted @ 2020-05-13 10:11  dzkjz  阅读(49)  评论(0)    收藏  举报