客户端渲染模式下,服务端把渲染的静态文件给到客户端,客户端拿到服务端发送过来的文件自己跑一遍 JS,根据 JS运行结果,生成相应 DOM,然后渲染给用户。
前端渲染的方式起源于 JavaScript 的兴起,ajax 的大热更是让前端渲染更加成熟,前端渲染真正意义上的实现了前后端分离,前端只专注于 UI 的开发,后端只专注于逻辑的开发,前后端交互只通过约定好的API来交互,后端提供 json 数据,前端循环 json 生成 DOM 插入到页面中去。
大多数平台采用的是客户端渲染,查看首页的源代码会发现代码里的 html 结构只有简单的几句。当请求首页面时,返回的 body 为空,之后执行 js 将 html 结构注入到 body 里,结合 css 显示出来;
<body>
<div id=app></div>
<script type=text/javascript src=/static/js/manifest.9476fbe0d0f0fe7c5038.js></script>
</body>
服务端渲染: 当用户第一次请求页面时,由服务器把需要的组件或页面渲染成 HTML 字符串,然后把它返回给客户端。客户端拿到手的,是可以直接渲染然后呈现给用户的 HTML 内容,不需要为了生成 DOM 内容自己再去跑一遍 JS 代码。使用服务端渲染的网站,可以说是“所见即所得”
,页面上呈现的内容,我们在 html 源文件里也能找到。如下,我们查看网页源码的时候,可以看到全部内容。
通过服务端渲染的概念以及它的两个特点:首屏加载速度快
、SEO优化
。我们知道,服务端渲染其实就是由浏览器做的一些事情,我们放到了服务端去做
。关于在 server 端还是在 browser 端渲染的选择,更多的是要看业务场景。
服务端渲染框架应用有Nuxt.js
、Beidou(北斗)
等。
Nuxt.js
是一个基于 Vue.js 的轻量级应用框架,可用来创建服务端渲染 (SSR) 应用,也可充当静态站点引擎生成静态站点应用,具有优雅的代码结构分层和热加载等特性。
Beidou(北斗)
是 NodeJS & React 同构框架,基于Egg.js开发。
尝试了这两个框架,对比觉得Nuxt.js更简单易上手,下面就用Nuxt.js搭建一个服务端渲染应用来介绍下 Nuxt.js 的用法。
为了快速入门,Nuxt.js团队创建了脚手架工具 create-nuxt-app
。
npx create-nuxt-app nuxtdemo
它会让你进行一些选择,比如集成的服务器端框架、喜欢的UI框架、测试框架、添加 axios、Eslint、 Prettier 等。根据项目需求进行选择就好了。这里以服务器框架选择None (Nuxt默认服务器)
,UI框架选择Element UI
为例进行讲解。
勾选完毕后,它将安装所有依赖项,因此下一步是直接启动项目:
cd nuxtdemo
npm run dev
这时候我们可以看到一个默认简易的项目搭建完成啦,如下所示:
接下来,我们来看下整个项目的目录结构
├── assets 未编译的静态资源如 LESS、SASS 或 JavaScript
├── components 组件,不会像页面组件那样有 asyncData 方法的特性
├── layouts 布局目录 layouts 用于组织应用的布局组件
├── middleware 用于存放应用的中间件
├── nuxt.config.js 用于组织Nuxt.js 应用的个性化配置,以便覆盖默认配置
├── package.json 用于描述应用的依赖关系和对外暴露的脚本接口
├── pages 用于组织应用的路由及视图
├── plugins 存放需要在根vue.js应用实例化之前需要运行的JS插件
├── static 用于存放应用的静态文件(不会被webpack编译处理)
├── store 应用的 Vuex 状态树
了解了每个文件的作用,我们来用Nuxt.js搭一个简单的网站吧。用一个简单的网站,讲解下 Nuxt.js 的基础用法。
我们用 Nuxt.js 来搭一个常用的网页框架,包括公共头部、底部、动态路由、嵌套路由,错误页面,以及在 Nuxt.js 框架下如何引用公共样式、公共方法、路由校验等。先放上网站成品图
下载链接:
git clone git@code.aliyun.com:echomaps/nuxtdemo.git
这是个简易的网站,包括公共头部跟尾部。首页是一个文章列表,采用了动态路由,点进去可以跳到对应的文章。人员介绍页面采用了嵌套路由。在左侧点击人员,右侧可以相应出来人员的信息。好,让我们来开始吧。
一般网站都有公共的头部、底部。在之前的项目中,我们都得手动去引入头部、尾部组件。如下:
import header from '@/publicResource/components/header.vue'
import footer from '@/publicResource/components/footer.vue'
export default {
components: {
'v-header': header,
'v-footer': footer
}
}
但在 Nuxt.js 中就不用这么麻烦。我们直接在 layout
目录下创建自定义的布局。修改 layouts/default.vue
文件来扩展应用的默认布局
<template>
<div>
<v-header></v-header>
<nuxt />
<v-footer></v-footer>
</div>
</template>
<script>
import Header from '~/components/Header.vue'
import Footer from '~/components/Footer.vue'
export default {
components: {
'v-header': Header,
'v-footer': Footer
},
data () {
return { }
}
}
</script>
<nuxt/>
组件用于显示页面的主体内容。这样所有的页面都会自动带上头部、尾部,不用特意声明与引入。如果有些页面布局不需要头部、尾部,这也很简单,我们只需要告诉页面使用哪个自定义布局即可。
<template>
<!-- Your template -->
</template>
<script>
export default {
layout: 'blog'
// page component definitions
}
</script>
我们也可以通过编辑 layouts/error.vue
文件来定制化错误页面。这个布局文件不需要包含 <nuxt/>
标签。可以把这个布局文件当成是显示应用错误(404,500等)的组件。
<template>
<div class="error-wrap">
<p v-if="error.statusCode === 404" class="info">页面不存在</p>
<p class="info" v-else>应用发生错误异常</p>
<p><nuxt-link to="/">首 页</nuxt-link></p>
</div>
</template>
<script>
export default {
props: ['error'],
}
</script>
Nuxt.js
中不用编写路由配置文件,只需要按照API规定命名与存放文件,即可自动生成路由配置文件。例如,我们需要新增一个人员介绍页面users
. 只需要在pages
下新增users页面,就可以自动生成路由。假设 pages 的目录结构如下:
pages/
--| users.vue
--| index.vue
那么,Nuxt.js 自动生成的路由配置如下:
router: {
routes: [
{
name: 'index',
path: '/',
component: 'pages/index.vue'
},
{
name: 'users',
path: '/users',
component: 'pages/users.vue'
}
]
}
其它页面引用的时候,直接用nuxt-link
即可
<nuxt-link to="/users">人员介绍</nuxt-link>
同样地,我们也可以通过框架规定的命名、存放文件。无需配置路由,可生成动态路由、嵌套路由的配置文件。
在 Nuxt.js 里面定义带参数的动态路由,需要创建对应的以下划线作为前缀的 Vue 文件 或 目录。如下所示:
├── pages
├────── blogs
│ └─── _blog.vue 博客的详情页
├────── index.vue 首页
假如我们在index.vue
中编写一个文章列表并链接到对应的文章页面,如下:
<template>
<div class="container">
<div class="bm-sider">
{{content}}
</div>
<div class="bm-con">
<ul>
<li><nuxt-link to="blogs/1">这是文章1</nuxt-link></li>
<li><nuxt-link to="blogs/2">这是文章2</nuxt-link></li>
<li><nuxt-link to="blogs/3">这是文章3</nuxt-link></li>
</ul>
</div>
</div>
</template>
pages/blogs/_blog.vue
:
<template>
<div class="container">
这是内容{{$route.params.blog}}
</div>
</template>
<script>
export default {
components: {},
data () {
return { }
},
validate ({ params }) {
return !isNaN(+params.blog)
}
}
</script>
这样,默认首页的展示如下:
当点击具体文章时候,展示如下:
我们还可以添加 validate 配置一个校验方法用于校验动态路由参数的有效性。如果校验方法返回的值不为 true 或 Promise 中 resolve 解析为 false 或抛出 Error , Nuxt.js 将自动加载显示 404 错误页面或 500 错误页面。这里我们设置只有数字可以正常访问,其它路由将跳到错误页面。如下所示:
创建内嵌子路由,需要添加一个 Vue 文件,同时添加一个与该文件同名的目录用来存放子视图组件。在父组件(.vue文件) 内增加用于显示子视图内容。
人员介绍页面采用了嵌套路由。点击左侧的人员名单,将出现对应的人员信息,效果如下:
实现这一效果,我们需要在 pages下添加人员介绍页面 users.vue
<template>
<div class="container">
<div class="bm-sider">
<ul class="players">
<li v-for="user in users" :key="user.id">
<NuxtLink :to="'/users/'+user.id">
{{ user.name }}
</NuxtLink>
</li>
</ul>
</div>
<div class="bm-con">
<NuxtChild :key="$route.params.id" />
</div>
</div>
</template>
同时添加一个与该文件同名的目录用来存放子视图组件。文件如下命名:
├── users
│ ├── _id.vue 点击人员后对应的人员信息组件
│ └── index.vue 默认的视图组件
└── users.vue 人员介绍页面
users/index.vue
:
<template>
<h2>Please select an user.</h2>
</template>
users/_id.vue
:
<template>
<div class="player">
<h1>#{{ number }}</h1>
<h2>{{ name }}</h2>
</div>
</template>
<script>
export default {
validate ({ params }) {
return !isNaN(+params.id)
},
asyncData ({ params, env, error }) {
const user = env.users.find(user => String(user.id) === params.id)
if (!user) {
return error({ message: 'User not found', statusCode: 404 })
}
return user
},
head () {
return {
title: this.name
}
}
}
</script>
这样,当我们未点击人员时候,人员介绍默认页面是这样的:
点击人员后,人员介绍页面将展示对应的人员信息内容:
在 Nuxt 中添加全局 css 也是非常简单的。我们在 assets 下新建一个 css 文件 base.css
。然后在 nuxt.config.js
中引用即可。
css: [
'~assets/base.css',
],
将内容注入 Vue 实例,避免重复引入,在 Vue 原型上挂载注入一个函数,所有组件内都可以访问。
plugins/vue-inject.js
:
import Vue from 'vue'
Vue.prototype.$myInjectedFunction = (string) => console.log("This is an example", string)
这样,我们就可以在所有Vue组件中使用该函数。
example-component.vue
:
export default {
mounted(){
this.$myInjectedFunction('test')
}
}
Nuxt.js 是使用 Webpack 和 Node.js 进行封装的基于 Vue 的 SSR 框架,使用它,你可以不需要自己搭建一套 SSR 程序,而是通过其约定好的文件结构和API就可以实现一个首屏渲染的 Web 应用。整体上,Nuxt.js 通过各个文件夹和配置文件的约束来管理我们的程序,而又不失扩展性。
本文由哈喽比特于3年以前收录,如有侵权请联系我们。
文章来源:https://mp.weixin.qq.com/s/NUujJlIsR5X3p2mizUczXw
京东创始人刘强东和其妻子章泽天最近成为了互联网舆论关注的焦点。有关他们“移民美国”和在美国购买豪宅的传言在互联网上广泛传播。然而,京东官方通过微博发言人发布的消息澄清了这些传言,称这些言论纯属虚假信息和蓄意捏造。
日前,据博主“@超能数码君老周”爆料,国内三大运营商中国移动、中国电信和中国联通预计将集体采购百万台规模的华为Mate60系列手机。
据报道,荷兰半导体设备公司ASML正看到美国对华遏制政策的负面影响。阿斯麦(ASML)CEO彼得·温宁克在一档电视节目中分享了他对中国大陆问题以及该公司面临的出口管制和保护主义的看法。彼得曾在多个场合表达了他对出口管制以及中荷经济关系的担忧。
今年早些时候,抖音悄然上线了一款名为“青桃”的 App,Slogan 为“看见你的热爱”,根据应用介绍可知,“青桃”是一个属于年轻人的兴趣知识视频平台,由抖音官方出品的中长视频关联版本,整体风格有些类似B站。
日前,威马汽车首席数据官梅松林转发了一份“世界各国地区拥车率排行榜”,同时,他发文表示:中国汽车普及率低于非洲国家尼日利亚,每百户家庭仅17户有车。意大利世界排名第一,每十户中九户有车。
近日,一项新的研究发现,维生素 C 和 E 等抗氧化剂会激活一种机制,刺激癌症肿瘤中新血管的生长,帮助它们生长和扩散。
据媒体援引消息人士报道,苹果公司正在测试使用3D打印技术来生产其智能手表的钢质底盘。消息传出后,3D系统一度大涨超10%,不过截至周三收盘,该股涨幅回落至2%以内。
9月2日,坐拥千万粉丝的网红主播“秀才”账号被封禁,在社交媒体平台上引发热议。平台相关负责人表示,“秀才”账号违反平台相关规定,已封禁。据知情人士透露,秀才近期被举报存在违法行为,这可能是他被封禁的部分原因。据悉,“秀才”年龄39岁,是安徽省亳州市蒙城县人,抖音网红,粉丝数量超1200万。他曾被称为“中老年...
9月3日消息,亚马逊的一些股东,包括持有该公司股票的一家养老基金,日前对亚马逊、其创始人贝索斯和其董事会提起诉讼,指控他们在为 Project Kuiper 卫星星座项目购买发射服务时“违反了信义义务”。
据消息,为推广自家应用,苹果现推出了一个名为“Apps by Apple”的网站,展示了苹果为旗下产品(如 iPhone、iPad、Apple Watch、Mac 和 Apple TV)开发的各种应用程序。
特斯拉本周在美国大幅下调Model S和X售价,引发了该公司一些最坚定支持者的不满。知名特斯拉多头、未来基金(Future Fund)管理合伙人加里·布莱克发帖称,降价是一种“短期麻醉剂”,会让潜在客户等待进一步降价。
据外媒9月2日报道,荷兰半导体设备制造商阿斯麦称,尽管荷兰政府颁布的半导体设备出口管制新规9月正式生效,但该公司已获得在2023年底以前向中国运送受限制芯片制造机器的许可。
近日,根据美国证券交易委员会的文件显示,苹果卫星服务提供商 Globalstar 近期向马斯克旗下的 SpaceX 支付 6400 万美元(约 4.65 亿元人民币)。用于在 2023-2025 年期间,发射卫星,进一步扩展苹果 iPhone 系列的 SOS 卫星服务。
据报道,马斯克旗下社交平台𝕏(推特)日前调整了隐私政策,允许 𝕏 使用用户发布的信息来训练其人工智能(AI)模型。新的隐私政策将于 9 月 29 日生效。新政策规定,𝕏可能会使用所收集到的平台信息和公开可用的信息,来帮助训练 𝕏 的机器学习或人工智能模型。
9月2日,荣耀CEO赵明在采访中谈及华为手机回归时表示,替老同事们高兴,觉得手机行业,由于华为的回归,让竞争充满了更多的可能性和更多的魅力,对行业来说也是件好事。
《自然》30日发表的一篇论文报道了一个名为Swift的人工智能(AI)系统,该系统驾驶无人机的能力可在真实世界中一对一冠军赛里战胜人类对手。
近日,非营利组织纽约真菌学会(NYMS)发出警告,表示亚马逊为代表的电商平台上,充斥着各种AI生成的蘑菇觅食科普书籍,其中存在诸多错误。
社交媒体平台𝕏(原推特)新隐私政策提到:“在您同意的情况下,我们可能出于安全、安保和身份识别目的收集和使用您的生物识别信息。”
2023年德国柏林消费电子展上,各大企业都带来了最新的理念和产品,而高端化、本土化的中国产品正在不断吸引欧洲等国际市场的目光。
罗永浩日前在直播中吐槽苹果即将推出的 iPhone 新品,具体内容为:“以我对我‘子公司’的了解,我认为 iPhone 15 跟 iPhone 14 不会有什么区别的,除了序(列)号变了,这个‘不要脸’的东西,这个‘臭厨子’。