将您的Web应用程序从纯JavaScript移植到Vue.js

Vue.js是一个Web应用程序开发框架。 它具有一个反应系统,使开发人员可以模拟应用程序的状态并进行管理。 结果,当数据更改时,它会自动反映在用户界面上,而开发人员则不需要访问DOM。 如果使用纯JavaScript或jQuery创建应用程序,则意味着必须显式访问DOM元素并更新它们,以便在界面中反映应用程序状态的变化,例如,在网页上显示一些数据。


对于大型项目,手动管理状态和应用程序界面的同步并非易事。 该材料的作者(我们将其翻译为您今天关注的翻译)希望分享他的研究结果,该研究旨在比较使用Hoodie (这是购物清单)渐进式Web应用程序的两个版本。 该应用程序的基本版本是用纯JS编写的(在本文中,您可以找到有关它的详细信息)。 在这里,通过对框架基本功能的通过检查以及对最终情况的分析,将显示应用程序到Vue.js的翻译。


准备申请

如果您想通读本材料,则可以使用纯JS下载应用程序的源代码,并跟随作者,使用Vue处理它。

将产品添加到列表


▍JavaScript


该应用程序允许用户将产品添加到他们的购物清单。 这是在公用文件夹的index.html文件中完成的。 标记包含在此文件的第92-124行中。 她在那儿。

 <div> <div class="mdl-grid center-items"> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="text" id="new-item-name">     <label class="mdl-textfield__label" for="new-item-name">Item Name</label> </div> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-cost">     <label class="mdl-textfield__label" for="new-item-cost">Item Cost</label> </div> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-quantity">     <label class="mdl-textfield__label" for="new-item-quantity">Quantity</label> </div> </div> <div class="mdl-grid center-items"> <button id="add-item" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">     Add Item </button> </div> </div> 

用于处理和保存数据的代码位于文件public/js/src/index.js 。 第28行的saveItems()函数负责从用于输入数据的控件中收集值并保存该数据。 此功能绑定到add-item按钮的click事件。 这是有问题的代码。

 function saveNewitem() { let name = document.getElementById("new-item-name").value; let cost = document.getElementById("new-item-cost").value; let quantity = document.getElementById("new-item-quantity").value; let subTotal = cost * quantity; if (name && cost && quantity) {   hoodie.store.withIdPrefix("item").add({     name: name,     cost: cost,     quantity: quantity,     subTotal: subTotal   });   document.getElementById("new-item-name").value = "";   document.getElementById("new-item-cost").value = "";   document.getElementById("new-item-quantity").value = ""; } else {   let snackbarContainer = document.querySelector("#toast");   snackbarContainer.MaterialSnackbar.showSnackbar({     message: "All fields are required"   }); } } document.getElementById("add-item").addEventListener("click", saveNewitem); 

ueVue


在开始使用Vue重做该项目之前,您需要将框架连接到页面。 在我们的示例中,在index.html文件中,操作如下:

 <script src="https://cdn.jsdelivr.net/npm/vue@2.5.16/dist/vue.js"></script> 

另外,在标识符app添加了<div>元素,该元素将包括位于body标记内的所有页面元素。 这是因为初始化Vue实例时,需要告知框架应管理页面的哪一部分。 在这种情况下,我们通知框架它应该处理此块中的所有内容。

现在让我们开始将项目转换为Vue。 首先,我们修改标记以使用一些Vue指令。 Vue指令是前缀为v-特殊属性。 这是更新的标记的外观。

 <form v-on:submit.prevent="onSubmit"> <div class="mdl-grid center-items">   <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="text" id="new-item-name" v-model="name">     <label class="mdl-textfield__label" for="new-item-name">Item Name</label>   </div>   <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-cost" v-model.number="cost">     <label class="mdl-textfield__label" for="new-item-cost">Item Cost</label>   </div>   <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">     <input class="mdl-textfield__input" type="number" id="new-item-quantity" v-model.number="quantity">     <label class="mdl-textfield__label" for="new-item-quantity">Quantity</label>   </div> </div> <div class="mdl-grid center-items">   <button id="add-item" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">     Add Item   </button> </div> </form> 

这里使用的v-on指令用于侦听DOM事件。 在上面的代码段中,它在form元素中用于侦听submit事件。 此外,它使用.prevent修饰符,该修饰符告诉v-on指令在被调用事件上调用event.preventDefault() 。 我们将v-model指令用于用于数据输入的元素。 应用于表单元素时,需要创建双向数据绑定。 这使系统可以根据项目的类型自动选择更新项目的正确方法。 我们将.number修饰符用于costquantity元素。

这会自动将值类型从输入字段转换为数字。 这样做是因为即使将类型设置为type=number ,该值也将始终作为字符串返回。 此处使用的修饰符可自动执行以前必须独立执行的其他检查。

接下来,创建一个新文件index-vue.js ,在其中我们将代码与index.js的代码等效,但要使用Vue的功能。 该文件的代码如下所示。 这将创建具有必要属性的Vue实例,用于处理表单事件和收集数据。

 const vm = new Vue({ el: "#app", data: {   name: "",   cost: "",   quantity: "" }, methods: {   onSubmit: function(event) {     if (this.name && this.cost && this.quantity) {       hoodie.store.withIdPrefix("item").add({         name: this.name,         cost: this.cost,         quantity: this.quantity,         subTotal: this.cost * this.quantity       });       this.name = "";       this.cost = "";       this.quantity = "";     } else {       const snackbarContainer = document.querySelector("#toast");       snackbarContainer.MaterialSnackbar.showSnackbar({         message: "All fields are required"       });     }   } } }); 

在此代码段中创建了Vue实例,并将一个对象传递给它,告诉Vue如何配置应用程序。 el属性告诉框架DOM元素的标识符,该元素的内容将由Vue控制,并将其视为“领土”。 在此元素内,Vue将考虑特定于框架的指令(以及与Vue相关的所有其他内容),并且在初始化框架的过程中,它将为应用程序配置绑定和事件处理程序。

data属性包含应用程序的状态。 初始化Vue时,此处可用的对象中的所有属性都将添加到框架的响应系统中。 当更改与DOM相关的值时,正是此系统的操作导致了用户界面的更新。 例如,使用v-model="name"指令将name属性绑定到name控件。 该指令设置属性和控件之间的双向数据绑定,以便在将某些内容添加到输入字段(或从中删除某些内容)时,对name属性进行更新。 结果,输入字段的内容反映了name属性的当前状态。

同样,绑定可与其他控件一起使用。

methods属性包含函数。 在上面的代码中, onSubmit()onSubmit()函数,该函数附加到submit()表单事件。

在页面上显示保存的数据


▍JavaScript


onSubmit函数将数据保存在连帽衫中。 之后,我们需要以表格的形式显示添加到商店的商品。 对于使用常规JS编写的应用程序,相应的标记如下所示:

 <div class="mdl-grid center-items"> <table id="item-table" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp">   <thead>     <tr>       <th class="mdl-data-table__cell--non-numeric">Item Name</th>       <th class="mdl-data-table__cell--non-numeric">Cost</th>       <th class="mdl-data-table__cell--non-numeric">Quantity</th>       <th class="mdl-data-table__cell">Sub-total</th>       <th class="mdl-data-table__cell--non-numeric">         <button class="mdl-button mdl-js-button mdl-button--icon">           <i class="material-icons">delete</font></i>         </button>       </th>     </tr>   </thead>   <tbody>   </tbody> </table> </div> <div class="mdl-grid center-items"> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">   <input class="mdl-textfield__input" type="number" id="total-cost" readonly value="0">   <label class="mdl-textfield__label" for="cost">Total Item Cost</label> </div> </div> <script id="item-row" type="text/template"> <tr id='{{row-id}}'>        <td class="mdl-data-table__cell--non-numeric">{{name}}</td>   <td class="mdl-data-table__cell--non-numeric">{{cost}}</td>   <td class="mdl-data-table__cell--non-numeric">{{quantity}}</td>   <td class="mdl-data-table__cell">{{subTotal}}</td>   <td class="mdl-data-table__cell--non-numeric">         <button class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored"         onclick="pageEvents.deleteItem('{{item-id}}')">         <i class="material-icons">remove</font></i>         </button>   </td> </tr> </script> 

该表将包含动态添加的数据,因此在这里我们需要某种方式用实际数据替换占位符,并将发生的事情附加到DOM。 在我们的案例中,使用微模板解决了这个问题。

以下代码显示了添加时用户界面中的元素。

 function addItemToPage(item) { if (document.getElementById(item._id)) return; let template = document.querySelector("#item-row").innerHTML; template = template.replace("{{name}}", item.name); template = template.replace("{{cost}}", item.cost); template = template.replace("{{quantity}}", item.quantity); template = template.replace("{{subTotal}}", item.subTotal); template = template.replace("{{row-id}}", item._id); template = template.replace("{{item-id}}", item._id); document.getElementById("item-table").tBodies[0].innerHTML += template; let totalCost = Number.parseFloat(   document.getElementById("total-cost").value ); document.getElementById("total-cost").value = totalCost + item.subTotal; } hoodie.store.withIdPrefix("item").on("add", addItemToPage); 

在此代码片段中,从DOM获取模板,将占位符替换为实际数据,并将结果附加到DOM。 然后计算出total-cost指标,该列表中所有元素的总金额也显示在界面中。

ueVue


切换到Vue时,脚本使用的模板已删除,表元素也进行了重新设计,以便它们使用Vue v-for指令,该指令可让您遍历包含元素数据的属性。 这就是现在相应标记的外观。

 <div class="mdl-grid center-items"> <table id="item-table" class="mdl-data-table mdl-js-data-table mdl-shadow--2dp">   <thead>     <tr>       <th class="mdl-data-table__cell--non-numeric">Item Name</th>       <th class="mdl-data-table__cell--non-numeric">Cost</th>       <th class="mdl-data-table__cell--non-numeric">Quantity</th>       <th class="mdl-data-table__cell">Sub-total</th>       <th class="mdl-data-table__cell--non-numeric">         <button class="mdl-button mdl-js-button mdl-button--icon">           <i class="material-icons">delete</font></i>         </button>       </th>     </tr>   </thead>   <tbody>     <tr v-for="item in items" :key="item._id">       <td class="mdl-data-table__cell--non-numeric">{{ item.name}}</td>       <td class="mdl-data-table__cell--non-numeric">{{ item.cost}}</td>       <td class="mdl-data-table__cell--non-numeric">{{ item.quantity}}</td>       <td class="mdl-data-table__cell">{{ item.subTotal}}</td>       <td class="mdl-data-table__cell--non-numeric">         <button @click="deleteRow(item._id)" class="mdl-button mdl-js-button mdl-button--icon mdl-button--colored">           <i class="material-icons">remove</font></i>         </button>       </td>     </tr>   </tbody> </table> </div> <div class="mdl-grid center-items"> <div class="mdl-textfield mdl-js-textfield mdl-textfield--floating-label">   <!-- <input class="mdl-textfield__input" type="number" id="total-cost" readonly value="0">   <label class="mdl-textfield__label" for="cost">Total Item Cost</label> -->   <h4>Total Cost: {{ total }}</h4> </div> </div> 

实际上,标记没有做太大的改变。 在此,将复制先前使用的微模板的内容,并使用Vue文本的指令和插值机制。 v-for伪指令用于列出其数据来自items属性的items 。 使用Vue {{ item.name }}构造的功能,数据以列显示。 此机制类似于微模板中使用的占位符。 总金额也使用文本插值技术显示在页面上。

现在,我们将完成index-vue.js的JavaScript代码,并获得以下内容。

 const vm = new Vue({ el: "#app", data: {   name: "",   cost: "",   quantity: "",   items: [] }, computed: {   //     total: function() {     // `this`    vm     return this.items.reduce(       (accumulator, currentValue) => accumulator + currentValue.subTotal,       0     );   } }, methods: {   ..... } }); hoodie.store.withIdPrefix("item").on("add", item => vm.items.push(item)); 

由Vue准备的上述机制的一种变体比使用常规JS创建的机制更短,更简单。 在此代码中,添加了items数据属性,该属性在上述v-for指令中使用。 添加项目后,Hoodie会调用一个函数,该函数执行vm.items.push(item)操作来更新应用程序的状态,这要归功于Vue反应性系统自动更新用户界面。 为了计算总量,不需要引用DOM元素。 在这里,我们使用计算属性,该属性使用.reduce()函数处理items数据集。 现在,借助Vue反应系统,当这些值更改时,用户界面也会更新。 好消息是,所有这些使程序员不必担心在代码中使用DOM元素。 结果,在较小的代码的帮助下,我们解决了相同的问题,在常规JS的情况下,这需要更多的代码(可能,如果在这种情况下使用jQuery库代替普通的JS,那么猫的体积也会更大,比使用Vue时获得的版本)。

将项目另存为列表


▍JavaScript


添加元素后,需要保存它们以备后用,以便以后可以将其他元素列表添加到系统中。 该应用程序具有一个“ Save List按钮,该按钮用于收集数据,使用Hoodie工具将它们保存为一组元素,并允许用户向系统中添加一组新元素。

使用常规JavaScript时,相应的函数绑定到onClick button onClick 。 这是标记。

 //index.html <div class="mdl-grid center-items"> <button class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored" onclick="pageEvents.saveList()">   Save List </button> </div> 

这是功能代码。

 //index.js function saveList() { let cost = 0; hoodie.store   .withIdPrefix("item")   .findAll()   .then(function(items) {     for (var item of items) {       cost += item.subTotal;     }     //      hoodie.store.withIdPrefix("list").add({       cost: cost,       items: items     });     //      hoodie.store       .withIdPrefix("item")       .remove(items)       .then(function() {         //          document.getElementById("item-table").tBodies[0].innerHTML = "";         //          var snackbarContainer = document.querySelector("#toast");         snackbarContainer.MaterialSnackbar.showSnackbar({           message: "List saved succesfully"         });       })       .catch(function(error) {         //             var snackbarContainer = document.querySelector("#toast");         snackbarContainer.MaterialSnackbar.showSnackbar({           message: error.message         });       });   }); } window.pageEvents = { deleteItem: deleteItem, saveList: saveList .... }; 

ueVue


切换到Vue不需要太多更改。 我们仍然需要将处理程序绑定到单击按钮时触发的事件,此外,我们需要在初始化Vue对象的methods属性时将methods (该事件的处理程序)添加到Vue对象的methods属性中。

这就是标记的外观。

 <div class="mdl-grid center-items"> <button @click="saveList" class="mdl-button mdl-js-button mdl-button--raised mdl-button--colored">   Save List </button> </div> 

@click="saveList"v-on:click="saveList"的简写v-on:click="saveList" 。 此机制用于侦听DOM事件。 在纯JS编写的应用程序版本中使用了相同的saveList函数,该函数已添加到Vue对象的methods属性中。

导航栏


▍JavaScript


现在可以将元素另存为列表,我们希望能够查看先前保存的列表以及其中包含的商品总价值的数据。 此信息将显示在另一页上,如下所示。


先前创建的产品列表中的数据

该页面的标记位于public/history.html文件中,相应的JS代码位于public/js/src/history.js 。 此页面和index.html有一些共同点。 这是位于窗口顶部的导航栏。 该面板包含指向不同页面的链接,“ Login和“ Register链接,这些链接调用用于输入系统并在其中进行注册的对话框形式。 还有一个Signout按钮,用于注销。
在使用普通JS创建的应用程序版本中,您必须在两个页面上复制相同的标记。 这就是导航栏HTML代码的样子。

 <header class="mdl-layout__header">   <div class="mdl-layout__header-row">   <!-- Title -->   <span class="mdl-layout-title">Shopping List</span>   <!-- Add spacer, to align navigation to the right -->   <div class="mdl-layout-spacer"></div>   <!-- Navigation. We hide it in small screens. -->   <nav class="mdl-navigation mdl-layout--large-screen-only">       <a class="mdl-navigation__link" href="index.html">Home</a>       <a class="mdl-navigation__link" href="history.html">History</a>       <a onclick="pageEvents.showLogin()" style="cursor: pointer" class="mdl-navigation__link login">Login</a>       <a onclick="pageEvents.showRegister()" style="cursor: pointer" class="mdl-navigation__link register">Register</a>       <a onclick="pageEvents.signout()" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>   </nav>   </div> </header> <div class="mdl-layout__drawer">   <span class="mdl-layout-title">Shopping List</span>   <nav class="mdl-navigation">   <a class="mdl-navigation__link" href="index.html">Home</a>   <a class="mdl-navigation__link" href="history.html">History</a>   <a onclick="pageEvents.showLogin()" style="cursor: pointer" class="mdl-navigation__link login">Login</a>   <a onclick="pageEvents.showRegister()" style="cursor: pointer" class="mdl-navigation__link register">Register</a>   <a onclick="pageEvents.signout()" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>   </nav> </div> 

在分析了这段代码之后,您会发现,当您单击LoginRegisterLogout链接时,将调用它们的相应功能。 该标记中描述的元素的事件处理程序在index.js文件中定义。

 import * as shared from "shared.js"; .... shared.updateDOMLoginStatus(); window.pageEvents = { showLogin: shared.showLoginDialog, showRegister: shared.showRegisterDialog, signout: shared.signOut }; 

负责使用导航栏的功能在shared.js文件中声明。

 //   let loginDialog = document.querySelector("#login-dialog"); dialogPolyfill.registerDialog(loginDialog); let registerDialog = document.querySelector("#register-dialog"); dialogPolyfill.registerDialog(registerDialog); let showLoginDialog = function() { loginDialog.showModal(); }; let showRegisterDialog = function() { registerDialog.showModal(); }; let showAnonymous = function() { document.getElementsByClassName("login")[0].style.display = "inline"; document.getElementsByClassName("login")[1].style.display = "inline"; document.getElementsByClassName("register")[0].style.display = "inline"; document.getElementsByClassName("register")[1].style.display = "inline"; document.getElementsByClassName("logout")[0].style.display = "none"; document.getElementsByClassName("logout")[1].style.display = "none"; }; let showLoggedIn = function() { document.getElementsByClassName("login")[0].style.display = "none"; document.getElementsByClassName("login")[1].style.display = "none"; document.getElementsByClassName("register")[0].style.display = "none"; document.getElementsByClassName("register")[1].style.display = "none"; document.getElementsByClassName("logout")[0].style.display = "inline"; document.getElementsByClassName("logout")[1].style.display = "inline"; }; let updateDOMLoginStatus = () => { hoodie.account.get("session").then(function(session) {   if (!session) {     //          showAnonymous();   } else if (session.invalid) {     //   ,          showAnonymous();   } else {     //         showLoggedIn();   } }); }; let signOut = function() { hoodie.account   .signOut()   .then(function() {     showAnonymous();     let snackbarContainer = document.querySelector("#toast");     snackbarContainer.MaterialSnackbar.showSnackbar({       message: "You logged out"     });     location.href = location.origin;   })   .catch(function() {     let snackbarContainer = document.querySelector("#toast");     snackbarContainer.MaterialSnackbar.showSnackbar({       message: "Could not logout"     });   }); }; export { signOut, showRegisterDialog, showLoginDialog, updateDOMLoginStatus }; 

此代码导出index.js中使用的功能。 showLoginDialog()showRegisterDialog()函数分别显示模式对话框,用于登录和注册。 signout()函数允许用户注销并调用showAnonymous()函数,该函数隐藏Logout链接并仅显示RegisterLogin链接。 updateDOMLoginStatus()函数检查用户是否已通过身份验证并显示适当的链接。 页面加载时调用此函数。

为了在两个不同页面上具有相同的导航栏,我们必须复制标记,访问DOM元素并使用CSS功能来显示和隐藏面板上的链接。 让我们看一下Vue创建的替代导航栏。

ueVue


许多Web应用程序在不同页面上使用相同的代码片段。 例如,导航栏。 此类实体应放置在容器中或作为适合重复使用的组件显示。 Vue为开发人员提供了一个组件引擎,可用于解决我们正在考虑的问题。 Vue组件是独立的且可重复使用。

转移项目以使用Vue组件,我们创建一个新文件shared-vue.js 。 Vue, . .

 Vue.component("navigation", { props: ["isLoggedIn", "toggleLoggedIn"], template: `<div>             <header class="mdl-layout__header">       <div class="mdl-layout__header-row">         <!-- Title -->         <span class="mdl-layout-title">Shopping List</span>         <!-- Add spacer, to align navigation to the right -->         <div class="mdl-layout-spacer"></div>         <!-- Navigation. We hide it in small screens. -->         <nav class="mdl-navigation mdl-layout--large-screen-only">           <a class="mdl-navigation__link" href="index.html">Home</a>           <a class="mdl-navigation__link" href="history.html">History</a>           <a v-show="!isLoggedIn" @click="showLogin" style="cursor: pointer" class="mdl-navigation__link login">Login</a>           <a v-show="!isLoggedIn" @click="showRegister" style="cursor: pointer" class="mdl-navigation__link register">Register</a>           <a v-show="isLoggedIn" @click="logout" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>         </nav>       </div>     </header>     <div class="mdl-layout__drawer">       <span class="mdl-layout-title">Shopping List</span>       <nav class="mdl-navigation">         <a class="mdl-navigation__link" href="index.html">Home</a>         <a class="mdl-navigation__link" href="history.html">History</a>         <a v-show="!isLoggedIn" @click="showLogin" style="cursor: pointer" class="mdl-navigation__link login">Login</a>         <a v-show="!isLoggedIn" @click="showRegister" style="cursor: pointer" class="mdl-navigation__link register">Register</a>         <a v-show="isLoggedIn" @click="logout" style="cursor: pointer" class="mdl-navigation__link logout">Logout</a>       </nav>     </div>           </div>`, methods: {   showLogin: function() {     const loginDialog = document.querySelector("#login-dialog");     dialogPolyfill.registerDialog(loginDialog);     loginDialog.showModal();   },   showRegister: function() {     const registerDialog = document.querySelector("#register-dialog");     dialogPolyfill.registerDialog(registerDialog);     registerDialog.showModal();   },   logout: function() {     hoodie.account       .signOut()       .then(() => {         this.toggleLoggedIn();       })       .catch(error => {         alert("Could not logout");       });   } } }); 

Vue, navigation , , , Vue. — props . props — . , , , props . isLoggedIn , .

, template , , . , , JS, , Vue — v-show @click . v-show . Logout , isLoggedIn true , falseLogin Register . , Vue v-if v-else . . @clickv-on:click . showLogin , showRegister logout .

methods . logout , , this.toggleLoggedIn() , props . , props , , isLoggedin , . , Vue DOM.
index.html . , 59-84. .

 <navigation v-bind:is-logged-in="isLoggedIn" v-bind:toggle-logged-in="toggleLoggedIn"></navigation> 

JS- isLoggedIn toggleLoggedIn , , props , , kebab-case. v-bind . isLoggedIn . : v-bind , .

 <navigation :is-logged-in="isLoggedIn" :toggle-logged-in="toggleLoggedIn"></navigation> 

isLoggedIn , toggleLoggedIn — , Vue index-vue.js . .

 const vm = new Vue({ el: "#app", data: {   name: "",   cost: "",   quantity: "",   items: [],   isLoggedIn: false }, computed: {   .....//   }, methods: {   toggleLoggedIn: function() {     this.isLoggedIn = !this.isLoggedIn;   },   ......//   } }); .....//   hoodie.account.get("session").then(function(session) { if (!session) {   //       vm.isLoggedIn = false; } else if (session.invalid) {   vm.isLoggedIn = false; } else {   //       vm.isLoggedIn = true; } }); 

Vue , , , , Vue. , Vue DOM , .


▍JavaScript


Login Register , . , , , . 171-244 index.html 100-158 history.html .

 <dialog id="login-dialog" class="mdl-dialog"> <h4 class="mdl-dialog__title">Login</h4> <div class="mdl-dialog__content">   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="text" id="login-username">       <label class="mdl-textfield__label" for="login-username">Username</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="password" id="login-password">       <label class="mdl-textfield__label" for="login-password">Password</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <span id="login-error"></span>     </div>   </div> </div> <div class="mdl-dialog__actions">   <button onclick="pageEvents.closeLogin()" type="button" class="mdl-button close">Cancel</button>   <button onclick="pageEvents.login()" type="button" class="mdl-button">Login</button> </div> </dialog> <dialog id="register-dialog" class="mdl-dialog"> <h4 class="mdl-dialog__title">Login</h4> <div class="mdl-dialog__content">   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="text" id="register-username">       <label class="mdl-textfield__label" for="register-username">Username</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <input class="mdl-textfield__input" type="password" id="register-password">       <label class="mdl-textfield__label" for="register-password">Password</label>     </div>   </div>   <div class="mdl-grid center-items">     <!-- Simple Textfield -->     <div class="mdl-textfield mdl-js-textfield">       <span id="register-error"></span>     </div>   </div> </div> <div class="mdl-dialog__actions">   <button onclick="pageEvents.closeRegister()" type="button" class="mdl-button close">Cancel</button>   <button onclick="pageEvents.register()" type="button" class="mdl-button">Register</button> </div> </dialog> 

, , shared.js index.js .

 //shared.js //   let loginDialog = document.querySelector("#login-dialog"); dialogPolyfill.registerDialog(loginDialog); let registerDialog = document.querySelector("#register-dialog"); dialogPolyfill.registerDialog(registerDialog); let closeLoginDialog = function() { loginDialog.close(); }; let closeRegisterDialog = function() { registerDialog.close(); }; let showAnonymous = function() { ... }; let showLoggedIn = function() { .... }; let signOut = function() { .... }; let updateDOMLoginStatus = () => { .... }; let login = function() { let username = document.querySelector("#login-username").value; let password = document.querySelector("#login-password").value; hoodie.account   .signIn({     username: username,     password: password   })   .then(function() {     showLoggedIn();     closeLoginDialog();     let snackbarContainer = document.querySelector("#toast");     snackbarContainer.MaterialSnackbar.showSnackbar({       message: "You logged in"     });   })   .catch(function(error) {     console.log(error);     document.querySelector("#login-error").innerHTML = error.message;   }); }; let register = function() { let username = document.querySelector("#register-username").value; let password = document.querySelector("#register-password").value; let options = { username: username, password: password }; hoodie.account   .signUp(options)   .then(function(account) {     return hoodie.account.signIn(options);   })   .then(account => {     showLoggedIn();     closeRegisterDialog();     return account;   })   .catch(function(error) {     console.log(error);     document.querySelector("#register-error").innerHTML = error.message;   }); }; export { register, login, closeRegisterDialog, closeLoginDialog, ... }; 

index.js.

 //index.js window.pageEvents = { closeLogin: shared.closeLoginDialog, showLogin: shared.showLoginDialog, closeRegister: shared.closeRegisterDialog, showRegister: shared.showRegisterDialog, login: shared.login, register: shared.register, signout: shared.signOut }; 

▍Vue


Vue . , .

 Vue.component("login-dialog", { data: function() {   return {     username: "",     password: ""   }; }, props: ["toggleLoggedIn"], template: `<dialog id="login-dialog" class="mdl-dialog">     <h4 class="mdl-dialog__title">Login</h4>     <div class="mdl-dialog__content">       <div class="mdl-grid center-items">         <!-- Simple Textfield -->         <div class="mdl-textfield mdl-js-textfield">           <input v-model="username" class="mdl-textfield__input" type="text" id="login-username">           <label class="mdl-textfield__label" for="login-username">Username</label>         </div>       </div>       <div class="mdl-grid center-items">         <!-- Simple Textfield -->         <div class="mdl-textfield mdl-js-textfield">           <input v-model="password" class="mdl-textfield__input" type="password" id="login-password">           <label class="mdl-textfield__label" for="login-password">Password</label>         </div>       </div>       <div class="mdl-grid center-items">         <!-- Simple Textfield -->         <div class="mdl-textfield mdl-js-textfield">           <span id="login-error"></span>         </div>       </div>     </div>     <div class="mdl-dialog__actions">       <button @click="closeLogin" type="button" class="mdl-button close">Cancel</button>       <button @click="login" type="button" class="mdl-button">Login</button>     </div>   </dialog>`, methods: {   closeLogin: function() {     const loginDialog = document.querySelector("#login-dialog");     dialogPolyfill.registerDialog(loginDialog);     loginDialog.close();   },   login: function(event) {     hoodie.account       .signIn({         username: this.username,         password: this.password       })       .then(() => {         this.toggleLoggedIn();         this.closeLogin();       })       .catch(error => {         console.log(error);         document.querySelector("#login-error").innerHTML = "Error loggin in";       });   } } }); 

data , props , template methods , Vue.component() .

, , Vue .

 //index.html <login-dialog v-bind:toggle-logged-in="toggleLoggedIn"></login-dialog> 

.

, , Vue. , , . , - Push API .

总结


-, JS, Vue.js. HTML, CSS JavaScript (jQuery), Vue . ES6 , .

Vue , , . , , , Vue. , , Vue .

, JS. — , Vue.

亲爱的读者们! - ?

Source: https://habr.com/ru/post/zh-CN413311/


All Articles