LogoLogo
Navigation
Advanced Javascript
Advanced Javascript
  • 😆Attribute Starts With Selector [name^="value"] (ok)
  • 🥹 Tìm hiểu về Map và Set trong javascript (ok)
  • 🫢 The Array.from() method returns an array from any iterable object. (ok)
  • 😍localeCompare() method compares two strings return sort order -1, 1,0 (for before, after, or equal)
  • 😍JavaScript Array some() method returns true (and stops) if the function returns true() (ok)
  • Add key value pair to all objects in array (ok)
  • 🥸Làm một sider tuyệt đẹp "Timed-Cards-Opening"
  • 🥸Scroll animations! How to add a flowing path like the Lusion site with SVG and Javascript (ok)
  • Chia sẽ code plugin tạo thời gian chờ tải cho nút download
  • 😛jQuery 1.9 .live,.delegate,.on is not a function (ok)
  • 😁Importing CSS Breakpoints Into JavaScript (ok)
  • The matchMedia() method returns a MediaQueryList with the results from the query. (ok)
  • Collect nhiều sách pdf (ok)
  • 😁Check device Agent chrome, firefox ... (ok)
  • === START Three.js and TypeScript ===
  • Setup Development Environment (ok)
  • === END Three.js and TypeScript ===
  • === START THREE.JS ===
  • 🥳Fundamentals - three.js manual
    • Light trong Three.js
  • == Start Nguyên tắc cơ bản ===
  • Nguyên tắc cơ bản
  • Thiết kế đáp ứng
  • nguyên thủy
  • 😅Điều chỉnh camera (ok)
  • 😅Điều chỉnh scale
  • 🥲Xử lý màn hình HD-DPI
  • 😃So sánh Mesh với Object3D
  • 😅Trục AxesHelper
  • 😅Tạo GridHelper
  • 😆MeshBasic, MeshLambert, MeshPhong, MeshToon, MeshStandard, MeshPhysical, Shader, RawShader
  • == End Nguyên tắc cơ bản ===
  • 🥰Bài viết mẫu thự hành tọa độ, quay (ok)
  • Giới thiệu HTML5 Canvas
  • Bài 1: Làm quen với môi trường 3D của ThreeJS
  • Bài 2: Dịch chuyển đối tượng 3D - Controls
  • Bài 3: makeup
  • Bài 4: Models loader
  • 😁Những trang học three.js
  • Source Code Example
  • === END THREE.JS ===
  • === START WebGL ===
  • 😇Trang học WebGL && Shador
  • 😅Tìm hiểu về OpenGL ES 2.0
  • Tìm hiểu về WebGL phần 1: thư viện đồ họa web.
  • Tìm hiểu WebGL Phần 2: Đi sâu vào cách code WebGL appication
  • Tìm hiểu WebGL Phần 3: Đi sau vào cách code WebGL appication - các ví dụ
  • Tìm hiểu WebGL Phần 4: Các ví dụ.
  • === END WebGL ===
  • 😃Getting started with systemjs full (ok)
  • Đọc thêm bài này Mô-đun ECMAScript và khả năng tương thích trình duyệt (ok)
  • 😖Thư viện chặn truy cập vào Devtool (ok)
  • === START JAVASCRIPT Vanila ===
  • 😄Làm cách nào để ngăn sự kiện onclick của cha mẹ kích hoạt khi nhấp vào con parent, child ? (ok)
  • 😁Bootstrap 5 - multi item carousel (ok)
  • Three dots ( … ) in JavaScript
  • "... Three Dots" đã thay đổi javascript như thếnào ?
  • Array-like objects, Chuyển đối tượng arguments thành array (ok)
  • 😇Making a short alias for document.querySelectorAll (ok)
  • JavasScript Siblings (ok)
  • JavaScript Modules Full (ok)
  • JavaScript select Element (ok)
  • === END JAVASCRIPT Vanila ===
  • Sử dụng async, await, bất đồng bộ lấy dữ liệu Pagination, sử dụng Deferred 👌 phần 2 (ok)
  • how to use multiple ternary operator in javascript, ?:, ?? (ok)
  • 😅[DATETIMEPICKER] jQuery Plugin Date and Time Picke Full (ok)
  • === START tutorial HYPERAPP ==
  • [HYPERAPP] Hyperapp - JavaScript micro-framework chỉ 1kB (ok)
  • [HYPERAPP] hyperapp-tutorial-step-1 (ok)
  • [HYPERAPP] hyperapp-tutorial-step-2 (ok)
  • [HYPERAPP] hyperapp-tutorial-step-3 (ok)
  • [HYPERAPP] hyperapp-tutorial-step-4 (ok)
  • === END tutorial HYPERAPP ==
  • Free and Open Source Web Builder Framework
  • 😁How to recursively fetch data from paginated API then combine into one array (ok)
  • 😆Create a form with dom with nested tags, Wrapping a set of DOM elements using JavaScript (ok)
  • 😇Array find, Tìm phần tử đầu tiên thỏa mãn điều kiện (ok)
  • 😁Array find, Tìm phần tử cuối cùng thỏa mãn điều kiện (ok)
  • Cách tích hợp bộ lọc select chọn nhanh Tỉnh, Thành & Quận, Huyện, districts, provinces (ok)
  • object with methods, you can simply call a method from the object returned. (ok)
  • Portfolio, Filter, Gallery, Tabmenu (ok)
  • JavaScript chạy bất đồng bộ như thế nào?, Microtask ,Macrotask, queueMicrotask bài viết hay (ok)
  • 😋Learn prototypejs 😒😒😒
  • === START JavaScript chuyên sâu ===
  • [JavaScript chuyên sâu] Higher order function trong JavaScript - phần 1 (ok)
  • [JavaScript chuyên sâu] - Higher order function - phần 2: closure, currying, callback
  • [JavaScript chuyên sâu] - So sánh Constructor Function và Factory Function
  • [JavaScript chuyên sâu] - 5 vai trò của Function: function, object, property, callback, constructor
  • [JavaScript chuyên sâu] : Đồng bộ và bất đồng bộ của JavaScript - phần 1: Callback
  • [JavaScript chuyên sâu]: Từ hàm IIFE tới Module Pattern
    • 😍IIFE=>Immediately Invoked Function Expression=>khởi tạo function & chạy ngay, import, export như nào
  • Tìm hiểu về Higher-Order Functions trong JavaScript
  • === END JavaScript chuyên sâu ===
  • QR-Card (ok)
  • === START DATATABLE ===
  • [DATATABLE] bộ lọc sử dụng các thẻ bên trong td matter.vn (ok)
  • 😁[DATATABLE] JQuery Datatables Editor - Alternative to the official one (ok)
  • Example: Datatables Add Edit Delete with Ajax, PHP & MySQL (ok)
  • [DATATABLE] fixedColumns, DataTable, Left and right fixed columns (ok)
  • [DATATABLE] Sử dụng thư viện dataTables.bootstrap.min.js && dataTables.bootstrap.min.js (ok)
  • [DATATABLE] DataTables.net with DataTableQueryBuilder sample input filter (ok)
  • [DATATABLE] How to use Tabledit plugin with jQuery Datatable in PHP Ajax (ok)
  • [DATATABLE] DataTables Custom Filter Demo (ok)
  • [DATATABLE] Datatable multiple checkbox demo (ok)
  • [DATATABLE] HTML5 export buttons (ok)
  • [DATATABLE] CodePen Home DataTable 2 Card view (ok)
  • [DATATABLE] DataTables - Column Search (ok)
  • [DATATABLE] CodePen Home dataTables conditional row and cell styling (ok)
  • [DATATABLE] DataTables example of styling Excel export(ok)
  • === END DATATABLE ===
  • 😅Bất ngờ về sử dụng Window History full 1 (ok)
  • 😁Bất ngờ về sử dụng Window History full 2, window.history.scrollRestoration,history.replaceState(ok)
  • workingHoursBetweenTimes, tính giờ làm việc, giờ làm thêm (ok)
  • 😅addDataToArray, cộng mảng đối tượng với điều kiện key == (ok)
  • You can get the number of days in a specified month (ok)
  • Lấy giá trị khác nhau đầu tiên, cuối trong một mảng Object (ok)
  • swiperjs.com (ok)
    • Swiper Slider (ok)
  • Một số cách viết ngắn gọn code trong JS phần 1 (ok)
  • Một số cách viết ngắn gọn code trong JS phần 2 (ok)
  • literal javascript, php (ok)
  • Bài toán kinh điển sử dụng three dots lấy tất cả các key của object, key same, plus (ok)
  • convert object to array javascript (ok)
  • ==== Start Google Sheet ====
  • Kintone width Appscript (ok)
  • [GOOGLE-SHEETS] Buttons in Google Sheets
  • [GOOGLE-SHEETS] thực hiện chuyển dữ liệu sang bản khác (ok)
  • [GOOGLE-SHEETS] method getRange (ok)
  • [GOOGLE-SHEETS] method getRange (ok)
  • Bài 1: Khai Báo Biến và Đọc Ghi Ô – Dải Ô (Cell / Range)
  • Bài 2: Các Hàm Lấy Giá Trị và Đặt Giá Trị Dải Ô getRange – getValues – setValues
  • Bài 3: Copy và Di Chuyển Dải Ô Sang Sheet khác
  • Bài 4: Vòng Lặp For
  • Bài 5: Di chuyển dòng từ Sheet này sang Sheet khác
  • [Help] – Chuyển Cột Sang Hàng (bỏ ô trống) (ok)
  • Bài 6: Câu lệnh điều kiện IF (ok)
  • Bài 7: Giới thiệu các Trigger App Script – onEdit onOpen
  • [Help] – Form nhập liệu đơn giản
  • Bài 8: Hộp thoại Dialog / Popup
  • Bài 9: Ghi công thức Google Sheet vào ô
  • Bài 10: Đọc Ghi Mảng (Array) App Script
  • Bài 11: Tạo xác thực dữ liệu phụ thuộc
  • Lấy Email người dùng đang hoạt động trên Google Sheet – getActiveUser
  • Bài 12: Liên kết Google Form – Sheet – Apps Script
  • [Series Email] Bài 1: Gửi Email bằng Apps Script cơ bản
  • [Series Email] Bài 2: Gửi Email Đính Kèm File – Hình Ảnh
  • [Series Email] Bài 3: Gửi Email Cho Danh Sách Nhập Vào Từ Google Sheet
  • Addon Email All in One | Email AI1 | RA MẮT BẢN THỬ NGHIỆM
  • [Series Email] Bài 4: Gửi Email Bcc Cho Danh Sách Nhập Vào Từ Google Sheet
  • [Series Email] Bài 5: Tạo Hộp Thoại Xem Email Trước Khi Gửi
  • [Series Email] Bài 6: Gửi Email Theo Template Cho Sẵn
  • [Series Email] Bài 7: Gửi Email Xác Nhận Điền Form (Email Confirmation)
  • [Series Email] Bài 8: Hẹn Giờ Gửi Email
  • SpreadsheetApp
  • Giới hạn các Service trong Apps Script
  • [CF] Lọc dải ô bao gồm dải ô khác
  • Cách lưu trữ trong Google Apps Script – PropertiesService
  • [CF] Custom Function Google Sheets là gì và Cách ‘cài đặt’
  • [CF] Tìm Ô – Có Giá Trị – Cuối Cùng Trong Cột – Google Sheets
  • [CF] Đếm số lần xuất hiện kí tự trong dải ô Google Sheets
  • [CF] Lọc dải ô không bao gồm
  • ==== End Google Sheet ====
  • [REDUCE] JavaScript Array reduce()
  • Merge object and split array by size, Trộn object và tách array theo size (ok)
  • Đặt điều kiện mới load js (ok)
  • Calculate working days between two dates in Javascript excepts holidays (ok)
  • Remove everything after a certain character remove replace (ok)
  • CodePen Home Image zoom on hover - auto run - view full (ok)
  • ======== Start Slider Revolution =======
  • How to start (ok)
  • Revolution Lightbox tham khảo
  • Mẫu và thực viện để thực hành (ok)
  • Tài liệu Slider Revolution Jquery 2.0 (ok)
  • Tài liệu Slider Revolution Jquery 4.1.2 (ok)
  • ======== End Slider Revolution =======
  • jQuery click / toggle between two functions (ok)
  • [TEXT ANIMATION] làm hiệu ứng chữ dòng trên xuất hiện trước rồi mới đến dòng dưới (ok)
  • Phát hiện phần tử xuất hiện ở màn hình, Detect element appearing on screen, view (ok)
  • what does !function in Javascript mean? (ok)
  • [WEBPACK] Một cách phân biệt khi bundle ra es5 hay es6 một ví dụ sử dụng webpack (ok)
  • Javascript Self Invoking Functions (ok)
  • ====== Start Convert ES5 class to ES6 class ====
  • VS Code tips: Convert ES5 class to ES6 class code action (ok)
  • ====== End Convert ES5 class to ES6 class ====
  • Get Substring between two characters using javascript (ok)
  • add Html Table rows data into JSON array Object (ok)
  • lightGallery, lightgalleryjs, Lightbox (ok)
  • same height (ok)
  • Hình ảnh :(
  • ============ Start serialize =============
  • jQuery serialize() Method (ok)
  • serialize width php mysql (ok)
  • serialize, serializeObject, serializeArray (ok)
  • How to access jQuery serialized data? (ok)
  • ============ End serialize =============
  • Sử dụng addQueryVar để thêm vào đường dẫn ajax (ok)
  • Cách tích hợp captcha style2.track360.xyz (ok)
  • Simple JavaScript Captcha Example (Client Side Captcha)
  • 😍Đoạn mã sử dụng translate.google.com (ok)
  • ========== Start [MultiLang] ===========
  • [MultiLang] MultiLang.js (ok)
  • [MultiLang] Localizing JavaScript apps with jQuery.i18n (ok) (full)
  • [MultiLang] jQuery i18n những điều nên biết (ok)
  • [MultiLang] How to Create a Multilingual Application using JavaScript
  • [MultiLang] Build multiple language website using jQuery and JSON based methods (ok)
  • [MultiLang] Switch Different Languages On The Webpage - jQuery multilang (ok)
  • [MultiLang] jquery-multilang (ok)
  • ========== End [MultiLang] ===========
  • [MINICOLORS] jquery.minicolors (ok)
  • jQuery - addClass ACTIVE--> set timeout --> cycle (ok)(online.vinmec.com)
  • WP Mapbox GL JS Settings key (ok)
  • Xử lý ảnh thiếu thuộc tính title, alt trên style2.track360.xyz (ok)
  • Register your schema (ok)
  • ========= Start Learn Graphql Website =======
  • 1. Query and Mutation types
  • ========= End Learn Graphql Website =======
  • [GRAPHQL] Tạo Database với Mysql (ok)
  • KẾT NỐI VỚI MYSQL – NODEJS – 05
  • 😍Quick start graphql (ok)
  • Hướng dẫn bắt đầu GraphQL với Node.js (Phần 1)
  • Hướng dẫn bắt đầu GraphQL với Node.js (Phần 2)
  • Cách bắt đầu với ứng dụng GraphQL, React, Apollo Client và Apollo Server
  • [Fullstack] Xây dựng forum bằng GraphQL, React, Apollo và Prisma - Part 1 (Application Introduction
  • 😍[Fullstack] Xây dựng forum bằng GraphQL, React, Apollo và Prisma - Part 2 (Backend - Project Setup a
  • [Fullstack] Xây dựng forum bằng GraphQL, React, Apollo và Prisma - Part 3 (Backend - Simple Mutation
  • [Fullstack] Xây dựng forum bằng GraphQL, React, Apollo và Prisma - Part 4 (Backend - Connect to Data
  • 😍Prisma Crud Full
    • 🥰Sử dụng kết hợp prisma.io với wordpress như nào?
    • [ERROR] gặp lỗi TypeError: Do not know how to serialize a BigInt (ok)
    • 😍Migrate MongoDB to MySQL using Prism Key Differences (ok)
  • Setting Up Prisma with MySQL: A Step-by-Step Guid
  • Tìm hiểu GraphQL, Xây dựng 1 GraphQL server với prisma
  • 🥹Đã có bài viết về sqlite, sqlite3 đầy đủ (ok)
  • 😍Querying Sequelize Full link sequelize.org (ok)
  • 😁Sqlite Sequelize Example (ok)
  • 😍CRUD with React and GraphQL Mysql (ok)
  • 😍A GraphQL Sqlite, sequelize Full (ok)
  • GraphQL in practice - Part 1: Xây dựng GraphQL server với Apollo Server, ExpressJS và MongoDB
  • GraphQL in practice - Part 2: Tạo ứng dụng GraphQL với Apollo Client và React
  • GraphQL in practice - Part 2: Tạo ứng dụng GraphQL với Apollo Client và React
  • TÌm hiểu về GraphQL
  • Cùng tìm hiểu về GraphQL
  • Simple Guidance For You In GraphQL
  • [GRAPHQL] Get started with Apollo Server (ok)
  • [GRAPHQL] Schema basics (ok)
  • [GRAPHQL] Subscriptions (ok)
  • [GRAPHQL] Unions and interfaces (ok)
  • Tham khảo: https://www.howtographql.com
  • Tìm hiểu GraphQL: Các khái niệm cơ bản (ok)
  • GraphQL Và Ưu Điểm Nổi Bật So Với Rest API?
  • Xây dựng server GraphQL với NodeJS (ok)
  • Tìm hiểu GraphQL
  • Xây dựng GraphQL server với Node.js
  • Ví dụ Tạo Restfull API - CRUD đơn giản với NodeJS, GraphQL (ok)
  • Sequelize with Node, Express & Mysql and it’s setup (ok)
  • Sequelize in Nodejs Part I
  • Sequelize in Nodejs Part II
  • Videos NodeJS + MySQL Database
  • NodeJS – Lưu trữ dữ liệu trên MySQL với Sequelize
  • Exploring The Node.js With MySQL Example Using Sequelize & Express
  • Tạo model, migration, seeds với Sequelize
  • Sử dụng passport với sequelize và MySQL
  • Tạo model, migration, seeds với Sequelize
  • GraphQL là gì? Bắt đầu với GraphQL
  • Xây dựng API sử dụng Laravel và GraphQL
  • How To Connect To MySql Database Using Sequlize In Express (Node) Application
  • Node.js MySQL Tutorial
  • Node.js Rest APIs example with Express, Sequelize & MySQL
  • Getting Started with Node, Express and Mysql Using Sequelize
  • [GRAPHQL] GraphQL – Công nghệ mới cho web developer
  • GraphQL là gì? Tìm hiểu về GraphQL (ok)
  • [GRAPHQL] Cùng tìm hiểu về GraphQL
  • Điều gì ẩn chứa bên trong $.event???
  • ===== Start Put JavaScript Design Patterns Into Practice (Videos) ========
  • 2.1. The Factory Pattern (ok)
  • 3.1. The Publisher-Subscriber Pattern (ok)
  • 3.2. The Strategy Pattern (ok)
  • Rời phần thử khỏi mảng sử dụng filter (ok)
  • 3.3. The Observer Pattern (ok)
  • 3.4. The Chain of Responsibility Pattern (ok)
  • 3.5. The Mediator Pattern (ok)
  • 3.6. The Iterator Pattern (ok)
  • ===== End Put JavaScript Design Patterns Into Practice (Videos) ========
  • ========== Start RequireJS Tutorial =======
    • Sử dụng RequireJS và AMD để module hóa code JavaScript (ok)
  • 😍Trình duyệt không có require, nhưng Node.js thì có. Với Browserify để trình duyệt cũng có (ok)
  • Sử dụng Bower để quản lý các thư viện code trong Laravel (ok)
  • RequireJS - Environment Setup (ok)
  • RequireJS - Configuration (ok)
  • RequireJS - AMD Modules (ok)
  • RequireJS - Defining Function (cách sử dụng require rất lạ) (ok)
  • RequireJS - Optimizer (ok)
  • ========== End RequireJS Tutorial =======
  • ========== Start jQuery Ui ======
  • Jquery Datepicker select multiple date ranges in one calender, button Reset (ok)
  • Tạo chức năng tự động hoàn tất nhập liệu với thư viện jQuery UI Autocomplete (Phần 1) (ok)
  • Draggable Widget, Droppable Widget (ok)
  • jQuery drag and drop (kéo thả bằng jQuery)
  • jQuery drag full (ok)
  • jQuery drop full (ok)
  • jQuery Resizable full (ok)
  • Tablesorter full (ok)
  • Live search through table rows (ok)
  • Loại bỏ một số cột không tìm kiếm trong Tablesorter (ok)
  • jQuery Sortable full, tablesorter (ok)
  • jQuery Selectable full (ok)
  • jQuery UI Sortable Tutorial - Save Positions With Ajax & PHP & MySQL (ok)
  • jQuery Drag and Drop TODO List with PHP MySQL (ok)
  • ========== End jQuery Ui ======
  • [TUTORIAL] TRÍCH XUẤT THÔNG TIN TỪ WEBSITE VỚI HTML AGLITITY PACK
  • ======== Start handlebars js =======
  • Sử dụng handlebars js
  • Handlebars nhỏ nhưng có võ
  • ======== End handlebars js =======
  • ==== Start JavaScript Tutorial ====
  • JavaScript Introduction
  • What is JavaScript
  • JavaScript Essentials
  • JavaScript Variables
  • JavaScript Operators
  • JavaScript Conditionals
  • JavaScript Loops
  • JavaScript Built-in Types
  • JavaScript Objects
  • JS Advanced Objects
  • JavaScript Arrays
  • JavaScript Functions
  • JavaScript Function Objects
  • JavaScript JSON
  • JavaScript Regular Expressions
  • Bôi màu cho một ký tự đặc biệt và chuỗi @EsportsArcadia Regular Expression (ok)
  • JavaScript Reference
  • ==== End JavaScript Tutorial ====
  • 🧐===== Start JavaScript Design Patterns ==
  • JavaScript Design Patterns
  • JavaScript Design Patterns – Explained with Examples
  • Js design pattern doFactory master (ok)
  • Chapter 5: jQuery Patterns
  • JavaScript Design Patterns (ok)
  • Abstract Factory (ok)
  • Builder (ok)
  • Factory Method (ok)
  • Prototype (ok)
  • Singleton (ok)
  • Adapter ( ok)
  • Bridge (ok)
  • Composite (ok)
  • Decorator (ok)
  • Facade (ok)
  • Flyweight (ok)
  • Proxy (ok)
  • Chain of Responsibility (ok)
  • Command (ok)
  • Interpreter (ok)
  • Iterator (ok)
  • Mediator (ok)
  • Memento (ok)
  • Observer (ok)
  • State (ok)
  • Strategy (ok)
  • Template Method (ok)
  • Visitor (ok)
  • ===== End JavaScript Design Patterns ==
  • ======== Start Backbone.js Tutorial Videos ======
  • Backbone.js Tutorial - 1 - Installation.mp4 (ok)
  • Backbone.js Tutorial - 2 - Introduction to Models (ok)
  • Backbone.js Tutorial - 3 - Model Attributes (ok)
  • Backbone.js Tutorial - 4 - Model Change Events ( ok)
  • Backbone.js Tutorial - 6 - Introduction to Views (ok)
  • Backbone.js Tutorial - 7 - (Views) Differerence between el and $el (ok)
  • Backbone.js Tutorial - 8 - (Views) Creating New HTML Elements (ok)
  • Backbone.js Tutorial - 9 - (Views) Using the Render Function (ok)
  • Backbone.js Tutorial - 10 - (Views) Events (ok)
  • Backbone.js Tutorial - 11 - Introduction to Collections (ok)
  • Backbone.js Tutorial - 12 - (Collections) Adding and Removing Elements (ok)
  • Backbone.js Tutorial - 13 - (Collections) Modifying Elements
  • Backbone.js Tutorial - 14 - (Collections) Events (ok)
  • ======== End Backbone.js Tutorial Videos ======
  • ====== Start Learn backbone.js tutorial from scratch for beginners =====
  • Backbone :)
  • 1. Learn backbone.js tutorial from scratch(Part 2) Features and Working Principle of backbone.js
  • 2. Learn backbone.js tutorial from scratch for beginners(Part 4) About el and $el in Backbone.js
  • 3. Learn backbone.js tutorial from scratch for beginners(Part 5) Underscore Templates in Backbone.js
  • 4. Learn backbone.js tutorial from scratch for beginners (Part 7) Delegate Events in backbone.js
  • 5. Learn backbone.js tutorial from scratch for beginners(Part 8) Introduction of models in backbone.
  • 6. Learn backbone.js tutorial from scratch for beginners(Part 9) Pass Model data to backbone.js View
  • 7. Learn backbone.js tutorial from scratch for beginners(Part 10) Model data to underscore.js templ
  • 8. Learn backbone.js tutorial from scratch for beginners(Part 11) Head back to underscore.js symbol
  • 9. Learn backbone.js tutorial from scratch for beginners(Part 12) Model Events in backbone.js
  • 10. Learn backbone.js tutorial from scratch for beginners(Part 13) Model Validation in backbone.js
  • 11. Learn backbone.js tutorial from scratch for beginners(Part 14) Model Change Events in backbone.j
  • 12. Learn backbone.js tutorial from scratch for beginners(Part 15) More Model Events and listenTo ev
  • 13. Learn backbone.js tutorial from scratch for beginners(Part 16) Model Inheritance in backbone.js
  • 14. Learn backbone.js tutorial from scratch for beginners(Part 17) Collection in backbone js
  • 15. Learn backbone.js tutorial from scratch for beginners(Part 18) Collection Events in backbone.js
  • 16. Learn backbone.js tutorial from scratch for beginners(Part 19) Collection to underscore.js templ
  • 17. Learn backbone.js tutorial from scratch for beginners(Part 20) Underscore js Methods in backbone
  • 18. Learn backbone.js tutorial from scratch for beginners(Part 21) Routing in backbone.js
  • 19. Learn backbone.js tutorial from scratch for beginners(Part 22) Parameterized Routing in backbone
  • 20. Learn backbone.js tutorial from scratch for beginners(Part 23) Handlebars templates in backb
  • ====== End Learn backbone.js tutorial from scratch for beginners =====
  • Giới thiệu Backbone.js (ok)
  • Backbone.localStorage thay thế Backbone.sync lưu vào window.localStorage thay vì vào máy chủ (ok)
  • Một ví dụ full LocalStorage với BackBoneJS (ok)
  • ========== Start Backbonejs Php Mysql =============
  • Full code backbonejs php mysql (ok)
  • Giao diện html để thực hành từ đầu (ok)
  • Xây dựng giao diện (ok)
  • Thực hiện chức năng crud add (ok)
  • Phân tích để tạo giao diên http://localhost/gulp/#crud/new 1.0
  • Phân tích để tạo giao diên http://localhost/gulp/#crud/new 1.1
  • Phân tích để tạo giao diên http://localhost/create/#crud/index 2.0
  • Chức năng thêm dữ liệu http://localhost/create/#crud/new (ok)
  • Lấy dữ liệu ra trang http://localhost/create/#crud/index (ok)
  • Chức năng cập nhật dữ liệu http://localhost/create/#crud/1/edit (ok)
  • ========== End Backbonejs Php Mysql =============
  • JQuery-Template (ok)
  • Learning JavaScript Design Patterns P.1 (ok)
  • Learning JavaScript Design Patterns P.2 (ok)
  • Learning JavaScript Design Patterns P.3 (ok)
  • Singleton design pattern PHP (ok)
  • Singleton Pattern javascript (ok)
  • Factory Pattern (ok)
  • Decorator Pattern (ok)
  • Creational Pattern (ok)
  • Constructor Pattern (ok)
  • Singleton Pattern (ok)
  • Module Pattern (ok)
  • Factory pattern (ok)
  • Built-in Object Factory (ok)
  • Iterator (ok)
  • Bridge Pattern (ok)
  • Composite Pattern (ok)
  • Một số Design Patterns có thể sử dụng trong Javascript – Phần 1 (ok)
  • Chém gió về JavaScript Design Pattern - Part 1(ok)
  • Chém Gió Về JavaScript Design Pattern Phần 2
  • Chém gió về JavaScript Design Pattern - Part 3
  • 4 Design Patterns trong Javascript mà bạn nên biết
  • Design Pattern trong JavaScript (ok)
  • Lebab chuyển mã ES5 của bạn thành ES6 / ES7. Nó hoàn toàn ngược lại với những gì Babel làm (ok)
  • Turn your ES5 code into readable ES6 (ok)
  • Thuộc tính :selected quá tuyệt cho sự lựa chọn (ok)
  • jQuery I want to add an active class to the linked ID of an anchor tag style2.track360.xyz (ok)
  • Keep URL unaffected when anchor link is clicked (ok)
  • [UI SLIDER] Ui slider with text box input (ok)
  • [SELECT2] version Select2 3.5.3 nhìn trực quan hơn (ok)
  • [SELECT2] keypress select2, enter key press keycode yp.vn (ok)
  • [SELECT2] Select2 Bootstrap Theme (ok)
  • [SELECT2] tags (ok)
  • [SELECT2] tokenSeparators (ok)
  • [SELECT2] click change value (ok)
  • [SELECT2] jQuery $.ajax options (ok)
  • [SELECT2] Full Options (ok)
  • [SELECT2] value placeholder (ok)
  • [SELECT2] Can thiệp vào templateResult (ok)
  • [SELECT2] làm lá cờ gắn trước text kiểu kool ngầu (ok)
  • [SELECT2] cam thiệp vào templateSelection (ok)
  • [SELECT2] thêm thẻ bọc vào lựa chọn ví dụ thẻ <strong/> (ok)
  • [SELECT2] opening when a result is selected (ok)
  • [SELECT2] Full Adapters hay (ok)
  • [SELECT2] Kiểu dữ liệu trả về cho giao diện dùng html & json (ok)
  • [SELECT2] sử dụng ngôn ngữ, i18n, language (ok)
  • [SELECT2] dropdownParent (ok)
  • [SELECT2] Hiểu submit trong javascript và nâng cấp sử dụng select 2, autocomplate (ok)
  • [SELECT2] Common problems Select2 does not function properly when I use it inside a Bootstrap modal
  • [SELECT2] Full Events (ok)
  • [SELECT2] lấy dữ liệu của wp, wordpress để thực hành (ok)
  • [JSONPLACEHOLDER SELECT2] Full Sử dụng website jsonplaceholder.typicode.com để thực hành (ok)
  • Sử dụng fetch trên console.log để get api test (ok)
  • jQuery.naturalWidth / jQuery.naturalHeight images natural Width Height Native Width (ok)
  • [SUBMIT ] form submit jquery (ok)
  • Tạo file package.json bằng lệnh (ok)
  • [TYPESCRIPT] tạo file tsconfig.json bằng lệnh (ok)
  • [TYPESCRIPT] cài đặt package chạy trực tiếp ts, tsx, ts-node (ok)
  • Object for Three Dots, Array for Three Dots (ok)
  • Cách giải thích Private Constructors & Singletons quá tuyệt (ok)
  • [TYPESCRIPT] Một số scripts hay được sử dụng trong typescripts (ok)
  • [TYPESCRIPT] A practical guide to TypeScript decorators exmaple (ok)
  • Object.getOwnPropertyDescriptor() (ok)
  • JavaScript — Property Descriptor && PropertyDescriptor (ok)
  • [TYPESCRIPT] Employing “Namespaces” in TypeScript to encapsulate your data
  • 😅[TYPESCRIPT] Một ví dụ sử dụng TypeScript Namespaces, xuất file use on browser (ok)
  • [NODEJS] object hóa một file trong javascript Nodejs - require, exports and module.exports
  • [TYPECRIPT] Omit type when extending an interface Cách loại trừ các thuộc tính khỏi giao diện (ok)
  • How TO - List Grid View (ok)
  • Javascript module, import, export, dễ ẹc, nhưng có thể bạn vẫn chưa biết
  • [BABEL] Giải thích gói babel (ok)
  • Cấu hình Webpack và Babel 7 cho React (ok)
  • ----------------- Start Kế thừa Prototype ngang và dọc -------------------
  • Kế thừa Prototype ngang và dọc
  • class, super, constructor (ok)
  • Kế thừa ngang giữa function (ok)
  • Ví dụ về kế thừa prototype ngang theo function constructor. Liên quan đến hàm call(), sẽ có bài chi
  • Kế thừa ngang giữa 2 object
  • Muốn tạo một class, object có tên k hác khi console.log?? (ok)
  • Ví dụ về Function constructor và object instance (ok)
  • Tất cả đều từ Function
  • ----------------- End Kế thừa Prototype ngang và dọc -----------
  • Easy Responsive Tabs to Accordion (ok)Demos
  • [ERROR] unable to read package/javascript (ok)
  • ------------Start Json-----------------
  • Cách để truyền dữ liệu dạng boolean trong Postman (ok)
  • ------------ End Json-----------------
  • ---------- start JSONP ---------------------
  • Cross-Domain Ajax Requests
  • 1. JSONP (JSON with padding)
  • 2. CORSCross-origin resource sharing (CORS) là một cơ chế đặc biệt cho phép resource đặt tại một do
  • 3. Proxy
  • JSONP là gì và tại sao nó được tạo ra? (ok)
  • 4. Javascript – Tạo script động và kĩ thuật JSONP (ok)
  • ----------- End JSONP --------------
  • Destructuring Assignment in ES6
  • Cơ chế bất đồng bộ trong javascript (ok)
  • jQuery.inArray()
  • website check call stack (ok)
  • Bài 6: Template Literals trong ES6 (ok)
  • ES6 Arrow Functions (ok)
  • Lập trình TypeScript (ok)
  • Uncaught ReferenceError: exports is not defined in filed generated by Typescript (ok)
  • Cách hoạt động của các module loader? (ok) một ví dụ kinh điển :)
  • RequireJS Cho Người Mới Bắt Đầu (ok) quá tuyệt
  • Tiny loaders tương tự REQUIREJS (Ok)
  • Javascript Module Loader – From the basic (ok)
  • ES6 Modules and CommonJS (Oke) Một ví dụ quý hơn vàng :(((
  • CommonJS là một module pattern hỗ trợ cho tất cả các phiên bản Node.js. Với CommonJS, JavaScript obj
  • ------------------------Start webpack ----------------------
  • [WEBPACK] Làm một ví dụ compile scss, sass bằng WEBPACK full (ok)
  • Webpack từ A đến Á: Webpack watch mode (ok)
  • Webpack từ A đến Á: Webpack dev server (ok)
  • Webpack từ A đến Á: Webpack output hash digest (ok)
  • Webpack từ A đến Á: Webpack multiple entry points (ok)
  • Webpack từ A đến Á: Webpack multiple file types per entry (ok)
  • Webpack từ A đến Á: Webpack import export module (ok)
  • Webpack từ A đến Á: Webpack source map (ok)
  • Webpack từ A đến Á: Webpack import jQuery (ok)
  • Webpack từ A đến Á: Webpack import jQuery - Bootstrap (ok)
  • Webpack từ A đến Á: Webpack import jQuery - Materialize
  • Webpack từ A đến Á: Code Splitting (ok)
  • Webpack từ A đến Á: Code Splitting (ok)
  • Webpack từ A đến Á: Webpack resolve alias - extensions
  • Config alias chuẩn trong webpack (ok)
  • Webpack từ A đến Á: Webpack Babel Loader (ok)
  • Webpack từ A đến Á: Webpack Eslint Loader (ok)
  • Webpack từ A đến Á: Webpack Url Loader (ok)
  • Webpack từ A đến Á: Webpack File Loader (ok)
  • Webpack từ A đến Á: Webpack Style Loader (ok)
  • Webpack từ A đến Á: Webpack Sass Loader (ok)
  • Webpack từ A đến Á: Html Webpack Plugin (ok)
  • Option chunks Html Webpack Plugin (ok)
  • Webpack từ A đến Á: Clean Webpack Plugin (ok)
  • What is the difference between @babel/core and babel-core? (ok)
  • [WEBPACK] 2. Webpack : Khởi Tạo Project (nghiepuit)
  • [WEBPACK] 3. Webpack : Apply Babel Cho Project (nghiepuit)
  • [WEBPACK] 4. Webpack : CSS Loader (nghiepuit)
  • plugin @babel/plugin-proposal-class-properties
  • [WEBPACK] 5. Webpack : Tạo Project ReactJS (
  • [WEBPACK] 7. Webpack : File Loader - Tích Hợp Bootstrap
  • [WEBPACK] 8. Webpack : Tích Hợp Jquery, React, Redux Devtools (nghiepuit)
  • [WEBPACK] 9. Webpack : Vendor Caching
  • [WEBPACK] 10. Webpack : CommonsChunkPlugin
  • [WEBPACK] 10. Webpack : CommonsChunkPlugin (ok)
  • [WEBPACK] Webpack series (ep3) - code splitting - chia code trong webpack (ok)
  • Compile SASS with Webpack into a CSS file (ok)
  • [WEBPACK] 11. Webpack : Optimize Khi Bundle template (ok)
  • [WEBPACK] 12. Webpack : Clean Project (ok)
  • [WEBPACK] 12+. Webpack : webpack-dev-server
  • [WEBPACK] Plugin HtmlWebpackPlugin (ok)
  • HashRouter vs BrowserRouter
  • [WEBPACK] Webpack giúp kết nối các module lại với nhau ( (ok)
  • [WEBPACK] Chú ý: @babel/preset-env dùng cho những gói cũ thay vì khai báo mới babel-preset-env (ok)
  • [WEBPACK]
  • [WEBPACK] webpack-dev-server (ok)
  • [WEBPACK] liên kết với trang Webpack (ok)
  • [WEBPACK] Webpack output hash digest (ok)
  • [WEBPACK] Webpack multiple file types per entry
  • [WEBPACK] Webpack import export module (ok)
  • [WEBPACK] Webpack source map (ok)
  • Simple use jQuery with TypeScript (ok)
  • [WEBPACK] Webpack import jQuery (ok)
  • [WEBPACK] Webpack import jQuery - Bootstrap (ok)
  • [WEBPACK] Webpack import jQuery - Materialize
  • [WEBPACK] Webpack từ A đến Á: Code Splitting
  • [WEBPACK] Webpack từ A đến Á: Webpack resolve alias - extensions
  • [WEBPACK] Config alias chuẩn trong webpack
  • [WEBPACK] Webpack từ A đến Á: Webpack Babel Loader
  • [WEBPACK] Webpack từ A đến Á: Webpack Eslint Loader
  • [WEBPACK] Webpack từ A đến Á: Webpack Url Loader (ok)
  • [WEBPACK] Webpack từ A đến Á: Webpack File Loader
  • [WEBPACK] Webpack từ A đến Á: Webpack Style Loader (ok)
  • [WEBPACK] Webpack từ A đến Á: Webpack Css Loader
  • [WEBPACK] Webpack từ A đến Á: Webpack Sass Loader
  • [WEBPACK] [SPITEST] Teach you how to use webpack to generate css sprites
  • Page learn webpack good
  • Remove unused CSS styles from Bootstrap using PurgeCSS (ok)
  • [WEBPACK] Webpack cho người mới bắt đầu (ok)
  • [WEBPACK] cấu hình output (ok)
  • [WEBPACK] Dùng webpack để sử dụng từ khóa import, export (ok)
  • [WEBPACK] Từ cơ bản đến nâng cao
  • [WEBPACK] Tăng Tốc Độ và Tối Ưu Hoá Website Bằng CSS Sprites (ok)
  • ------------------------ End webpack ----------------------
  • How to convert unordered list into nicely styled <select> dropdown using jquery? (ok)
  • 😆Lazy loading images using event handlers 1
  • 😄Layload ajax && background 2
  • jQuery Lazy 3
  • jQuery lazyload 4
  • Config lazySizesConfig lazysizes.min.js lazysizes(ok)
  • Lazy loading images using event handlers (ok)
  • GIỚI THIỆU THƯ VIỆN LAZYSIZES.JS ĐỂ LAZY LOAD ẢNH (PHẦN 1)
  • GIỚI THIỆU THƯ VIỆN LAZYSIZES.JS ĐỂ LAZY LOAD ẢNH (PHẦN 2)
  • GIỚI THIỆU THƯ VIỆN LAZYSIZES.JS ĐỂ LAZY LOAD ẢNH (PHẦN 3)
  • Native lazy-loading for the web (ok)
  • Tầm quan trọng của thuộc tính sizes, srcset trong thẻ img (ok)
  • Thực hành lazysizes.min.js
  • Check image img exits vieclam123.vn (ok)
  • Nestable - Drag & drop hierarchical list with mouse and touch compatibility (ok)
  • Cấu hình tawk chat web500.vn ( ok)
  • Cùng tìm hiểu plugin Jquery Validation
  • Tìm hiểu về Jquery Validation (Phần 1) (ok)
  • Tìm hiểu về Jquery Validation (Phần 2) (ok)
  • Tìm hiểu về hộp thoại Sweet alert 2
  • Multi-table,Multi table (ok)
  • SweetAlert2 getHtmlContainer (ok)
  • AJAX request preConfirm (ok)
  • sử dụng php kết hợp Sweetalert2 (ok)
  • Một ví dụ tuyệt vời Ajax SweetAlert for Live Data Deleting Rows in with PHP~MySQL~Ajax (ok)
  • SweetAlert makes popup messages easy and pretty (page learn) (kiể cũ)
  • sweetalert bản chuẩn (ok)
  • AJAX requests (ok)
  • sweetalert2 bản chuẩn (ok) cái này dùng hay hơn sweetalert (ok)
  • Toast (ok)
  • Email (ok)
  • jQuery trigger() Method
  • jQuery one() Method (ok)
Powered by GitBook

Navigation

  • Lionel

@Copyright 2023

On this page
  • Module Pattern
  • Modules
  • Revealing Module Pattern
  • Singleton Pattern
  • Observer Pattern

Learning JavaScript Design Patterns P.1 (ok)

https://addyosmani.com/resources/essentialjsdesignpatterns/book/#introduction

Object Creation

Ba cách phổ biến để tạo các đối tượng mới trong JavaScript như sau:

// Each of the following options will create a new empty object:
var newObject = {};
// or
var newObject = Object.create( Object.prototype );
// or
var newObject = new Object();

Sau đó, có bốn cách để các khóa và giá trị có thể được gán cho một đối tượng:

// ECMAScript 3 compatible approaches
// 1. Dot syntax
// Set properties
newObject.someKey = "Hello World";
// Get properties
var value = newObject.someKey;
// 2. Square bracket syntax
// Set properties
newObject["someKey"] = "Hello World";
// Get properties
var value = newObject["someKey"];
// ECMAScript 5 only compatible approaches
// For more information see: http://kangax.github.com/es5-compat-table/
// 3. Object.defineProperty
// Set properties
Object.defineProperty( newObject, "someKey", {
    value: "for more control of the property's behavior",
    writable: true,
    enumerable: true,
    configurable: true
});
// If the above feels a little difficult to read, a short-hand could
// be written as follows:
var defineProp = function ( obj, key, value ){
  var config = {
    value: value,
    writable: true,
    enumerable: true,
    configurable: true
  };
  Object.defineProperty( obj, key, config );
};
// To use, we then create a new empty "person" object
var person = Object.create( Object.prototype );
// Populate the object with properties
defineProp( person, "car", "Delorean" );
defineProp( person, "dateOfBirth", "1981" );
defineProp( person, "hasBeard", false );
console.log(person);
// Outputs: Object {car: "Delorean", dateOfBirth: "1981", hasBeard: false}
// 4. Object.defineProperties
// Set properties
Object.defineProperties( newObject, {
  "someKey": {
    value: "Hello World",
    writable: true
  },
  "anotherKey": {
    value: "Foo bar",
    writable: false
  }
});
// Getting properties for 3. and 4. can be done using any of the
// options in 1. and 2.

Như chúng ta sẽ thấy phần sau của cuốn sách, các phương thức này thậm chí có thể được sử dụng để kế thừa, như sau:

// Usage:
// Create a race car driver that inherits from the person object
var driver = Object.create( person );
// Set some properties for the driver
defineProp(driver, "topSpeed", "100mph");
// Get an inherited property (1981)
console.log( driver.dateOfBirth );
// Get the property we set (100mph)
console.log( driver.topSpeed );

Basic Constructors

function Car( model, year, miles ) {
  this.model = model;
  this.year = year;
  this.miles = miles;
  this.toString = function () {
    return this.model + " has done " + this.miles + " miles";
  };
}
// Usage:
// We can create new instances of the car
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
// and then open our browser console to view the
// output of the toString() method being called on
// these objects
console.log( civic.toString() );
console.log( mondeo.toString() );

Trên đây là một phiên bản đơn giản của mẫu hàm tạo nhưng nó có một số vấn đề. Một là nó làm cho việc kế thừa trở nên khó khăn và hai là các hàm như toString () được định nghĩa lại cho từng đối tượng mới được tạo bằng cách sử dụng hàm khởi tạo Car. Điều này không tối ưu lắm vì lý tưởng là chức năng này nên được chia sẻ giữa tất cả các phiên bản của loại Xe.

Rất may vì có một số lựa chọn thay thế tương thích với cả ES3 và ES5 cho việc xây dựng các đối tượng, nên việc khắc phục hạn chế này là rất nhỏ.

Constructors With Prototypes

Các hàm, giống như hầu hết các đối tượng trong JavaScript, chứa một đối tượng "nguyên mẫu". Khi chúng ta gọi một hàm tạo JavaScript để tạo một đối tượng, tất cả các thuộc tính của nguyên mẫu của hàm tạo sẽ được cung cấp cho đối tượng mới. Theo cách này, nhiều đối tượng Xe có thể được tạo để truy cập vào cùng một nguyên mẫu. Do đó, chúng ta có thể mở rộng ví dụ ban đầu như sau:

function Car( model, year, miles ) {
  this.model = model;
  this.year = year;
  this.miles = miles;
}
// Note here that we are using Object.prototype.newMethod rather than
// Object.prototype so as to avoid redefining the prototype object
Car.prototype.toString = function () {
  return this.model + " has done " + this.miles + " miles";
};
// Usage:
var civic = new Car( "Honda Civic", 2009, 20000 );
var mondeo = new Car( "Ford Mondeo", 2010, 5000 );
console.log( civic.toString() );
console.log( mondeo.toString() );

Ở trên, một phiên bản duy nhất của toString () bây giờ sẽ được chia sẻ giữa tất cả các đối tượng Car.

Module Pattern

Modules

Mô-đun là một phần không thể thiếu trong kiến trúc của bất kỳ ứng dụng mạnh mẽ nào và thường giúp giữ cho các đơn vị mã cho một dự án được phân tách và tổ chức rõ ràng.

Object Literals

var myObjectLiteral = {
    variableKey: variableValue,
    functionKey: function () {
      // ...
    }
};

Dưới đây, chúng ta có thể xem một ví dụ đầy đủ hơn về một mô-đun được xác định bằng cách sử dụng object literal:

var myModule = {
  myProperty: "someValue",
  // object literals can contain properties and methods.
  // e.g we can define a further object for module configuration:
  myConfig: {
    useCaching: true,
    language: "en"
  },
  // a very basic method
  saySomething: function () {
    console.log( "Where in the world is Paul Irish today?" );
  },
  // output a value based on the current configuration
  reportMyConfig: function () {
    console.log( "Caching is: " + ( this.myConfig.useCaching ? "enabled" : "disabled") );
  },
  // override the current configuration
  updateMyConfig: function( newConfig ) {
    if ( typeof newConfig === "object" ) {
      this.myConfig = newConfig;
      console.log( this.myConfig.language );
    }
  }
};
// Outputs: Where in the world is Paul Irish today?
myModule.saySomething();
// Outputs: Caching is: enabled
myModule.reportMyConfig();
// Outputs: fr
myModule.updateMyConfig({
  language: "fr",
  useCaching: false
});
// Outputs: Caching is: disabled
myModule.reportMyConfig();

Module Pattern

Trong JavaScript, mẫu Mô-đun được sử dụng để mô phỏng thêm khái niệm về các lớp theo cách mà chúng ta có thể bao gồm cả các phương thức và biến công khai / riêng tư bên trong một đối tượng duy nhất

Privacy

Cần lưu ý rằng không thực sự có ý nghĩa rõ ràng về "quyền riêng tư" bên trong JavaScript bởi vì không giống như một số ngôn ngữ truyền thống, nó không có công cụ sửa đổi quyền truy cập. Về mặt kỹ thuật, các biến không thể được khai báo là công khai hay riêng tư và vì vậy chúng tôi sử dụng phạm vi hàm để mô phỏng khái niệm này.

Examples

Hãy bắt đầu xem xét việc triển khai mô hình Mô-đun bằng cách tạo một mô-đun độc lập.

var testModule = (function() {
  var counter = 0;
  return {
    incrementCounter: function() {
      return counter++;
    },
    resetCounter: function() {
      console.log("counter value prior to reset: " + counter);
      counter = 0;
    }
  };
})();
// Usage:
// Increment our counter
testModule.incrementCounter();
// Check the counter value and reset
// Outputs: counter value prior to reset: 1
testModule.resetCounter();

Ở đây, các phần khác của mã không thể đọc trực tiếp giá trị của incrementCounter () hoặc resetCounter (). Biến bộ đếm thực sự được bảo vệ hoàn toàn khỏi phạm vi toàn cục của chúng ta nên nó hoạt động giống như một biến riêng - sự tồn tại của nó bị giới hạn trong phạm vi đóng của mô-đun để mã duy nhất có thể truy cập phạm vi của nó là hai hàm của chúng ta.

Khi làm việc với mẫu Mô-đun, chúng tôi có thể thấy hữu ích khi xác định một mẫu đơn giản mà chúng tôi sử dụng để bắt đầu với nó. Đây là một trong đó bao gồm các biến không gian tên, công khai và riêng tư:

var myNamespace = (function() {
  var myPrivateVar, myPrivateMethod;
  // A private counter variable
  myPrivateVar = 0;
  // A private function which logs any arguments
  myPrivateMethod = function(foo) {
    console.log(foo);
  };
  return {
    // A public variable
    myPublicVar: "foo",
    // A public function utilizing privates
    myPublicFunction: function(bar) {
      // Increment our private counter
      myPrivateVar++;
      // Call our private method using bar
      myPrivateMethod(bar);
    }
  };
})();

Nhìn vào một ví dụ khác, bên dưới chúng ta có thể thấy một giỏ hàng được triển khai bằng mẫu này. Bản thân mô-đun hoàn toàn tự chứa trong một biến toàn cục có tên là basketModule. Mảng giỏ trong mô-đun được giữ kín và do đó các phần khác của ứng dụng của chúng tôi không thể đọc trực tiếp nó. Nó chỉ tồn tại khi đóng mô-đun và vì vậy các phương thức duy nhất có thể truy cập nó là những phương thức có quyền truy cập vào phạm vi của nó (tức là addItem (), getItemCount (), v.v.).

var basketModule = (function() {
  // privates
  var basket = [];
  function doSomethingPrivate() {
    //...
  }
  function doSomethingElsePrivate() {
    //...
  }
  // Return an object exposed to the public
  return {
    // Add items to our basket
    addItem: function(values) {
      basket.push(values);
    },
    // Get the count of items in the basket
    getItemCount: function() {
      return basket.length;
    },
    // Public alias to a private function
    doSomething: doSomethingPrivate,
    // Get the total value of items in the basket
    getTotal: function() {
      var q = this.getItemCount(),
        p = 0;
      while (q--) {
        p += basket[q].price;
      }
      return p;
    }
  };
})();

Bên trong mô-đun, bạn có thể nhận thấy rằng chúng tôi trả về một đối tượng. Điều này sẽ tự động được gán cho basketModule để chúng tôi có thể tương tác với nó như sau:

// basketModule returns an object with a public API we can use
basketModule.addItem({
  item: "bread",
  price: 0.5
});
basketModule.addItem({
  item: "butter",
  price: 0.3
});
// Outputs: 2
console.log( basketModule.getItemCount() );
// Outputs: 0.8
console.log( basketModule.getTotal() );
// However, the following will not work:
// Outputs: undefined
// This is because the basket itself is not exposed as a part of our
// public API
console.log( basketModule.basket );
// This also won't work as it only exists within the scope of our
// basketModule closure, but not in the returned public object
console.log( basket );

Module Pattern Variations

Import mixins

Biến thể này của mẫu thể hiện cách các hình cầu (ví dụ: jQuery, Dấu gạch dưới) có thể được chuyển vào làm đối số cho hàm ẩn danh của mô-đun của chúng tôi. Điều này cho phép chúng tôi nhập chúng và bí danh cục bộ một cách hiệu quả như chúng tôi muốn.

// Global module
var myModule = (function ( jQ, _ ) {
    function privateMethod1(){
        jQ(".container").html("test");
    }
    function privateMethod2(){
      console.log( _.min([10, 5, 100, 2, 1000]) );
    }
    return{
        publicMethod: function(){
            privateMethod1();
        }
    };
// Pull in jQuery and Underscore
})( jQuery, _ );
myModule.publicMethod();

Exports

Biến thể tiếp theo này cho phép chúng ta khai báo toàn cầu mà không cần tiêu thụ chúng và tương tự có thể hỗ trợ khái niệm nhập khẩu toàn cầu được thấy trong ví dụ cuối cùng.

// Global module
var myModule = (function() {
  // Module object
  var module = {},
    privateVariable = "Hello World";
  function privateMethod() {
    // ...
  }
  module.publicProperty = "Foobar";
  module.publicMethod = function() {
    console.log(privateVariable);
  };
  return module;
})();

Bộ công cụ và triển khai mẫu mô-đun dành riêng cho khung

Dojo

Dojo cung cấp một phương thức thuận tiện để làm việc với các đối tượng được gọi là dojo.setObject (). Điều này coi đối số đầu tiên của nó là một chuỗi được phân tách bằng dấu chấm, chẳng hạn như myObj.parent.child tham chiếu đến thuộc tính có tên "child" trong đối tượng "parent" được xác định bên trong "myObj". Sử dụng setObject () cho phép chúng ta đặt giá trị của các phần tử con, tạo bất kỳ đối tượng trung gian nào trong phần còn lại của đường dẫn được truyền nếu chúng chưa tồn tại.

Ví dụ: nếu chúng ta muốn khai báo basket.core như một đối tượng của không gian tên cửa hàng, điều này có thể đạt được như sau bằng cách sử dụng cách truyền thống:

Ví dụ: nếu chúng ta muốn khai báo basket.core như một đối tượng của store namespace, điều này có thể đạt được như sau bằng cách sử dụng cách truyền thống:

var store = window.store || {};
if ( !store["basket"] ) {
  store.basket = {};
}
if ( !store.basket["core"] ) {
  store.basket.core = {};
}
store.basket.core = {
  // ...rest of our logic
};

Or as follows using Dojo 1.7 (AMD-compatible version) and above:

require(["dojo/_base/customStore"], function(store) {
  // using dojo.setObject()
  store.setObject("basket.core", (function() {
    var basket = [];
    function privateMethod() {
      console.log(basket);
    }
    return {
      publicMethod: function() {
        privateMethod();
      }
    };
  })());
});

ExtJS

Ở đây, chúng ta thấy một ví dụ về cách xác định một không gian tên mà sau đó có thể được điền bằng một mô-đun chứa cả API riêng và công khai. Ngoại trừ một số khác biệt về ngữ nghĩa, nó khá gần với cách mô-đun được triển khai trong JavaScript vani:

// create namespace
Ext.namespace("myNameSpace");
// create application
myNameSpace.app = function() {
  // do NOT access DOM from here; elements don't exist yet
  // private variables
  var btn1,
    privVar1 = 11;
  // private functions
  var btn1Handler = function(button, event) {
    console.log("privVar1=" + privVar1);
    console.log("this.btn1Text=" + this.btn1Text);
  };
  // public space
  return {
    // public properties, e.g. strings to translate
    btn1Text: "Button 1",
    // public methods
    init: function() {
      if (Ext.Ext2) {
        btn1 = new Ext.Button({
          renderTo: "btn1-ct",
          text: this.btn1Text,
          handler: btn1Handler
        });
      } else {
        btn1 = new Ext.Button("btn1-ct", {
          text: this.btn1Text,
          handler: btn1Handler
        });
      }
    }
  };
}();

YUI

Tương tự, chúng ta cũng có thể triển khai Mô-đun mẫu khi xây dựng ứng dụng bằng YUI3. Ví dụ sau dựa nhiều vào việc triển khai mẫu Mô-đun YUI ban đầu của Eric Miraglia, nhưng một lần nữa, không khác nhiều so với phiên bản JavaScript vani:

Y.namespace("store.basket");
Y.store.basket = (function() {
  var myPrivateVar, myPrivateMethod;
  // private variables:
  myPrivateVar = "I can be accessed only within Y.store.basket.";
  // private method:
  myPrivateMethod = function() {
    Y.log("I can be accessed only from within YAHOO.store.basket");
  }
  return {
    myPublicProperty: "I'm a public property.",
    myPublicMethod: function() {
      Y.log("I'm a public method.");
      // Within basket, I can access "private" vars and methods:
      Y.log(myPrivateVar);
      Y.log(myPrivateMethod());
      // The native scope of myPublicMethod is store so we can
      // access public members using "this":
      Y.log(this.myPublicProperty);
    }
  };
})();

jQuery

Có một số cách mà mã jQuery không cụ thể cho các plugin có thể được bao bọc bên trong mẫu Mô-đun. Ben Cherry trước đây đã đề xuất một triển khai trong đó một trình bao bọc hàm được sử dụng xung quanh các định nghĩa mô-đun trong trường hợp có một số điểm chung giữa các mô-đun.

Trong ví dụ sau, một hàm thư viện được định nghĩa để khai báo một thư viện mới và tự động liên kết hàm init với document.ready khi các thư viện mới (tức là mô-đun) được tạo.

function library( module ) {
  $( function() {
    if ( module.init ) {
      module.init();
    }
  });
  return module;
}
var myLibrary = library(function () {
  return {
    init: function () {
      // module implementation
    }
  };
}());

Revealing Module Pattern

Mô hình Mô-đun tiết lộ ra đời khi Heilmann thất vọng với thực tế là anh ta phải lặp lại tên của đối tượng chính khi chúng ta muốn gọi một phương thức công khai từ một phương thức khác hoặc truy cập các biến công khai. Anh ấy cũng không thích yêu cầu của Mô-đun về việc phải chuyển sang ký hiệu chữ đối tượng cho những thứ anh ấy muốn công khai.

Kết quả của những nỗ lực của anh ấy là một mô hình được cập nhật trong đó chúng tôi chỉ cần xác định tất cả các hàm và biến của chúng tôi trong phạm vi riêng tư và trả về một đối tượng ẩn danh với các con trỏ đến chức năng riêng tư mà chúng tôi muốn tiết lộ dưới dạng công khai.

var myRevealingModule = (function() {
  var privateVar = "Ben Cherry",
    publicVar = "Hey there!";
  function privateFunction() {
    console.log("Name:" + privateVar);
  }
  function publicSetName(strName) {
    privateVar = strName;
  }
  function publicGetName() {
    privateFunction();
  }
  // Reveal public pointers to
  // private functions and properties
  return {
    setName: publicSetName,
    greeting: publicVar,
    getName: publicGetName
  };
})();
myRevealingModule.setName("Paul Kinlan");

Mẫu cũng có thể được sử dụng để tiết lộ các chức năng và thuộc tính riêng tư với một lược đồ đặt tên cụ thể hơn nếu chúng ta muốn:

var myRevealingModule = (function() {
  var privateCounter = 0;
  function privateFunction() {
    privateCounter++;
  }
  function publicFunction() {
    publicIncrement();
  }
  function publicIncrement() {
    privateFunction();
  }
  function publicGetCount() {
    return privateCounter;
  }
  // Reveal public pointers to
  // private functions and properties
  return {
    start: publicFunction,
    increment: publicIncrement,
    count: publicGetCount
  };
})();
myRevealingModule.start();

Singleton Pattern

Vì vậy, mẫu Singleton được biết đến vì nó hạn chế việc khởi tạo một lớp cho một đối tượng duy nhất. Về mặt cổ điển, mẫu Singleton có thể được thực hiện bằng cách tạo một lớp với một phương thức tạo ra một thể hiện mới của lớp nếu nó không tồn tại. Trong trường hợp một cá thể đã tồn tại, nó chỉ trả về một tham chiếu đến đối tượng đó.

Singleton khác với các lớp (hoặc đối tượng) tĩnh là chúng ta có thể trì hoãn việc khởi tạo chúng, nói chung là vì chúng yêu cầu một số thông tin có thể không có sẵn trong thời gian khởi tạo. Họ không cung cấp một cách để mã không biết về tham chiếu trước đó của họ để dễ dàng truy xuất chúng. Điều này là do nó không phải là đối tượng hoặc "lớp" được trả về bởi một Singleton, nó là một cấu trúc. Hãy nghĩ về cách các biến được đóng thực sự không phải là các bao đóng - phạm vi hàm cung cấp sự đóng lại là sự đóng lại.

Trong JavaScript, các Singleton đóng vai trò như một không gian tên tài nguyên được chia sẻ cách ly mã thực thi với không gian tên chung để cung cấp một điểm truy cập duy nhất cho các hàm.

var mySingleton = (function() {
  // Instance stores a reference to the Singleton
  var instance;
  function init() {
    // Singleton
    // Private methods and variables
    function privateMethod() {
      console.log("I am private");
    }
    var privateVariable = "Im also private";
    var privateRandomNumber = Math.random();
    return {
      // Public methods and variables
      publicMethod: function() {
        console.log("The public can see me!");
      },
      publicProperty: "I am also public",
      getRandomNumber: function() {
        return privateRandomNumber;
      }
    };
  };
  return {
    // Get the Singleton instance if one exists
    // or create one if it doesn't
    getInstance: function() {
      if (!instance) {
        instance = init();
      }
      return instance;
    }
  };
})();
var myBadSingleton = (function() {
  // Instance stores a reference to the Singleton
  var instance;
  function init() {
    // Singleton
    var privateRandomNumber = Math.random();
    return {
      getRandomNumber: function() {
        return privateRandomNumber;
      }
    };
  };
  return {
    // Always create a new Singleton instance
    getInstance: function() {
      instance = init();
      return instance;
    }
  };
})();
// Usage:
var singleA = mySingleton.getInstance();
var singleB = mySingleton.getInstance();
console.log(singleA.getRandomNumber() === singleB.getRandomNumber()); // true
var badSingleA = myBadSingleton.getInstance();
var badSingleB = myBadSingleton.getInstance();
console.log(badSingleA.getRandomNumber() !== badSingleB.getRandomNumber()); // true
// Note: as we are working with random numbers, there is a
// mathematical possibility both numbers will be the same,
// however unlikely. The above example should otherwise still
// be valid.

Điều làm cho Singleton là quyền truy cập toàn cục vào cá thể (thường thông qua MySingleton.getInstance ()) vì chúng tôi không (ít nhất là trong các ngôn ngữ tĩnh) gọi trực tiếp MySingleton () mới. Tuy nhiên, điều này có thể thực hiện được trong JavaScript.

Trong thực tế, mẫu Singleton hữu ích khi cần chính xác một đối tượng để điều phối các đối tượng khác trên toàn hệ thống. Dưới đây là một ví dụ với mẫu được sử dụng trong ngữ cảnh này:

var SingletonTester = (function() {
  // options: an object containing configuration options for the singleton
  // e.g var options = { name: "test", pointX: 5};
  function Singleton(options) {
    // set options to the options supplied
    // or an empty object if none are provided
    options = options || {};
    // set some properties for our singleton
    this.name = "SingletonTester";
    this.pointX = options.pointX || 6;
    this.pointY = options.pointY || 10;
  }
  // our instance holder
  var instance;
  // an emulation of static variables and methods
  var _static = {
    name: "SingletonTester",
    // Method for getting an instance. It returns
    // a singleton instance of a singleton object
    getInstance: function(options) {
      if (instance === undefined) {
        instance = new Singleton(options);
      }
      return instance;
    }
  };
  return _static;
})();
var singletonTest = SingletonTester.getInstance({
  pointX: 5
});
// Log the output of pointX just to verify it is correct
// Outputs: 5
console.log(singletonTest.pointX);

Observer Pattern

Observer là một mẫu thiết kế trong đó một object (được gọi là chủ thể) duy trì danh sách các đối tượng phụ thuộc vào observers (observers), tự động thông báo cho chúng về bất kỳ thay đổi nào đối với trạng thái.

Khi một đối tượng cần thông báo cho những người quan sát về một điều gì đó thú vị đang xảy ra, nó sẽ phát một thông báo cho những người quan sát (có thể bao gồm dữ liệu cụ thể liên quan đến chủ đề của thông báo).

Khi chúng tôi không còn muốn một quan sát viên cụ thể được thông báo về những thay đổi của chủ thể mà họ đã đăng ký, chủ thể đó có thể xóa họ khỏi danh sách quan sát viên.

Thường sẽ hữu ích khi tham khảo lại các định nghĩa đã xuất bản về các mẫu thiết kế không có ngôn ngữ để hiểu rộng hơn về cách sử dụng và lợi thế của chúng theo thời gian. Định nghĩa của mẫu Người quan sát được cung cấp trong sách GoF, Mẫu thiết kế: Các yếu tố của phần mềm hướng đối tượng có thể tái sử dụng,

Bây giờ chúng ta có thể mở rộng những gì chúng ta đã học được để triển khai mẫu Observer với các thành phần sau:

Subject: duy trì danh sách quan sát viên, tạo điều kiện thêm hoặc xóa quan sát viên

Observer: cung cấp giao diện cập nhật cho các đối tượng cần được thông báo về sự thay đổi trạng thái của Chủ thể

ConcreteSubject: phát thông báo cho người quan sát về những thay đổi của trạng thái, lưu trữ trạng thái của ConcreteObservers

ConcreteObserver: lưu trữ một tham chiếu đến ConcreteSubject, triển khai giao diện cập nhật cho Người quan sát để đảm bảo trạng thái nhất quán với Chủ thể

Đầu tiên, hãy lập mô hình danh sách các Quan sát viên phụ thuộc mà một đối tượng có thể có:

function ObserverList() {
  this.observerList = [];
}
ObserverList.prototype.add = function(obj) {
  return this.observerList.push(obj);
};
ObserverList.prototype.count = function() {
  return this.observerList.length;
};
ObserverList.prototype.get = function(index) {
  if (index > -1 && index < this.observerList.length) {
    return this.observerList[index];
  }
};
ObserverList.prototype.indexOf = function(obj, startIndex) {
  var i = startIndex;
  while (i < this.observerList.length) {
    if (this.observerList[i] === obj) {
      return i;
    }
    i++;
  }
  return -1;
};
ObserverList.prototype.removeAt = function(index) {
  this.observerList.splice(index, 1);
};

Tiếp theo, hãy lập mô hình Đối tượng và khả năng thêm, bớt hoặc thông báo cho các quan sát viên trong danh sách quan sát viên.

function Subject() {
  this.observers = new ObserverList();
}
Subject.prototype.addObserver = function(observer) {
  this.observers.add(observer);
};
Subject.prototype.removeObserver = function(observer) {
  this.observers.removeAt(this.observers.indexOf(observer, 0));
};
Subject.prototype.notify = function(context) {
  var observerCount = this.observers.count();
  for (var i = 0; i < observerCount; i++) {
    this.observers.get(i).update(context);
  }
};

Sau đó, chúng tôi xác định một khung để tạo các Quan sát viên mới. Chức năng cập nhật ở đây sẽ được ghi đè sau đó với hành vi tùy chỉnh.

// The Observer
function Observer(){
  this.update = function(){
    // ...
  };
}

Sau đó, chúng tôi xác định các trình xử lý ConcreteSubject và ConcreteObserver để thêm người quan sát mới vào trang và triển khai giao diện cập nhật. Xem bên dưới để biết nhận xét nội tuyến về những gì các thành phần này làm trong bối cảnh của ví dụ của chúng tôi.

HTML:

<button id="addNewObserver">Add New Observer checkbox</button>
<input id="mainCheckbox" type="checkbox"/>
<div id="observersContainer"></div>

Full code

C:\Users\Administrator\Desktop\gulp\index.html

<html>
<head>
</head>
<body>
  <button id="addNewObserver">Add New Observer checkbox</button>
  <input id="mainCheckbox" type="checkbox" />
  <div id="observersContainer"></div>
  <script src="es6.js"></script>
</body>
</html>

C:\Users\Administrator\Desktop\gulp\es6.js

function ObserverList() {
  this.observerList = [];
}
ObserverList.prototype.add = function(obj) {
  return this.observerList.push(obj);
};
ObserverList.prototype.count = function() {
  return this.observerList.length;
};
ObserverList.prototype.get = function(index) {
  if (index > -1 && index < this.observerList.length) {
    return this.observerList[index];
  }
};
ObserverList.prototype.indexOf = function(obj, startIndex) {
  var i = startIndex;
  while (i < this.observerList.length) {
    if (this.observerList[i] === obj) {
      return i;
    }
    i++;
  }
  return -1;
};
ObserverList.prototype.removeAt = function(index) {
  this.observerList.splice(index, 1);
};
// ==
function Subject() {
  this.observers = new ObserverList();
}
Subject.prototype.addObserver = function(observer) {
  this.observers.add(observer);
};
Subject.prototype.removeObserver = function(observer) {
  this.observers.removeAt(this.observers.indexOf(observer, 0));
};
Subject.prototype.notify = function(context) {
  var observerCount = this.observers.count();
  for (var i = 0; i < observerCount; i++) {
    this.observers.get(i).update(context);
  }
};
// ========
// The Observer
function Observer() {
  this.update = function() {
    // ...
  };
}
// ====
// Extend an object with an extension
function extend(obj, extension) {
  console.log(typeof obj);
  for (var key in extension) {
    obj[key] = extension[key];
  }
}
// References to our DOM elements
var controlCheckbox = document.getElementById("mainCheckbox"),
  addBtn = document.getElementById("addNewObserver"),
  container = document.getElementById("observersContainer");
// Concrete Subject
// Extend the controlling checkbox with the Subject class
extend(controlCheckbox, new Subject());
// Clicking the checkbox will trigger notifications to its observers
controlCheckbox.onclick = function() {
  controlCheckbox.notify(controlCheckbox.checked);
};
addBtn.onclick = addNewObserver;
// Concrete Observer
function addNewObserver() {
  // Create a new checkbox to be added
  var check = document.createElement("input");
  check.type = "checkbox";
  // Extend the checkbox with the Observer class
  extend(check, new Observer());
  // Override with custom update behaviour
  check.update = function(value) {
    this.checked = value;
  };
  // Add the new observer to our list of observers
  // for our main subject
  controlCheckbox.addObserver(check);
  // Append the item to the container
  container.appendChild(check);
}

Differences Between The Observer And Publish/Subscribe Pattern

Mặc dù mẫu Observer rất hữu ích cần lưu ý, khá thường xuyên trong thế giới JavaScript, chúng tôi sẽ thấy nó thường được triển khai bằng cách sử dụng một biến thể được gọi là mẫu Publish / Subscribe. Mặc dù rất giống nhau, nhưng có sự khác biệt giữa các mẫu này đáng chú ý.

Mẫu Người quan sát yêu cầu người quan sát (hoặc đối tượng) muốn nhận thông báo chủ đề phải đăng ký mối quan tâm này với đối tượng kích hoạt sự kiện (chủ đề).

Tuy nhiên, mẫu Xuất bản / Đăng ký sử dụng kênh chủ đề / sự kiện nằm giữa đối tượng muốn nhận thông báo (người đăng ký) và đối tượng kích hoạt sự kiện (nhà xuất bản). Hệ thống sự kiện này cho phép mã xác định các sự kiện cụ thể của ứng dụng có thể chuyển các đối số tùy chỉnh chứa các giá trị mà người đăng ký cần. Ý tưởng ở đây là tránh sự phụ thuộc giữa người đăng ký và nhà xuất bản.

Điều này khác với mẫu Người quan sát vì nó cho phép bất kỳ người đăng ký nào triển khai một trình xử lý sự kiện thích hợp đăng ký và nhận thông báo chủ đề do nhà xuất bản phát.

Dưới đây là một ví dụ về cách một người có thể sử dụng Publish/Subscribe nếu được cung cấp triển khai chức năng hỗ trợ publish(), subscribe() và unsubscribe() đằng sau hậu trường:

Ý tưởng chung ở đây là sự thúc đẩy của khớp nối lỏng lẻo. Thay vì các đối tượng đơn lẻ trực tiếp gọi các phương thức của các đối tượng khác, chúng đăng ký vào một nhiệm vụ hoặc hoạt động cụ thể của một đối tượng khác và được thông báo khi nó xảy ra.

// A very simple new mail handler
// A count of the number of messages received
var mailCounter = 0;
// Initialize subscribers that will listen out for a topic
// with the name "inbox/newMessage".
// Render a preview of new messages
var subscriber1 = subscribe( "inbox/newMessage", function( topic, data ) {
  // Log the topic for debugging purposes
  console.log( "A new message was received: ", topic );
  // Use the data that was passed from our subject
  // to display a message preview to the user
  $( ".messageSender" ).html( data.sender );
  $( ".messagePreview" ).html( data.body );
});
// Here's another subscriber using the same data to perform
// a different task.
// Update the counter displaying the number of new
// messages received via the publisher
var subscriber2 = subscribe( "inbox/newMessage", function( topic, data ) {
  $('.newMessageCounter').html( ++mailCounter );
});
publish( "inbox/newMessage", [{
  sender: "hello@google.com",
  body: "Hey there! How are you doing today?"
}]);
// We could then at a later point unsubscribe our subscribers
// from receiving any new topic notifications as follows:
// unsubscribe( subscriber1 );
// unsubscribe( subscriber2 );

Publish/Subscribe Implementations

Xuất bản / Đăng ký rất phù hợp trong hệ sinh thái JavaScript, phần lớn bởi vì cốt lõi, việc triển khai ECMAScript là hướng sự kiện. Điều này đặc biệt đúng trong môi trường trình duyệt vì DOM sử dụng các sự kiện làm API tương tác chính của nó để tạo tập lệnh.

May mắn thay, các thư viện JavaScript phổ biến như dojo, jQuery (sự kiện tùy chỉnh) và YUI đã có các tiện ích có thể hỗ trợ dễ dàng triển khai hệ thống Xuất bản / Đăng ký với rất ít nỗ lực. Dưới đây, chúng ta có thể xem một số ví dụ về điều này:

// Publish
// jQuery: $(obj).trigger("channel", [arg1, arg2, arg3]);
$(el).trigger("/login", [{ username: "test", userData: "test" }]);
// Dojo: dojo.publish("channel", [arg1, arg2, arg3] );
dojo.publish("/login", [{ username: "test", userData: "test" }]);
// YUI: el.publish("channel", [arg1, arg2, arg3]);
el.publish("/login", { username: "test", userData: "test" });
// Subscribe
// jQuery: $(obj).on( "channel", [data], fn );
$(el).on("/login", function(event) { ... });
// Dojo: dojo.subscribe( "channel", fn);
var handle = dojo.subscribe("/login", function(data) {.. });
// YUI: el.on("channel", handler);
el.on("/login", function(data) { ... });
// Unsubscribe
// jQuery: $(obj).off( "channel" );
$(el).off("/login");
// Dojo: dojo.unsubscribe( handle );
dojo.unsubscribe(handle);
// YUI: el.detach("channel");
el.detach("/login");

A Publish/Subscribe Implementation

var pubsub = {};
(function(myObject) {
  // Storage for topics that can be broadcast
  // or listened to
  var topics = {};
  // A topic identifier
  var subUid = -1;
  // Publish or broadcast events of interest
  // with a specific topic name and arguments
  // such as the data to pass along
  myObject.publish = function(topic, args) {
    if (!topics[topic]) {
      return false;
    }
    var subscribers = topics[topic],
      len = subscribers ? subscribers.length : 0;
    while (len--) {
      subscribers[len].func(topic, args);
    }
    return this;
  };
  // Subscribe to events of interest
  // with a specific topic name and a
  // callback function, to be executed
  // when the topic/event is observed
  myObject.subscribe = function(topic, func) {
    if (!topics[topic]) {
      topics[topic] = [];
    }
    var token = (++subUid).toString();
    topics[topic].push({
      token: token,
      func: func
    });
    return token;
  };
  // Unsubscribe from a specific
  // topic, based on a tokenized reference
  // to the subscription
  myObject.unsubscribe = function(token) {
    for (var m in topics) {
      if (topics[m]) {
        for (var i = 0, j = topics[m].length; i < j; i++) {
          if (topics[m][i].token === token) {
            topics[m].splice(i, 1);
            return token;
          }
        }
      }
    }
    return this;
  };
}(pubsub));

Example: Using Our Implementation

Bây giờ chúng tôi có thể sử dụng việc triển khai để xuất bản và đăng ký các sự kiện quan tâm như sau:

// Another simple message handler
// A simple message logger that logs any topics and data received through our
// subscriber
var messageLogger = function(topics, data) {
  console.log("Logging: " + topics + ": " + data);
};
// Subscribers listen for topics they have subscribed to and
// invoke a callback function (e.g messageLogger) once a new
// notification is broadcast on that topic
var subscription = pubsub.subscribe("inbox/newMessage", messageLogger);
// Publishers are in charge of publishing topics or notifications of
// interest to the application. e.g:
pubsub.publish("inbox/newMessage", "hello world!");
// or
pubsub.publish("inbox/newMessage", ["test", "a", "b", "c"]);
// or
pubsub.publish("inbox/newMessage", {
  sender: "hello@google.com",
  body: "Hey again!"
});
// We can also unsubscribe if we no longer wish for our subscribers
// to be notified
pubsub.unsubscribe(subscription);
// Once unsubscribed, this for example won't result in our
// messageLogger being executed as the subscriber is
// no longer listening
pubsub.publish("inbox/newMessage", "Hello! are you still there?");

Full code

var pubsub = {};
(function(myObject) {
  // Storage for topics that can be broadcast
  // or listened to
  var topics = {};
  // A topic identifier
  var subUid = -1;
  // Publish or broadcast events of interest
  // with a specific topic name and arguments
  // such as the data to pass along
  myObject.publish = function(topic, args) {
    if (!topics[topic]) {
      return false;
    }
    var subscribers = topics[topic],
      len = subscribers ? subscribers.length : 0;
    while (len--) {
      subscribers[len].func(topic, args);
    }
    return this;
  };
  // Subscribe to events of interest
  // with a specific topic name and a
  // callback function, to be executed
  // when the topic/event is observed
  myObject.subscribe = function(topic, func) {
    if (!topics[topic]) {
      topics[topic] = [];
    }
    var token = (++subUid).toString();
    topics[topic].push({
      token: token,
      func: func
    });
    return token;
  };
  // Unsubscribe from a specific
  // topic, based on a tokenized reference
  // to the subscription
  myObject.unsubscribe = function(token) {
    for (var m in topics) {
      if (topics[m]) {
        for (var i = 0, j = topics[m].length; i < j; i++) {
          if (topics[m][i].token === token) {
            topics[m].splice(i, 1);
            return token;
          }
        }
      }
    }
    return this;
  };
}(pubsub));
// =======================
// Another simple message handler
// A simple message logger that logs any topics and data received through our
// subscriber
var messageLogger = function(topics, data) {
  console.log("Logging: " + topics + ": " + data);
};
// Subscribers listen for topics they have subscribed to and
// invoke a callback function (e.g messageLogger) once a new
// notification is broadcast on that topic
var subscription = pubsub.subscribe("inbox/newMessage", messageLogger);
// Publishers are in charge of publishing topics or notifications of
// interest to the application. e.g:
pubsub.publish("inbox/newMessage", "hello world!");
// or
pubsub.publish("inbox/newMessage", ["test", "a", "b", "c"]);
// or
pubsub.publish("inbox/newMessage", {
  sender: "hello@google.com",
  body: "Hey again!"
});
// We can also unsubscribe if we no longer wish for our subscribers
// to be notified
pubsub.unsubscribe(subscription);
// Once unsubscribed, this for example won't result in our
// messageLogger being executed as the subscriber is
// no longer listening
pubsub.publish("inbox/newMessage", "Hello! are you still there?");

Example: User-Interface Notifications

Tiếp theo, hãy tưởng tượng chúng ta có một ứng dụng web chịu trách nhiệm hiển thị thông tin chứng khoán theo thời gian thực.

Ứng dụng có thể có một lưới để hiển thị số liệu thống kê về kho và một bộ đếm để hiển thị điểm cập nhật cuối cùng. Khi mô hình dữ liệu thay đổi, ứng dụng sẽ cần cập nhật lưới và bộ đếm. Trong trường hợp này, chủ đề của chúng tôi (sẽ xuất bản các chủ đề / thông báo) là mô hình dữ liệu và người đăng ký của chúng tôi là lưới và bộ đếm.

Khi người đăng ký của chúng tôi nhận được thông báo rằng bản thân mô hình đã thay đổi, họ có thể tự cập nhật cho phù hợp.

Trong quá trình triển khai của chúng tôi, người đăng ký của chúng tôi sẽ lắng nghe chủ đề "newDataAvailable" để tìm hiểu xem có thông tin cổ phiếu mới hay không. Nếu một thông báo mới được xuất bản cho chủ đề này, nó sẽ kích hoạt gridUpdate để thêm một hàng mới vào lưới của chúng tôi có chứa thông tin này. Nó cũng sẽ cập nhật bộ đếm cập nhật lần cuối để ghi lại lần cuối cùng dữ liệu được thêm vào

// Return the current local time to be used in our UI later
getCurrentTime = function() {
  var date = new Date(),
    m = date.getMonth() + 1,
    d = date.getDate(),
    y = date.getFullYear(),
    t = date.toLocaleTimeString().toLowerCase();
  return (m + "/" + d + "/" + y + " " + t);
};
// Add a new row of data to our fictional grid component
function addGridRow(data) {
  // ui.grid.addRow( data );
  console.log("updated grid component with:" + data);
}
// Update our fictional grid to show the time it was last
// updated
function updateCounter(data) {
  // ui.grid.updateLastChanged( getCurrentTime() );
  console.log("data last updated at: " + getCurrentTime() + " with " + data);
}
// Update the grid using the data passed to our subscribers
gridUpdate = function(topic, data) {
  if (data !== undefined) {
    addGridRow(data);
    updateCounter(data);
  }
};
// Create a subscription to the newDataAvailable topic
var subscriber = pubsub.subscribe("newDataAvailable", gridUpdate);
// The following represents updates to our data layer. This could be
// powered by ajax requests which broadcast that new data is available
// to the rest of the application.
// Publish changes to the gridUpdated topic representing new entries
pubsub.publish("newDataAvailable", {
  summary: "Apple made $5 billion",
  identifier: "APPL",
  stockPrice: 570.91
});
pubsub.publish("newDataAvailable", {
  summary: "Microsoft made $20 million",
  identifier: "MSFT",
  stockPrice: 30.85
});

Example: Decoupling applications using Ben Alman's Pub/Sub implementation

Trong ví dụ xếp hạng phim sau đây, chúng tôi sẽ sử dụng triển khai jQuery của Ben Alman về Xuất bản / Đăng ký để chứng minh cách chúng tôi có thể tách giao diện người dùng. Lưu ý rằng việc gửi xếp hạng chỉ có tác dụng công bố thực tế là có sẵn dữ liệu xếp hạng và người dùng mới.

Điều đó phụ thuộc vào người đăng ký các chủ đề đó để sau đó ủy quyền những gì xảy ra với dữ liệu đó. Trong trường hợp của chúng tôi, chúng tôi đang đẩy dữ liệu mới đó vào các mảng hiện có và sau đó hiển thị chúng bằng cách sử dụng phương thức .template () của thư viện Underscore để tạo khuôn mẫu.

Điều đó phụ thuộc vào người đăng ký các chủ đề đó để sau đó ủy quyền những gì xảy ra với dữ liệu đó. Trong trường hợp của chúng tôi, chúng tôi đang đẩy dữ liệu mới đó vào các mảng hiện có và sau đó hiển thị chúng bằng cách sử dụng phương thức .template () của thư viện Underscore để tạo khuôn mẫu.

C:\Users\Administrator\Desktop\gulp\index.html

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/underscore@1.12.0/underscore-min.js"></script>
  <script type="text/javascript" src="jquery.ba-tinypubsub.min.js"></script>
</head>

<body>
  <script id="userTemplate" type="text/html">
    <li><%= name %></li>
	</script>
  <script id="ratingsTemplate" type="text/html">
    <li><strong><%= title %></strong> was rated <%= rating %>/5</li>
	</script>
  <div id="container">
    <div class="sampleForm">
      <p>
        <label for="twitter_handle">Twitter handle:</label>
        <input type="text" id="twitter_handle" />
      </p>
      <p>
        <label for="movie_seen">Name a movie you've seen this year:</label>
        <input type="text" id="movie_seen" />
      </p>
      <p>
        <label for="movie_rating">Rate the movie you saw:</label>
        <select id="movie_rating">
          <option value="1">1</option>
          <option value="2">2</option>
          <option value="3">3</option>
          <option value="4">4</option>
          <option value="5" selected>5</option>
        </select>
      </p>
      <p>
        <button id="add">Submit rating</button>
      </p>
    </div>
    <div class="summaryTable">
      <div id="users">
        <h3>Recent users</h3>
      </div>
      <div id="ratings">
        <h3>Recent movies rated</h3>
      </div>
    </div>
  </div>
  <script src="es6.js"></script>
</body>

</html>

C:\Users\Administrator\Desktop\gulp\es6.js

(function($) {
  // Pre-compile templates and "cache" them using closure
  var
    userTemplate = _.template($("#userTemplate").html()),
    ratingsTemplate = _.template($("#ratingsTemplate").html());
  // Subscribe to the new user topic, which adds a user
  // to a list of users who have submitted reviews
  $.subscribe("/new/user", function(e, data) {
    if (data) {
      $('#users').append(userTemplate(data));
    }
  });
  // Subscribe to the new rating topic. This is composed of a title and
  // rating. New ratings are appended to a running list of added user
  // ratings.
  $.subscribe("/new/rating", function(e, data) {
    if (data) {
      $("#ratings").append(ratingsTemplate(data));
    }
  });
  // Handler for adding a new user
  $("#add").on("click", function(e) {
    e.preventDefault();
    var strUser = $("#twitter_handle").val(),
      strMovie = $("#movie_seen").val(),
      strRating = $("#movie_rating").val();
    // Inform the application a new user is available
    $.publish("/new/user", { name: strUser });
    // Inform the app a new rating is available
    $.publish("/new/rating", { title: strMovie, rating: strRating });
  });
})(jQuery);

C:\Users\Administrator\Desktop\gulp\jquery.ba-tinypubsub.min.js

/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
 * http://benalman.com/
 * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
(function(a){var b=a({});a.subscribe=function(){b.on.apply(b,arguments)},a.unsubscribe=function(){b.off.apply(b,arguments)},a.publish=function(){b.trigger.apply(b,arguments)}})(jQuery)

Example: Decoupling an Ajax-based jQuery application

Trong ví dụ cuối cùng của chúng tôi, chúng tôi sẽ xem xét thực tế cách tách mã của chúng tôi bằng cách sử dụng Pub / Sub ngay từ đầu trong quá trình phát triển có thể giúp chúng tôi tiết kiệm một số cấu trúc lại tiềm ẩn khó khăn sau này.

Khá thường xuyên trong các ứng dụng Ajax nặng, khi chúng tôi nhận được phản hồi cho một yêu cầu, chúng tôi muốn đạt được nhiều hơn chỉ một hành động duy nhất. Người ta có thể chỉ cần thêm tất cả logic sau yêu cầu của họ vào một lệnh gọi lại thành công, nhưng có những hạn chế đối với cách tiếp cận này.

C:\Users\Administrator\Desktop\gulp\index.html

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
  <script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
  <script type="text/javascript" src="https://cdn.jsdelivr.net/npm/underscore@1.12.0/underscore-min.js"></script>
  <script type="text/javascript" src="jquery.ba-tinypubsub.min.js"></script>
</head>
<body>
  <form id="flickrSearch">
    <input type="text" name="tag" id="query" />
    <input type="submit" name="submit" value="submit" />
  </form>
  <div id="lastQuery"></div>
  <ol id="searchResults"></ol>
  <script id="resultTemplate" type="text/html">
    <% _.each(items, function( item ){ %>
      <li><img src="<%= item.media.m %>"/></li>
    <% });%>
	</script>
  <script src="es6.js"></script>
</body>
</html>

C:\Users\Administrator\Desktop\gulp\es6.js

(function($) {
  // Pre-compile template and "cache" it using closure
  var resultTemplate = _.template($("#resultTemplate").html());
  // Subscribe to the new search tags topic
  $.subscribe("/search/tags", function(e, tags) {
    $("#lastQuery").html("<p>Searched for:<strong>" + tags + "</strong></p>");
  });
  // Subscribe to the new results topic
  $.subscribe("/search/resultSet", function(e, results) {
    $("#searchResults").empty().append(resultTemplate(results));
  });
  // Submit a search query and publish tags on the /search/tags topic
  $("#flickrSearch").submit(function(e) {
    e.preventDefault();
    var tags = $(this).find("#query").val();
    if (!tags) {
      return;
    }
    $.publish("/search/tags", [$.trim(tags)]);
  });
  // Subscribe to new tags being published and perform
  // a search query using them. Once data has returned
  // publish this data for the rest of the application
  // to consume
  $.subscribe("/search/tags", function(e, tags) {
    $.getJSON("http://api.flickr.com/services/feeds/photos_public.gne?jsoncallback=?", {
        tags: tags,
        tagmode: "any",
        format: "json"
      },
      function(data) {
        if (!data.items.length) {
          return;
        }
        $.publish("/search/resultSet", { items: data.items });
      });
  });
})(jQuery);

C:\Users\Administrator\Desktop\gulp\jquery.ba-tinypubsub.min.js

/* jQuery Tiny Pub/Sub - v0.7 - 10/27/2011
 * http://benalman.com/
 * Copyright (c) 2011 "Cowboy" Ben Alman; Licensed MIT, GPL */
(function(a){var b=a({});a.subscribe=function(){b.on.apply(b,arguments)},a.unsubscribe=function(){b.off.apply(b,arguments)},a.publish=function(){b.trigger.apply(b,arguments)}})(jQuery)

PreviousJQuery-Template (ok)NextLearning JavaScript Design Patterns P.2 (ok)

Last updated 4 years ago