文来自 企业微信 移步到微 官网原文链接:http://www.easywork365.com/999a967.html
有开发者反映,在开发微信小程序时候,遇到了一个困扰很久的问题:页面之间,如何传递数据和变量?刚开始,大家比较倾向于选择用路径传输参数解决,但是,各浏览器 HTTP Get 请求 URL 最大长度并不相同,大部分浏览器只能接受 7000 个字符的数据。所以,这个方式并不通。
经过研究发现,有两种方式可以比较“委婉”地解决这个问题。
使用全局变量
在项目 app.js 中定义 globalData(全局变量)。
App({
globalData:{
userInfo:'angeladaddy'
}
});
在需要的地方,我们可以随意调用这个全局变量。
getGlobalVar:function(){
var that=this;
that.setData({
globalvar_str:JSON.stringify(getApp().globalData)
})
}
当然,赋值也是没问题的。
onLoad:function(options){
getApp().globalData.userInfo+=' is an awesome man';
},
来试试效果:
使用模板
在官方文档中,模板的使用需要先定义一个模板,要用到 name 属性。
{{index}}: {{msg}}
Time: {{time}}
接着,使用模板和 is 属性,声明需要的使用的模板,然后将模板所需要的 data 传入。比如这样:
给 item 赋值,以显示模板数据。
Page({
data: {
item: {
index: 0,
msg: 'this is a template',
time: '2016-09-15'
}
}
})
这样就duang地一下,解决了页面传值问题。
SO,既然小程序可以使用ES6的所有特性,那么var that=this是什么呢?为什么不可以用箭头函数解决作用域问题?其实大家可以自行have a try。
今年国庆假期终于可以憋在家里了不用出门了,不用出去看后脑了,真的是一种享受。这么好的光阴怎么浪费,睡觉、吃饭、打豆豆这怎么可能(耍多了也烦),完全不符合我们程序员的作风,赶紧起来把文章写完。
这篇文章比较基础,在国庆期间的业余时间写的,这几天又完善了下,力求把更多的前端所涉及到的关于文件上传的各种场景和应用都涵盖了,若有疏漏和问题还请留言斧正和补充。
以下是本文所涉及到的知识点,break or continue ?
原理很简单,就是根据 http 协议的规范和定义,完成请求消息体的封装和消息体的解析,然后将二进制内容保存到文件。
我们都知道如果要上传一个文件,需要把 form 标签的enctype设置为multipart/form-data,同时method必须为post方法。
那么multipart/form-data表示什么呢?
multipart互联网上的混合资源,就是资源由多种元素组成,form-data表示可以使用HTML Forms 和 POST 方法上传文件,具体的定义可以参考RFC 7578。
multipart/form-data 结构
看下 http 请求的消息体
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryDCntfiXcSkPhS4PN 表示本次请求要上传文件,其中boundary表示分隔符,如果要上传多个表单项,就要使用boundary分割,每个表单项由———XXX开始,以———XXX结尾。
每一个表单项又由Content-Type和Content-Disposition组成。
Content-Disposition: form-data 为固定值,表示一个表单元素,name 表示表单元素的 名称,回车换行后面就是name的值,如果是上传文件就是文件的二进制内容。
Content-Type:表示当前的内容的 MIME 类型,是图片还是文本还是二进制数据。
解析
客户端发送请求到服务器后,服务器会收到请求的消息体,然后对消息体进行解析,解析出哪是普通表单哪些是附件。
可能大家马上能想到通过正则或者字符串处理分割出内容,不过这样是行不通的,二进制buffer转化为string,对字符串进行截取后,其索引和字符串是不一致的,所以结果就不会正确,除非上传的就是字符串。
不过一般情况下不需要自行解析,目前已经有很成熟的三方库可以使用。
至于如何解析,这个也会占用很大篇幅,后面的文章在详细说。
使用 form 表单上传文件
在 ie时代,如果实现一个无刷新的文件上传那可是费老劲了,大部分都是用 iframe 来实现局部刷新或者使用 flash 插件来搞定,在那个时代 ie 就是最好用的浏览器(别无选择)。
DEMO
这种方式上传文件,不需要 js ,而且没有兼容问题,所有浏览器都支持,就是体验很差,导致页面刷新,页面其他数据丢失。
HTML
<form method="post" action="http://localhost:8100" enctype="multipart/form-data">
选择文件:
<input type="file" name="f1"/> input 必须设置 name 属性,否则数据无法发送<br/>
<br/>
标题:<input type="text" name="title"/><br/><br/><br/>
<button type="submit" id="btn-0">上 传</button>
</form>
复制代码
服务端文件的保存基于现有的库koa-body结合 koa2实现服务端文件的保存和数据的返回。
在项目开发中,文件上传本身和业务无关,代码基本上都可通用。
在这里我们使用koa-body库来实现解析和文件的保存。
koa-body 会自动保存文件到系统临时目录下,也可以指定保存的文件路径。
然后在后续中间件内得到已保存的文件的信息,再做二次处理。
NODE
/**
* 服务入口
*/
var http=require('http');
var koaStatic=require('koa-static');
var path=require('path');
var koaBody=require('koa-body');//文件保存库
var fs=require('fs');
var Koa=require('koa2');
var app=new Koa();
var port=process.env.PORT || '8100';
var uploadHost=`http://localhost:${port}/uploads/`;
app.use(koaBody({
formidable: {
//设置文件的默认保存目录,不设置则保存在系统临时目录下 os
uploadDir: path.resolve(__dirname, '../static/uploads')
},
multipart: true // 开启文件上传,默认是关闭
}));
//开启静态文件访问
app.use(koaStatic(
path.resolve(__dirname, '../static')
));
//文件二次处理,修改名称
app.use((ctx)=> {
var file=ctx.request.files.f1;//得道文件对象
var path=file.path;
var fname=file.name;//原文件名称
var nextPath=path+fname;
if(file.size>0 && path){
//得到扩展名
var extArr=fname.split('.');
var ext=extArr[extArr.length-1];
var nextPath=path+'.'+ext;
//重命名文件
fs.renameSync(path, nextPath);
}
//以 json 形式输出上传文件地址
ctx.body=`{
"fileUrl":"${uploadHost}${nextPath.slice(nextPath.lastIndexOf('/')+1)}"
}`;
});
/**
* http server
*/
var server=http.createServer(app.callback());
server.listen(port);
console.log('demo1 server start ...... ');
复制代码
CODE
https://github.com/Bigerfe/fe-learn-code/
外话:近来想把网站做下更新,从框架到内容的更新,但又不想放弃SEO的优势,日常工作用到vue.js在SEO方面劣势较多,果断选择了Nuxt.js,苦于国内文章抄袭的非常严重 如某n 某书,最终在稀土找到一篇像样的文章,以头条为平台记录网站改版全过程。
此文章建议在PC端查看,涉及到代码部分,移动端查看确实不方便
简而言之,Nuxt.js是帮助Vue.js轻松完成服务端渲染工作的框架。Nuxt.js预设了服务端渲染所需要的各种配置,如异步数据,中间件,路由。它好比是 Angular Universal 之于 Angular, Next.js 之于 React。
如Nuxt.js文档所说,通过对客户端/服务端基础架构的抽象,Nuxt.js 让开发者专注于页面的UI渲染。
Nuxt.js的一个重要功能是,通过 generate 命令,生成静态站点。类似于流行的静态生成工具Jekyll。
除了Vue.js 2.0之外,Nuxt.js集成了如下模块: Vue-Router, Vue-Meta 和 Vuex (仅在使用 Vuex 状态树配置项 时引入)。 这样的好处在于,不需要手工配置依赖,不需要同时在客户端和服务端配置相同的库。 Nuxt.js在包含如上依赖的情况下,总大小仍然保持在 28kb min+gzip (如果使用了 Vuex 特性的话为 31kb)。
另外,Nuxt.js 使用 Webpack 和 vue-loader 、 babel-loader 来处理代码的自动化构建工作(如打包、代码分层、压缩等等)。
当你访问一个基于Nuxt.js构建的页面时,发生了的事情如下:
下图阐述了 Nuxt.js 应用一个完整的服务器请求渲染的流程,摘自官网:
下面让我们动手创建一个基于Nuxt.js简单的静态博客。我们的发送的请求,返回 mock 的JSON数据。
完成下面的例子,你需要了解基础的 vue.js 知识。如果你是个新手,你可以通过Jack Franklin的getting started guide了解 Vue.js 2.0。同时,我将使用ES6语法,你可以参考www.sitepoint.com/tag/es6/ 重温ES6语法。
我们的 Demo 最终效果如下:
本文中代码可参照 GitHub, demo 地址如下:https://github.com/sitepoint-editors/nuxt-ssr-blog/
开始使用 Nuxt.js 最简单的方式就是使用 Nuxt.js 团队自己开发的脚手架。我们可以使用 vue-cli 快速创建我们的项目 (ssr-blog):
`vue init nuxt/starter ssr-blog`
# 提示: 如果你没有安装过vue-cli,请先通过npm install -g vue-cli 命令安装vue-cli。
# 之后,我们将安装项目的依赖
cd ssr-blog
npm install
# 现在我们启动程序:
`npm run dev`
# 如果正确启动, 你能访问 http://localhost:3000
# 展示的页面是 Nuxt.js 模板的初始页面
# 你也可以通过查看页面源代码,验证页面所展示的一切内容,都是服务端渲染好的。
下面,我们简单配置下 nuxt.config.js,包含以下选项:
// ./nuxt.config.js
module.exports={
/*
* Headers of the page
*/
head: {
titleTemplate: '%s | Awesome JS SSR Blog',
// ...
link: [
// ...
{
rel: 'stylesheet',
href: 'https://cdnjs.cloudflare.com/ajax/libs/bulma/0.4.2/css/bulma.min.css'
}
]
},
// ...
}
在如上配置文件下,我们使用 titleTemplate 字段 title 变量指定文章题目,在渲染之前用title变量值替换掉%s这个占位,填充到titleTemplate 。
同时,我也使用了 CSS 框架, Bulma, 预设一些样式。通过 link 配置项。
提示: Nuxt.js使用 vue-meta 更新我们的 html headers 信息。所以,我们可以看看 meta 具体的配置项,优化页面 html 信息。
现在,我们可以通过几个步骤,完成博客的页面和功能。
首先,我们将为我们所有的页面定义一个通用的基本布局。我们通过修改 layouts/default.vue 文件,更新 main Nuxt.js layout:
<!-- ./layouts/default.vue -->
<template>
<div>
<!-- navigation -->
<nav class="nav has-shadow">
<div class="container">
<div class="nav-left">
<nuxt-link to="/" class="nav-item">
Awesome JS SSR Blog!
</nuxt-link>
<nuxt-link active-class="is-active" to="/" class="nav-item is-tab" exact>Home</nuxt-link>
<nuxt-link active-class="is-active" to="/about" class="nav-item is-tab" exact>About</nuxt-link>
</div>
</div>
</nav>
<!-- /navigation -->
<!-- displays the page component -->
<nuxt/>
</div>
</template>
在我们通用的布局里,我们仅仅对页面添加导航栏,我们通过 component进一步完成具体页面模块的定制。你可以查看components-nuxt-link 进一步了解。
在创建布局时component非常重要,它决定具体页面展示的元素。
当然,component也可以做更多事情,比如定义通用组件和错误页面,但是我们的博客很简单,不需要这些功能。强烈建议阅读 Nuxt.js documentation on views ,你可以通过这篇文章了解更多 Nuxt.js 特性。
Nuxt.js 页面是以 单文件组件 形式组织目录结构。 Nuxt.js 自动找到目录下每个 .vue 文件,并添加到页面中。
我们可以通过修改 index.vue 文件修改主页, 通过 Nuxt.js 创建的文件如下:
<!-- ./pages/index.vue -->
<template>
<div>
<section class="hero is-medium is-primary is-bold">
<div class="hero-body">
<div class="container">
<h1 class="title">
Welcome to the JavaScript SSR Blog.
</h1>
<h2 class="subtitle">
Hope you find something you like.
</h2>
</div>
</div>
</section>
</div>
</template>
<script>
export default {
head: {
title: 'Home'
}
}
</script>
如前所述,在渲染之前,题目将自动填充至文件。
我们现在可以刷新页面,看看主页的变化。
Nuxt.js 还有一个优秀的特性,监听文件夹下文件的更改,所以,在文件更改时,不需要重启应用更新。
来,我们添加一个简单的 about.vue 页面:
<!-- ./pages/about.vue -->
<template>
<div class="main-content">
<div class="container">
<h2 class="title is-2">About this website.</h2>
<p>Curabitur accumsan turpis pharetra <strong>augue tincidunt</strong> blandit. Quisque condimentum maximus mi, sit amet commodo arcu rutrum id. Proin pretium urna vel cursus venenatis. Suspendisse potenti. Etiam mattis sem rhoncus lacus dapibus facilisis. Donec at dignissim dui. Ut et neque nisl.</p>
<br>
<h4 class="title is-4">What we hope to achieve:</h4>
<ul>
<li>In fermentum leo eu lectus mollis, quis dictum mi aliquet.</li>
<li>Morbi eu nulla lobortis, lobortis est in, fringilla felis.</li>
<li>Aliquam nec felis in sapien venenatis viverra fermentum nec lectus.</li>
<li>Ut non enim metus.</li>
</ul>
</div>
</div>
</template>
<script>
export default {
head: {
title: 'About'
}
}
</script>
现在我们访问 http://localhost:3000/about 看看about页面,无需重启,非常方便。
我们的首页在没有内容的时候展示如上, 所以下一步,我们要在 index.vue 上添加博客列表这个组件。
首先,我们需要把 JSON 格式的文章保存在服务根目录下。文件可以从 这里下载,或者你可以复制下面的 JSON 到根目录文件夹 posts.json 下:
[
{
"id": 4,
"title": "Building universal JS apps with Nuxt.js",
"summary": "Get introduced to Nuxt.js, and build great SSR Apps with Vue.js.",
"content": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>",
"author": "Jane Doe",
"published": "08:00 - 07/06/2017"
},
{
"id": 3,
"title": "Great SSR Use cases",
"summary": "See simple and rich server rendered JavaScript apps.",
"content": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>",
"author": "Jane Doe",
"published": "17:00 - 06/06/2017"
},
{
"id": 2,
"title": "SSR in Vue.js",
"summary": "Learn about SSR in Vue.js, and where Nuxt.js can make it all faster.",
"content": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>",
"author": "Jane Doe",
"published": "13:00 - 06/06/2017"
},
{
"id": 1,
"title": "Introduction to SSR",
"summary": "Learn about SSR in JavaScript and how it can be super cool.",
"content": "<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>",
"author": "John Doe",
"published": "11:00 - 06/06/2017"
}
]
提示: 理想情况下,我们应该从通过 API 获取文章数据。
components 存放在 components 文件夹下,我们可以创建如下组件:
<!-- ./components/Posts.vue -->
<template>
<section class="main-content">
<div class="container">
<h1 class="title has-text-centered">
Recent Posts.
</h1>
<div class="columns is-multiline">
<div class="column is-half" v-for="post in posts">
<div class="card">
<header class="card-header">
<p class="card-header-title">
{{ post.title }}
</p>
</header>
<div class="card-content">
<div class="content">
{{ post.summary }}
<br>
<small>
by <strong>{{ post.author}}</strong>
\\ {{ post.published }}
</small>
</div>
</div>
<footer class="card-footer">
<nuxt-link :to="`/post/${post.id}`"
class="card-footer-item">
Read More
</nuxt-link>
</footer>
</div>
</div>
</div>
</div>
</section>
</template>
<script>
import posts from '~/posts.json'
export default {
name: 'posts',
data () {
return { posts }
}
}
</script>
我们引入 JSON 文件充当异步数据,通过 v-for 指令循环列表,取出我们需要的属性填充进组件模板展示。
提示: ~ 符号是 / 的别名。你可以查看 这篇文档 了解更具体的用法。
下面,我们添加 component 到主页:
<!-- ./pages/index.vue -->
<template>
<div>
<!-- ... -->
<posts />
</div>
</template>
<script>
import Posts from '~components/Posts.vue'
export default {
components: {
Posts
},
// ...
}
</script>
现在,我们为文章页配置动态路由,我们以 /post/1 为例:
为此,我们添加 post 文件夹到 pages 目录下,如下:
pages
└── post
└── _id
└── index.vue
我们的程序生成相应的动态路由:
router: {
routes: [
// ...
{
name: 'post-id',
path: '/post/:id',
component: 'pages/post/_id/index.vue'
}
]
}
更新单一发布文件:
<!-- ./pages/post/_id/index.vue -->
<template>
<div class="main-content">
<div class="container">
<h2 class="title is-2">{{ post.title }}</h2>
<div v-html="post.content"></div>
<br>
<h4 class="title is-5 is-marginless">by <strong>{{ post.author }}</strong> at <strong>{{ post.published }}</strong></h4>
</div>
</div>
</template>
<script>
// import posts saved JSON data
import posts from '~/posts.json'
export default {
validate ({ params }) {
return /^\d+$/.test(params.id)
},
asyncData ({ params }, callback) {
let post=posts.find(post=> post.id===parseInt(params.id))
if (post) {
callback(null, { post })
} else {
callback({ statusCode: 404, message: 'Post not found' })
}
},
head () {
return {
title: this.post.title,
meta: [
{
hid: 'description',
name: 'description',
content: this.post.summary
}
]
}
}
}
</script>
Nuxt.js通过添加通用方法,简化开发流程。看看我们应该如何在单文件应用中使用它。
现在我们可以再次访问我们的博客看到所有路线和页面正常工作,并查看页面源代码生成的HTML。我们有一个服务器端JavaScript应用程序呈现功能。
接下来,我们要生成程序的 HTML 静态文件。
我们需要对 Nuxt.js 做一个小修改,Nuxt.js 默认忽略动态路由。为了生成动态路由文件,我们需要修改 ./nuxt.config.js
我们使用回调函数,返回以后包含动态路由的列表:
// ./nuxt.config.js
module.exports={
// ...
generate: {
routes(callback) {
const posts=require('./posts.json')
let routes=posts.map(post=> `/post/${post.id}`)
callback(null, routes)
}
}
}
如果你想查看全部关于 generate 的配置, 可以参照 这篇文档 。
运行如下命令,生成全部页面:
`npm run generate`
Nuxt 将所有生成的页面放到 dist 文件夹下。
最后一步,可以使用 Nginx 进行部署,nginx的安装过程此文不再赘述。
generate 命令来生成我们页面的静态文件,假如,我们需要回复。
下一期讲,改版中的踩坑问题。
*请认真填写需求信息,我们会在24小时内与您取得联系。