文來自 企業微信 移步到微 官網原文鏈接: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通過添加通用方法,簡化開發流程??纯次覀儜撊绾卧趩挝募弥惺褂盟?/p>
現在我們可以再次訪問我們的博客看到所有路線和頁面正常工作,并查看頁面源代碼生成的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小時內與您取得聯系。