<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                > 原文地址?[https://blog.udemy.com/node-js-tutorial](https://blog.udemy.com/node-js-tutorial) > 感謝來自Udemy的Samantha來信分享 ## 從數據庫中查詢所有視頻 首先,我們來實現一個簡單的功能:在首頁上展示數據庫中所有的視頻。有幾種方式來實現這個功能。我們可以從前端到后端開發,也可以反過來。這并沒有什么對錯,不過在本教程中,處于教學原因我推薦從后端開始開發。 我們將通過以下幾個步驟來實現: 1. 我們將在Mongo中創建一個數據庫并且構建一些視頻文件。 2. 然后我們通過Express在數據庫中創建一個API 3. 最后我們用Angular來調用API并顯示這些數據 如果你對這些技術沒有任何經驗也并無大礙。在本章節中,將覆蓋這些技術的基礎知識。然而,學習起來可能會有一點曲折。請保持耐心,因為一旦我們實現了接下來這些功能,在你再次運用這些概念的時候將會變得得心應手。 ### 第1步:構建數據庫 我們怎么通過數據文件來構建MongoDB數據庫?MongoDB有一個可以通過控制臺訪問的腳本,然而通過腳本訪問并不是很友好,所以為了開發變得簡單,我們將用到一個免費的工具——RboMongo。登陸到?[http://robomong.org](http://robomong.org/)?然后下載適合你操作系統的安裝程序。 啟動RoboMong。你將看見一個用來連接MongoDB服務器的對話框 [![](https://box.kancloud.cn/2015-11-20_564e9a56030bb.png)](http://yalishizhude.github.io/2015/11/02/mean-3/robomongo-1.png) 點擊頂部的?**Create**按鈕。 將連接名稱改為?**localhost**。注意連接地址指向的是**localhost:27017。默認情況下MongoDB將在27017端口上啟動。 [![](https://box.kancloud.cn/2015-11-20_564e9a561cb91.png)](http://yalishizhude.github.io/2015/11/02/mean-3/robomongo-2.png) 如果你點擊?**Test**按鈕,你可能看到一個類似這樣的錯誤“Authorization skipped by you”。不用擔心,忽略這個錯誤連接你本地的MongoDB。 保存配置的連接。回到?**Connect**對話框。連接?**localhost**。 在?**View**菜單中,勾選?**Explorer**選項。現在你的RoboMongo看起來應該是這樣: [![](https://box.kancloud.cn/2015-11-20_564e9a56344bb.png)](http://yalishizhude.github.io/2015/11/02/mean-3/robomongo-3.png) 在?**Explorer**面板,右鍵?**localhost**選擇?**Create Database**。命名數據庫為?**vidzy**。展開?**vidzy**,右鍵**Collections**然后點擊?**Create Collection**。在MongoDB中,一個集合就類似于關系型數據庫中的一張表。將這個集合命名為?**videos**。然后這個集合就顯示在了列表中。 接下來右鍵?**videos**?集合然后選擇?**Insert Document**。1個文檔再MongoDB中類似關系型數據庫中的1條記錄。而MongoDB文檔與之不同的是可以包含其它的文檔。在Mongo中,我們使用JSON格式來展現文檔。復制粘貼下面的代碼到對話框中來新增一個視頻文檔: ~~~ { "title" : "Terminator Genisys", "genre" : "SciFi", "description" : "When John Connor, leader of the human resistance, sends Sgt. Kyle Reese back to 1984 to protect Sarah Connor and safeguard the future, an unexpected turn of events creates a fractured timeline." } ~~~ 注意:在粘貼這些代碼之前請確保對話框中的內容已經清除,不然可能會得到一個非JSON對象。 重復上一步繼續添加兩個文檔到videos集合: ~~~ { "title" : "The Lord of the Rings", "genre" : "Fantasy", "description" : "A meek hobbit of the Shire and eight companions set out on a journey to Mount Doom to destroy the One Ring and the dark lord Sauron." } { "title" : "Apollo 13", "genre" : "Drama", "description" : "NASA must devise a strategy to return Apollo 13 to Earth safely after the spacecraft undergoes massive internal damage putting the lives of the three astronauts on board in jeopardy." } ~~~ 現在右鍵videos集合并選擇?**View Documents。你將在?**videos**集合中看見3個文檔。 [![](https://box.kancloud.cn/2015-11-20_564e9a56478e1.png)](http://yalishizhude.github.io/2015/11/02/mean-3/robomongo-4.png) 注意到每個文檔都有一個由MongoDB自動生成的ID。 大功告成!我們的數據庫準備就緒。現在,讓我們用Express創建一個API來獲取這些視頻文檔。 ### 第2步:通過Express創建1個API 在這個步驟中,你將學習到關于Node模塊系統,Express路由和用Monk從MongoDB中獲取數據。 用你最喜歡的代碼編輯器在項目根目錄中打開app.js。文件中第1部分包含了幾個?**require**函數調用。**require**方法是Node中內置方法之一,主要用來引用其它文件中定義的模塊: ~~~ var express = require('express'); var path = require('path'); var favicon = require('serve-favicon'); var logger = require('morgan'); var cookieParser = require('cookie-parser'); var bodyParser = require('body-parser'); ~~~ 第2部分引入了我們的路由模塊。1個路由模塊定義了1個或多個關聯的端點以及對應的處理器。在這個由Express Generator生成的示例應用中,我們有兩個路由模塊:?**index**?和?**users**: ~~~ var routes = require('./routes/index'); var users = require('./routes/users'); ~~~ 讓我們看一看其中的一個路由模塊,打開?**rutes>index.js**。你將看到以下代碼: ~~~ var express = require('express'); var router = express.Router(); /* GET home page. */ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); module.exports = router; ~~~ 來分析一下這段代碼。 在第1行,我們在當前模塊引用了Express。當使用?**require**方法時,依賴于目標模塊是怎樣實現的,**require**方法可能返回1個方法或者對象。在這個例子中,這個?**express**變量是1個對象。它提供了一個叫做?**Router**的方法,我們在第2行就調用了這個方法。用來訪問Express中的路由對象。我們用1個路由來定義我們應用中的端點。我們在這些端點中接收請求。每個端點將會被關聯到1個路由處理器,處理器負責處理在端點中收到的請求。 現在看下一行中路由配置的示例。 ~~~ router.get('/', function(req, res, next) { res.render('index', { title: 'Express' }); }); ~~~ 我們使用路由中定義的?**get**方法來定義1個路由和它的處理器。第1個參數是這個端點;在這里,’/‘代表網站的根路徑或者主頁。第2個參數就是路由的處理器。 在Express中,所有的路由處理器都有一個同樣的簽名。第1個參數是請求對象,第2個參數是響應對象,第3個參數是當前鏈中的下一個處理器。Express使用的中間件函數采用鏈式調用的方式。當Express使用中間件時,有時候你可能需要在當前鏈中調用下一個中間件。你可以通過?**next**?變量實現。但是當我們在處理路由的時候,我們幾乎不需要這個操作,所以這里你可以安全地刪除?**next**?變量。 現在看一下這個函數體。?**res**?變量代表了響應對象。這個響應對象自帶了一些有用的函數。 * **render**:用來渲染視圖 * **send**:用來發送文本內容到客戶端 * **json**:發送json對象到客戶端 * **redirect**:重定向客戶端到另一個地址 在這里,我們渲染index視圖,這個視圖在?**views>index.jade**中已經定義了。 這就是一個路由的基礎結構。我們現在需要為我們的視頻創建一個RESTful API。我們將在1個類似**/api/videos**的端點中展示我們的視頻。 在?**routes**?目錄下創建1個新的路由模塊叫做?**videos.js**?,然后在文件輸入以下代碼,之后我會對這段代碼進行逐行講解。 ~~~ var express = require('express'); var router = express.Router(); var monk = require('monk'); var db = monk('localhost:27017/vidzy'); router.get('/', function(req, res) { var collection = db.get('videos'); collection.find({}, function(err, videos){ if (err) throw err; res.json(videos); }); }); module.exports = router; ~~~ 頭兩行和之前的一樣,我們引入了Express然后獲取路由對象。 然后我們引入了Monk,一個用來持久化MongoDB數據的模塊。另一個叫做?**Mongoose**?的模塊也可以達到這個效果。但是在本教程中,我更傾向用Monk。 之前曾經提過,?**require**?方法會根據模塊的實現方式來返回一個對象或者方法。當我們引入Monk的時候得到的是一個方法而不是對象。所以?**monk**?變量是一個我們通過調用來訪問數據庫的方法。 ~~~ var db = monk('localhost:27017/vidzy'); ~~~ 現在來實現我們路由處理器的邏輯。 ~~~ function(req, res) { var collection = db.get('videos'); collection.find({}, function(err, videos){ if (err) throw err; res.json(videos); }); } ~~~ 首先我們調用?**db**?對象的?**get**?方法,傳入集合的名稱(**video**)。它將返回一個集合對象。這個集合對象提供了一個數字和一些方法來操作集合上的文檔。 * inser * find * findOne * update * remove 這里我們使用?**find**?方法來獲取集合中的所有視頻。這個方法的第1個參數是一個用來過濾的對象。由于我們需要查詢所有視頻,我們傳入一個空對象。第2個參數是一個回調方法,從數據庫返回結果之后調用。這個方法遵循Node回調函數的標準協議模式——“錯誤優先”。在這個模式中,回調函數的第1個參數是一個錯誤對象,第2個參數才是返回結果。當你開發更多的Node應用的時候,你將發現更多的這種回調模式。 在這種回調中,我們首先檢查?**err**?對象是否被設置。如果在查詢視頻文檔中沒有出現錯誤,?**err**?的值是**null**;否則它將被設置。我們拋出?**err**?來中斷程序的執行并且告知用戶。如果沒有錯誤,就通過調用**res.json**?簡單地返回一個JSON對象。 看最后一行 ~~~ module.exports = router; ~~~ 這一行定義了一個對象返回值,當別的模塊引用這個模塊時我們將返回這個對象。在這種情況下我們返回路由對象給Express。這個模塊的主要功能就是獲取路由并注冊一些路由配置并返回。 現在還剩下一個小步驟。雖然寫了一個模塊來為我們的新API配置路由信息,但是我們并沒有調用它。再次打開?**app.js**?然后靠近頂部查找以下代碼: ~~~ var routes = require('./routes/index'); var users = require('./routes/users'); ~~~ 通過以下代碼將我們的路由模塊引入到應用程序模塊。添加下面這行代碼。 ~~~ var videos = require('./routes/videos'); ~~~ 將新模塊復制給?**videos**變量供之后使用。將?**app.js**?往下滾動一點然后找到下面代碼: ~~~ app.use('/', routes); app.use('/users', users); ~~~ 添加一行代碼: ~~~ app.use('/api/videos', videos); ~~~ 這一行代碼的作用就是讓?**videos**?模塊給任何以?**/api/vides**開頭的路由使用。 現在來測試一下我們的API。打開瀏覽器輸入地址?[http://localhost:3000/api/videos](http://localhost:3000/api/videos)?。你將看到以下JSON對象 [![](https://box.kancloud.cn/2015-11-20_564e9a5662814.png)](http://yalishizhude.github.io/2015/11/02/mean-3/json.png) 我使用了?**JSONView**?Chrome插件來高亮顯示JSON對象。 接下來幾步我們將使用Angular來構建前端代碼展示這些視頻。 ### 第3步:添加Angular 在這一步中,你將學習到Angular的基礎知識。如果你已經熟悉Angular,可以跳過這些描述,但是請拷貝這些代碼到項目中。 Angular是一個用來構建單頁應用(SPA)的非常流行的前端框架。它提供了路由,依賴注入,測試和MVC的結構實現的代碼解耦。如果這些聽起來太極客了,也不用擔心。這一章將帶你了解這些特性。 首先,需要添加Angular腳本到應用中。打開?**views>layout.jad**?添加以下3個腳本文件引用在?**head**的末尾(一般考慮性能會放在body標簽的末端)。 ~~~ script(src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular.js') script(src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular-resource.js') script(src='https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.5/angular-route.js') ~~~ 確保他們的縮進空格數相等,因為jad對縮進空格非常敏感。Express Generator生成Jade視圖的時候將會把兩個空格當做縮進。所以你需要遵循同樣的縮進并且不能省略。否則將會報錯。 這些是什么腳本?第1個是Angular框架的主腳本,第2個是用來調用RESTful APIs,第3個是用來管理路由的。通過路由來定義應用導航對應展示的頁面。 下一步,在?**public>javascripts**?路徑下創建一個名為?**vidzy.js**的文件,在里面編寫javascript代碼。 在Angular腳本之后,添加?**vidzy.js**?引用 ~~~ script(src='/javascripts/vidzy.js') ~~~ 請再次確保縮進空格數一致。 現在主要腳本已經引入,可以添加Angular到我們的應用了。添加Angular包括兩步: * 第1步,在HTML元素上添加?**ng-app**?屬性。當Angular腳本加載完時,它將在DOM中找到這個屬性然后掛載應用程序。 * 第2步,為應用創建一個Angular模塊。Angular應用通常由1個或者多個模塊構成。這個簡單的應用,你只需要一個?**app**?模塊。但是隨著應用的擴展,為了提升代碼結構和可維護性,你可能需要劃分不同的功能到不同的模塊。 打開?**layout.jade**?添加?**ng-app**?到html元素。 ~~~ doctype html html(ng-app='Vidzy') ~~~ 在Jade中,我們使用括號來為HTML標簽添加屬性。當該行被Jade模板引擎渲染時,我們將獲取以下HTML元素 ~~~ <html ng-app=’Vidzy’> ~~~ 我們給ng-app設置的值就是應用的名稱。現在我們需要創建這個模塊。 打開 vidzy.js輸入以下代碼: ~~~ var app = angular.module('Vidzy', []); ~~~ **Angular**現在是一個全局可用的對象,?**module**?方法可以用來定義一個新的模塊或者獲取已有模塊的引用。第1個參數和我們之前在?**ng-app**?中定義的值一致。第2個參數是一個依賴數組。這里傳入一個空數組來聲明當前模塊不依賴任何其他模塊。 我們做這些就是為了將Angular掛載到我們的應用上。接下來我們將重構首頁,使用Angular來展示數據庫中所有的視頻。 ### 第4步:用Angular重構首頁 Express Generator生成的默認項目使用了Jade做為視圖引擎。這些Jade視圖在服務端被解析和渲染成HTML然后返回給客戶端。這就是很多網頁框架如何工作的。但是在本應用中,我們將使用一種不同的構建風格。我們將返回JSON給客戶端(Angular)來渲染視圖來替代返回HTML。下面說一說這樣做的原因。 開始的時候,在本章關于“什么時候使用Node”中,我提到一種通用的場景:Node擅長在文檔數據庫上構建基于RESTful APIs的應用。通過這種架構,我們不必把時間花在數據轉換上。我們存儲JSON對象在Mongo中,通過RESTful API導出它們并且直接在客戶端進行展示(通過Angular)。JSON就是Javascript和MongoDB的原生對像。所以用它來貫穿整個技術棧,我們就減少了匹配和轉換數據的工作。通過從API返回JSON對象然后在客戶端渲染視圖,來提高性能和可擴展性。因為服務器的CPU將不會被浪費在為大量并發用戶渲染視圖上。另外,我們可以重用同樣的API去構建另一個客戶端,例如Iphone和Android app。 在這一步中,我們將用Angular視圖來取代首頁上默認的Jade視圖。 在?**public**?下創建一個新的叫做?**partials**?的文件夾用來存儲視圖文件。在這個文件夾下創建一個新的文件?**home.html**,在文件中輸入 ~~~ <h1>Home Page</h1> ~~~ 現在,我們需要告訴Angular當跳轉到這個首頁時渲染這個視圖。我們通過Angular路由來實現這個功能。 在?**vidzy.js**?中,改變?**app**?模塊的聲明如下: ~~~ var app = angular.module('Vidzy', ['ngRoute']); ~~~ 在依賴數組中我添加了一個?**ngRoute**?的引用。?**ngRoute**?是構建Angular模塊中用來配置路由的。 在?**app**?模塊聲明中寫下如下代碼: ~~~ app.config(['$routeProvider', function($routeProvider){ $routeProvider .when('/', { templateUrl: 'partials/home.html' }) .otherwise({ redirectTo: '/' }); }]); ~~~ 讓我來為你講解一下。我們使用?**app**?模塊的?**config**?方法來為我們的應用提供配置。這個代碼將在Angular檢測到?**ng-app**?并且視圖啟動的時候執行。?**config**?方法的參數是一個數組: ~~~ app.config([]); ~~~ 這個數組可以有0個或更多的依賴以及一個函數來實現配置邏輯。這里我們有一個依賴**$routeProvider**,這是一個在?**ngRoute**?中國定義的模塊。這就是我們修改app模塊聲明來依賴**ngRoute**?的原因。配置函數接收?**$routeProvider**?作為一個參數 ~~~ app.config(['$routeProvider', function($routeProvider){ }]); ~~~ 在我們的配置函數中,我們使用?**$routeProvider**?的?**when**?方法來配置路由。 ~~~ $routeProvider .when('/', { templateUrl: 'partials/home.html' }) ~~~ 第1個參數(‘/‘)是相對路徑。第2個參數是一個對象,定義了路徑對應的視圖(通過?**templateUrl**)。我們可以多次調用?**when**?方法,每次定義個不同的路由。最后,我們使用?**otherwise**?方法來聲明如果用戶瀏覽其他URLs,將被重定向到根路徑(‘/‘)。 現在還差一點點。我們只需要做一些小小的改動來時使Jade視圖映射到首頁。打開?**views>index.jade**然后改變文件的內容: ~~~ extends layout block content div(ng-view) ~~~ 我溢出了視圖中之前的內容(Welcom to Express)添加了一個帶有?**ng-view**?的?**div**。這個屬性告訴Angular在當前dom下渲染視圖。通過這個設置,用戶首次進入主頁時,Jade視圖將會在服務端渲染并且返回給客戶端。在實際項目中,站點視圖將有基礎的模板()例如導航條,logo等)。它也有一個內容區(通過?**ng-view**?聲明)由Angular來渲染視圖。當用戶通過應用來訪問頁面時,Angular將用不同的Angular視圖來替換內容區域。這樣避免了整個頁面的刷新從而帶來了更好的效果。這就是我們稱這些應用為單頁應用的原因:從本質上說只有一個頁面被完整地從服務器下載,然后其他子頁面只是簡單的用來替換內容區。 注意:我必須再一次強調Jade對空格符非常敏感。在同一個視圖中你不能混淆空格和tab鍵的縮進。Express Genrator默認生成的Jade視圖用兩個空格鍵來縮進。確保添加兩個空格在?**div(ng-view)**?前面,否則你運行時將報錯。 在最后一步之前讓我們快速測試一下。回到你的瀏覽器,輸入[http://localhost:3000.你將看見我們通過Angular構建的新首頁](http://localhost:3000.%E4%BD%A0%E5%B0%86%E7%9C%8B%E8%A7%81%E6%88%91%E4%BB%AC%E9%80%9A%E8%BF%87Angular%E6%9E%84%E5%BB%BA%E7%9A%84%E6%96%B0%E9%A6%96%E9%A1%B5/) [![](https://box.kancloud.cn/2015-11-20_564e9a567cbbb.png)](http://yalishizhude.github.io/2015/11/02/mean-3/home.png) ### 第5步:實現控制器 首頁已經被正確地掛載了。現在需要從服務端獲取視頻并渲染到首頁。在Angular或其他MVC中,這是控制器的主要職責。視圖只負責展現響應的數據,控制器負責為視圖獲取數據或者處理視圖中發生的事件。 現在為我們的首頁視圖創建一個控制器。打開?**vidzy.js**?并且改變?**app**?模塊的聲明: ~~~ var app = angular.module('Vidzy', ['ngResource', 'ngRoute']); ~~~ 現在我們依賴兩個模塊:ngResource,用來調用RESTful APIs和ngRoute來管理路由。 接下來在文件末尾輸入以下代碼來創建一個控制器: ~~~ app.controller('HomeCtrl', ['$scope', '$resource', function($scope, $resource){ }]); ~~~ 這里我們使用?**app**?模塊提供的?**controller**?方法來定義一個新的控制器。 第1個參數是1個字符串,用來定義控制器的名稱。按照管理,我們通常在Angular控制器名末尾添加**Ctrl**。 第2個參數是數組。這個數組可以引用0個或更多的字符串,每個代表了1個控制器的依賴。這里定義了依賴?**$scope**?和?**resource**。這些都是Angular的內部服務,所以她們都有一個前綴”$”。**$scope**用來傳遞數據給視圖,**$resource**用來調用RESTful API。數組中最后一個對象是函數,這個函數就是控制器的主體。在這個例子中,我們的函數獲取了兩個參數?**$scope**?和?**$resource**?。因為我們依賴了**$scope**?和?**$resource**?在函數聲明之前。 讓我們實現控制器的主體部分。在控制器函數內部,輸入以下代碼 ~~~ app.controller('HomeCtrl', ['$scope', '$resource', function($scope, $resource){ var Videos = $resource('/api/videos'); Videos.query(function(videos){ $scope.videos = videos; }); }]); ~~~ 這里我們調用?**$resouce**?方法通過給定的API端點(/api/videos)來獲取一個資源對象。這個對象將提供一些方法來訪問我們的?**API**。我們用?**query**?方法來獲取所有視頻。?**query**?方法在查詢結果就緒后將得到一個回調函數。這個函數將獲得我們從服務端獲取的視頻。最后我們將視頻存儲到?**$scope**對象中然后渲染到視圖中。記住?**$scope**?就是視圖和控制器之間的膠水。 現在我們需要改變視圖來渲染視圖中的列表。打開?**partials>home.html**?然后輸入代碼: ~~~ <ul> <li ng-repeat='video in videos' ng-bind="video.title"></li> </ul> ~~~ 我們用ul和li來渲染視頻列表。li標簽有一個Angular定義的屬性叫做?**ng-repeat**。這些屬性在Angular中叫做指令,用來為HTML元素添加一些行為。**ng-repeat**屬性的值是一個類似js中foreach的表達式。**videos**變量是我們之前在?**$scope**中定義的屬性。**video in videos**表示一次從數組中獲取一個video。所以li元素將會被數組中的video對象重復渲染。我們用雙花括號來編寫表達式。這里我們簡單的渲染video對象中的title屬性在li標簽中。 最后我們需要將這個控制器注冊到路由上。回到?**vidzy.js**,改變路由配置 ~~~ .when('/', { templateUrl: 'partials/home.html', controller: 'HomeCtrl' }) ~~~ 完成了這些步驟,當用戶進入網站根路徑時,Angular將展示?**partials/home.html**?并且為它添加**HomeCtrl**?控制器。 回到瀏覽器并刷新首頁。你將看到視頻列表。 [![](https://box.kancloud.cn/2015-11-20_564e9a569153d.png)](http://yalishizhude.github.io/2015/11/02/mean-3/list.png) 如果你是一個Angular新手并且還有些困惑,沒關系,在接下來的章節中我們將繼續使用更多的Angular控制器,視圖和路由。 總結下,本章節中,為我們的應用添加了第一個功能。我們開始用RoboMongo來連接MongoDB。我們創建了一個數據庫然后填充了一些視頻文檔。然后我們創建了一個API用Express來導出視頻列表。最后,我們添加Angular到應用中來調用API渲染視頻列表。 在下一節中,我們將添加另一個功能到應用中。 這一部分的內容很多,翻譯花費了很多時間。原文作者寫教程的時候確實是很用心的,這也是我答應作者翻譯這篇教程的一個原因。如果想看更多教程可以去作者的官網,如果覺得這篇教程不錯,還請點個贊~3q~
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看