关于web开发:用云开发Webify5分钟上线新网站

用最简略的形式,带你上线本人的网站!大家好,我是鱼皮。 置信每位学编程的同学都想要领有一个本人的网站,比方集体博客,能够拿来记录本人的学习过程、分享本人的文章、展现作品等,从而激励本人继续学习和总结。 那么明天这篇文章,指标很简略,我要用 新技术 带 所有同学 从 0 到 1 疾速上线一个本人的网站! 给我 5 分钟,我给你全世界。 上线网站极简教程让咱们先来理解下传统的上线网站流程。 传统形式如果咱们要上线集体博客网站,供其他同学拜访,那么须要经验如下步骤: 筹备一份集体博客网站的源代码购买一台有公网 IP 的服务器把网站文件放到服务器上,并装置 web 服务器软件提供网页拜访能力购买一个域名配置 DNS 解析,把域名指向服务器的 IP 地址如果要进步网站访问速度,自行购买 CDN流程图如下: 听起来就感觉麻烦,而且这一套流程下来起码也要 1 个小时。这也是为啥很多同学只是有上线集体网站的想法,却从未实现。 然而,昨天我却只用 5 分钟,就上线了本人的网站,怎么做到的呢? 上面引出明天的配角 Webify 。 WebifyWebify 是腾讯云提供的 一站式 Web 利用托管服务,帮忙大家极速开发、部署、上线网站我的项目。 什么是一站式呢? 就是一条龙服务,只有你有一套网页代码,无论是动态、动静网站还是其余类型的 web 利用,都能应用 Webify 傻瓜式部署。由它提供服务器、默认域名、自定义域名、HTTPS、CDN 减速,晋升 Web 利用的性能和安全性。 换言之,如果应用 Webify 上线集体博客,你只须要: 筹备一份集体博客网站的源代码进入 Webify 控制台,抉择源码和配置一键公布流程大大精简了! 此外,Webify 还提供基于 Git 工作流的 DevOps 流程,每次批改代码都能主动从新构建部署,不必再登录服务器本人操作了! 听起来挺爽,上面咱们一起试着用 Webify 上线集体博客。 Webify 实战地址:https://cloud.tencent.com/product/webify首先进入 Web 利用托管平台,新建一个利用。 ...

July 27, 2021 · 1 min · jiezi

关于web开发:Angular都2021年了你为啥还没用Angular

摘要:数据绑定是将应用程序UI或用户界面绑定到模型的机制。应用数据绑定,用户将可能应用浏览器来操纵网站上存在的元素。本文分享自华为云社区《什么是Angular数据绑定及其实现形式?》,原文作者:Yuchuan 。 Web开发须要模型和视图之间的数据同步。这些模型基本上蕴含数据值,而视图则解决用户看到的内容。因而,如果您想晓得这在Angular中是如何产生的,这篇无关Angular数据绑定的文章将为您提供帮忙。 上面提到的是此处探讨的主题: What is Data Binding?Types of Data Binding in AngularOne-way Data BindingInterpolationProperty BindingEvent BindingTwo-way Data Binding什么是数据绑定?数据绑定是将应用程序UI或用户界面绑定到模型的机制。应用数据绑定,用户将可能应用浏览器来操纵网站上存在的元素。因而,无论何时更改了某些变量,该特定更改都必须反映在文档对象模型或DOM中。 在Angular中,数据绑定定义了组件与DOM之间的交互。从AngularJS始终到最新的Angular 9版本,数据绑定是所有Angular版本的一部分。 Angular中的数据绑定类型Angular容许单向和双向数据绑定。单向数据绑定是一种简略的数据绑定类型,您能够在其中通过模型来操纵视图。这意味着,对Typescript代码进行的更改将反映在相应的HTML中。在Angular中,单向数据绑定是通过以下形式实现的: Interpolation or String InterpolationProperty bindingEvent binding另一方面,双向数据绑定容许以如下形式同步数据:能够应用模型更新视图,而能够应用视图更新模型。这意味着您的应用程序将可能在组件类及其模板之间共享信息。 单向数据绑定在单向数据绑定中,数据仅沿一个方向流动,即从模型流向视图。如前所述,Angular中的单向数据绑定能够为三种类型,即插值,属性绑定和事件绑定。 Interpolation Binding插值绑定用于从TypeScript代码(即从组件到视图)返回HTML输入。在此,模板表达式在双花括号内指定。通过插值,能够将字符串增加到HTML元素标签之间以及属性调配内的文本中。这些字符串是应用Template表达式计算的。 例子: <h1>{{title}}</h1> Learn <b> {{course}}</b> with Edureka. 2 * 2 = {{2 * 2}} <div><img src="{{image}}"></div>此代码的Typescript局部如下: export class AppComponent { title = 'Databinding'; course ='Angular'; image = 'paste the url here'}输入: component属性在两个花括号之间指定。Angular将用与该组件属性关联的字符串值替换该组件属性。依据须要能够在不同的中央应用。角度将插值转换为属性绑定。 Angular还容许您配置插值定界符,并应用您抉择的内容代替两个花括号。能够应用组件元数据中的插值选项来实现此操作。 模板表达式 模板表达式位于两个大括号内,并且它们产生一个值。Angular将执行该表达式,而后将特定的表达式调配给绑定指标的属性,例如HTML元素,组件或指令。 留神:插值括号之间的2 * 2是模板表达式。 属性绑定在“属性绑定”中,值从组件的属性流入指标元素的属性。因而,属性绑定不能用于从指标元素读取或提取数据或调用属于指标元素的办法。元素引发的事件能够通过事件绑定进行确认,事件绑定将在本文稍后介绍。 ...

May 7, 2021 · 1 min · jiezi

关于web开发:实战丨Web云开发项目TodoList待办事项

背景TodoList利用,是面向零根底同学的疾速入门利用。你能够一行代码实现TodoList的本地化搭建,如果你想要网络同步你的Todo数据,在多个设施之间实时同步共享,云开发构建仅需100行。 体验地址:https://acc.cloudbase.vip/todo/ 此我的项目实用于零根底用户体验应用,通过肯定的模块伎俩粗放了整体编码。如果想要深刻学习请把握js、html、css等编程技术,自主解析模块中的代码(均为入门原生代码)如果你不想执行以下步骤翻看代码,能够间接点击下方按钮一键部署 一、构建本地化TodoList在本地任意中央新建文本文件,在文件中填入如下内容: <script src="https://acc.cloudbase.vip/todo/src/todo.js" charset="utf-8"></script>保留,并将后缀改为html,命名为index.html【留神:mac用户举荐应用无格局文本编辑】 应用浏览器关上此html文件,浏览器显示如下,即为失常。 如此,你就通过一行代码实现了本地化Todo利用的构建。通过此利用,你能够回车新增一条待办,也能够以勾选已实现,批改事项内容,删除事项;当页面敞开再次加载时依然保留待办事项。 二、将本地TodoList公布,给其他人应用咱们只在本地构建了这个利用网站,如何将这个利用分享给其他人呢? 咱们须要将这个利用网站公布到云开发动态网站托管中 关上云开发控制台,新建一个按量计费环境(如果已有按量计费环境则间接应用,跳过此步) 按量计费环境创立结束后,个别主动开明动态网站托管服务,如果未开明点击开明即可。 点击上传文件,将上一步的index.html抉择上传 上传完毕后,点击上图配置信息中的【默认域名】,即可在公网环境下拜访Todo利用网站。 默认域名可供您疾速验证业务,如您须要对外正式提供网站服务,请绑定您已备案的自定义域名。三、为Todo利用构建后盾服务以上一行代码实现的繁多利用网站只能做到在本地进行Todo记录,当更换设施时,无奈做到同步,接下来,咱们来构建后盾服务,实现同步需要。 关上云开发控制台,找到上一步操作的环境,关上数据库,新建todo汇合,如下图所示: 关上环境-登录受权,开启邮箱登录,如下图所示: 开启后点击左边【配置发件人】,参考配置QQ邮箱进行配置。 随后,点击左边【利用配置】,填写一下利用名称,如下图所示 配置实现后,将你的云环境ID复制保留,填入下步骤代码中 关上之前本地构建的index.html,填充内容如下所示 <script src="https://acc.cloudbase.vip/todo/src/todo.js" charset="utf-8"></script><script src="https://acc.cloudbase.vip/todo/src/login_util.js" charset="utf-8"></script><script src="https://imgcache.qq.com/qcloud/tcbjs/1.10.8/tcb.js"></script><script> let uid = null; const app = tcb.init({ env: "替换本人的云开发环境ID" }) const auth = app.auth({ persistence: "local" }); const db = app.database(); window.onload = function () { LO.init(); TODO.init(); } LO.Done = function () { uid = app.auth().hasLoginState().user.uid; db.collection('todo').doc(uid).get().then(res => { if (res.data.length == 0) { db.collection('todo').add({ _id: uid, list: TODO.todo, time: new Date() }).then(res => { console.log(res); watchtodo(); }) } else { console.log(res); TODO.todo = res.data[0].list; TODO.todoinit(); watchtodo(); } }) app.callFunction({ name:'todo_getNumber' }).then(res=>{ document.getElementById('model').innerHTML+=`<p class='bottom-des'>共${res.result}人应用云开发TODO</p>` }) } TODO.itemChange = function (id, type, des) { if (type === 'add') { if (des != null) { app.uploadFile({ cloudPath: `todo/${uid}/${TODO.todo[id].file}`, filePath: des }).then((result) => { console.log(result) TODO.todo[id].file = result.fileID updatetodo() }); } else { updatetodo() } } else if (type === 'delete') { if (TODO.todo[id].file != null) { app.deleteFile({ fileList: [TODO.todo[id].file] }).then((result) => { delete TODO.todo[id] console.log(result) updatetodo() }); } else { delete TODO.todo[id] updatetodo() } } else { updatetodo() } } TODO.downLoadfile = function (file) { app.downloadFile({ fileID: file }) } function updatetodo() { db.collection('todo').doc(uid).update({ list: db.command.set(TODO.todo), time: new Date() }).then(res => { }).catch(e => { console.log(e); }) } function watchtodo() { db.collection('todo').where({ _id: uid }).watch({ onChange: (snapshot) => { if (snapshot.msgType != "INIT_EVENT") { TODO.todo = snapshot.docs[0].list; TODO.todoinit(); } }, onError: (error) => { alert('远端数据库监听失败!'); } }); } </script>保留文件,从新上传至动态网站托管中,如此一个有后盾服务的Todo利用便构建实现了,依然关上配置信息中的【默认域名】(如果有缓存,能够在链接后加 ?123 等随机数),关上后如下图所示: ...

February 2, 2021 · 2 min · jiezi

关于web开发:Web开发技术架构图

Web开发技术架构图大型web零碎架构动静利用,是绝对于网站动态内容而言,是指以c/c++、php、Java、perl、.net等服务器端语言开发的网络应用软件,比方论坛、网络相册。1、学习Web开发原理,包含MVC/MTV等Web框架; 2、学习Django Web框架,从技术原理到我的项目实际; 3、学习Djan... 软件开发周期软件生命周期(Software Life Cycle,SLC)是软件的产生直到报废或停止使用的生命周期。软件生命周期内有问题定义、可行性剖析、总体形容、零碎设计、编码、调试和测试、验收与运行、保护降级到废除等阶段一个软件产品或软件系统也要经验孕育、诞生、成长、成熟、兴起等阶段,个别称为软件生存... 软件开发流程图软件开发流程即软件设计思路和办法的个别过程,包含对软件先进行需要剖析,设计软件的性能和实现的算法和办法、软件的总体结构设计和模块设计、编码和调试、程序联调和测试。软件我的项目开发流程图是用来详细描述了软件在开发过程中产品调研、设计、开发、测试等各个阶段中各个角色,蕴含产品经理、研发、测试、用户等需... 产品开发流程图产品开发流程(Product Development Process)产品开发流程是指企业用于想像、设计和商业化一种产品的步骤或流动的序列。产品开发流程波及的人员从产品经理到设计师、前端、后端等等一系列人员,这篇文章次要对于产品开发的残缺流程,心愿对各个工作岗位上的人有借鉴意义。很多产品经理不... 前台登录注册流程图1.页面字段,手机号,输入框;,图形验证码,输入框+验证码图片,短信验证码,输入框。2.默认状态,默认【获取验证码】按钮可点,【登录】按钮不可点。3.未输出状态,首先从手机号开始判断,当手机号/图形验证码未输出时,点击【获取验证码】。4.验证输出内容,~若手机号/图形验证码已输出时,点击【获取... 程序设计流程图遵循这种办法的程序设计,就是结构化程序设计。相应地,只有规定好三种根本构造的流程图的画法,就能够画出任何算法的流程图。程序设计流程图,流程图是一款网络图绘制软件,新鲜玲珑,功能强大,能够很不便的绘制各种业余的业务流程图/程序流程图/数据流程图/网络拓扑图,操作简略,一键绘制.剖析问题,对于承受... 程序流程图程序流程图又称程序框图,是用对立规定的规范符号形容程序运行具体步骤的图形示意。程序框图的设计是在解决流程图的根底上,通过对输入输出数据和处理过程的详细分析,将计算机的次要运行步骤和内容标识进去。程序根本构造的流程图实例解说,不论什么程序设计语言,程序设计都有3种根本构造:程序构造、抉择构造和循... 算法流程图设计算法是程序设计的外围。为了示意一个算法,能够用不同的办法。罕用的有自然语言,流程图,伪代码,PAD图等。这其中以特定的图形符号加上阐明,示意算法的图,称为算法流程图。算法流程图包含传统流程图和构造流程图两种。流程图就是一种形容算法的图形化形容,用流程图能够清晰地形容出算法的思路和过程。众所... 领取零碎性能架构图领取业务的根底零碎的复杂性和稳定性是领取业务是否可能及时平安解决的基本,该领取零碎性能架构图收集了支付宝的零碎架构。残缺的领取零碎整体架构! 从产品分类、模块性能和业务流程,理解领取产品服务的设计。领取零碎要合并合规性、易用性、安全性为一体,在后期设计时肯定要综合思考。领取零碎架构图为通用领取... 研发流程图产品研发流程图我的项目内容需要提交 责任部门市场部、运营部、产品部、 总经理及公司其余领导层,程序、职责阐明需要提交根据: 领导层——战略规划与指标 市场、运营部。一个产品的研发须要多个不同工种配合实现,如果没有好协同机制必然引起凌乱,造成产品研发的迁延:1.产品研发布局阶段。公司最高决策层依据客...

September 24, 2020 · 1 min · jiezi

后端程序员使用Dreamweaver与Bootstrap所见即所得快速编写前端页面

作为后端程序员我不懂css啊,只是花了几分钟简单的了解了下Bootstrap栅格布局,这里介绍使用Dreamweaver所见即所得快速编写前端页面,方便后端人员做自己的项目。 安装好Dreamweaver后创建空白文件: 创建空白文件后,选择live模式: 窗口布局改成standard模式: 切换出Bootstrap组件: 先在DOM中点击你要插入位置附近的元素,然后点击要被插入的Bootstrap组件,比如我要navbar之前插入navigation,我用数字标出点击顺序: 得到最终结果:

May 3, 2019 · 1 min · jiezi

Web 开发学习笔记(6) --- 前端开发之 HTML5

前言通过之前的文章, 我们已经搭好了 webapp 的雏形, 不过到目前为止, 我们的前端界面比较简单, 为此, 我们要学习前端的知识, 然后对界面进行改进.前端的内容可以分为 HTML CSS JavaScript 三部分, 我们首先学习 HTMLHTML5简介什么是 HTML5 ———— 第五代 HTML 语言为什么学 H5所有主流浏览器都支持 h5, chrome, firefox, safari, IE9+H5 改变了用户与文档的交互方式, 尤其是多媒体, 替代了传统的 flash, 多媒体标签 video, audio, canvas增加了其他新特性语义特性、本地存储、网页多媒体(音视频), 二位三维变换, 特效(过渡, 动画)相比于 h4, 抛弃了不合理不常用的标签和属性, 增加了一些标签和属性, h5代码更加简洁(<!doctype html>, <meta charset=“UTF-8”)HTML5 语义化标签header, nav, main, article, aside, footer. 更多标签可以查看这里 HTML Tags语义化标签的例子html<!doctype html><html><head> <meta charset=“UTF-8”> <title>Title</title> <link rel=“stylesheet” href=“index.css”></head><body> <!– 语义化标签 –> <header>This is header</header> <nav>This is nav</nav> <main> <article>article</article> <aside>aside</aside> </main> <footer>footer</footer></body></html>css*{ /padding: 0px; margin: 0px;/}header{ width: 100%; height: 100px; background-color: red;}nav{ width: 100%; height: 36px; background-color: green;}main{ width: 100%; height: 240px; background-color: #ccc;}main > article{ width: 80%; height: 100%; background-color: purple; float: left;}main > aside{ width: 20%; height: 100%; background-color: pink; float: right;}footer{ width: 100%; height: 80px; background-color: skyblue;}参考资料w3schools, HTML黑马程序员 2018版Html5+Css3由浅入深教程 ...

February 26, 2019 · 1 min · jiezi

Web 开发学习笔记(5) --- 抽象出 Page 类

回顾通过前几篇文章的内容, 我们已经搭建了基于 Flask 框架的一个简单的 Web 应用, server.py 的代码如下from flask import Flask, make_responsefrom flask.views import MethodViewapp = Flask(name)class IndexHandler(MethodView): def get(self): resp = make_response(‘It is a GET request’) resp.headers[‘Strict-Transport-Security’] = ‘max-age=15768000; includeSubDomains; preload’ return respif name == ‘main’: app.add_url_rule(’/’, view_func=IndexHandler.as_view(‘index’)) context = (’./server.cer’, ‘./server.key’) app.run(port=443, host=‘0.0.0.0’, debug=True, threaded=True, ssl_context=context)抽象出 Page 类由于我们在以后的每个页面的 Handler 中都要用到 HSTS, 以及其他一些共用的特性, 我们将其提取出来, 抽象成一个 Page 类, 修改 server.py 如下from flask import Flask, make_responsefrom flask.views import MethodViewapp = Flask(name)class Page(MethodView): def render(self, resp): resp.headers[‘Strict-Transport-Security’] = ‘max-age=15768000; includeSubDomains; preload’ return respclass IndexHandler(Page): def get(self): content = ‘It is a GET request’ return self.render(content)if name == ‘main’: app.add_url_rule(’/’, view_func=IndexHandler.as_view(‘index’)) context = (’./server.cer’, ‘./server.key’) app.run(port=443, host=‘0.0.0.0’, debug=True, threaded=True, ssl_context=context)提取其他共用特性get_args()args 一般出现在 GET 请求中, 比如 Google 搜索时地址栏出现的 https://www.google.com/search?q=awesome, 其中 ? 后面的内容就是 args, 以 key-value 的形式出现. 对应刚才的例子, key 就是 q, value 就是 awesome. 如果有多组 key-value, 中间就用 & 连接, 如 ?q=awesome&type=server. 这种形式很容易让我们联想到 Python 的字典结构 dict. 根据 文档, Flask 是通过 ImmutableMultiDict 来存储 args 的. 我们可以在 Page 类中增加 get_args() 方法from flask import requestclass Page(MethodView): def get_args(self, key): return request.args.get(key)这样, 我们就可以通过调用 get_args() 来获取用户请求中的参数了, 举个栗子class AwesomeHandler(Page): def get(self): if self.get_args(‘q’) == ‘awesome’: # do something return ‘This is an awesome page!‘同样地, 我们可以在 Page 类中增加其他特性, 如 get_date(), get_referer(), get_cookies() 等等, 编写好的 Page 类如下from flask import requestfrom datetime import datetime, dateclass Page(MethodView): def render(self, resp): resp.headers[‘Strict-Transport-Security’] = ‘max-age=15768000; includeSubDomains; preload’ return resp def get_args(self, key): return request.args.get(key) def get_date(self, year=0, month=0, day=0): if year and month and day: return date(year, month, day) else: return date.today() def get_referer(self): return request.headers.get(‘referer’) def get_cookies(self): return request.cookies参考资料http://flask.pocoo.org/docs/1… ...

February 16, 2019 · 2 min · jiezi

Koa 系列 —— Koa 中间件机制解析

上一篇讲了如何编写属于自己的 Koa 中间件,本篇将根据原理实现一个简单的中间件处理函数,并对 Koa 中间件处理函数 compose 函数进行源码解析。1. compose 函数简单实现Koa 中间件采取的是中间件洋葱模型,具体原理可见如何编写属于自己的 Koa 中间件。本质就是将中间件嵌套执行:function middleware0(){ console.log(‘middleware0’)}function middleware1(){ console.log(‘middleware1’)}// 将两个中间件嵌套执行middleware0(middleware1())当然实际上更复杂,还要考虑中间件的异步执行和中间件如何进行嵌套。Koa 中异步处理在 Koa1 中使用的是 generator + co.js,在 Koa2 中使用的是 async/await,我们本次采用 async/await 来处理异步。中间件的嵌套可以通过将中间件当参数传递来实现嵌套。据此我们对上面的代码进行进一步加工:ps:Node7.6+ 支持 async/awaitasync function middleware0(next){ console.log(‘middleware0’) await next()}async function middleware1(next){ console.log(‘middleware1’)}// 将两个中间件嵌套执行middleware0(middleware1)Koa 中通过 compose 函数对中间件的进行处理。compose 函数参数为 middleware 的数组, middleware 数组成员是通过 use 方法添加的中间件。下面写个简单的 compose 函数,来实现多个中间件的处理:async function middleware0(next){ console.log(‘middleware0’) await next() console.log(‘middleware0 end’)}async function middleware1(next){ console.log(‘middleware1’) await next() console.log(‘middleware1 end’)}async function middleware2(next){ console.log(‘middleware2’) await next() console.log(‘middleware2 end’)}/** * @param {Array} 中间件数组 /function compose (middleware) { // 从第一个中间件开始执行 return dispatch(0) function dispatch(i){ // 获取第 i 个中间件 fn = middleware[i] // 获取不到中间件,则直接返回结束 if(!fn) return // 执行第 i 个中间件,并传入第 i + 1 个中间件 return fn(() => dispatch(i + 1)) }}// 执行compose([middleware0, middleware1, middleware2])2. 源码解析我们已经简单实现了一个 compose 函数,现在来看下 Koa 中源码的实现。Koa 中的 compose 函数已经提取到 koa-compose 包中,其中的核心代码如下:/* * @param {Array} 中间件数组 * @return {Function} /function compose (middleware) { // 判断是否为数组,不是则抛出异常 if (!Array.isArray(middleware)) throw new TypeError(‘Middleware stack must be an array!’) // 判断 middleware 数组中的中间件是否为函数,不是函数抛出异常 for (const fn of middleware) { if (typeof fn !== ‘function’) throw new TypeError(‘Middleware must be composed of functions!’) } /* * 此处先不执行中间件,直接返回函数 * 统一在外面进行异常判断,再开始执行中间件 / return function (context, next) { let index = -1 // 从第一个中间件开始执行 return dispatch(0) function dispatch (i) { // 同一个中间件多次调用 next 抛出异常 if (i <= index) return Promise.reject(new Error(’next() called multiple times’)) index = i // 获取第 i 个中间件 let fn = middleware[i] /* * 中间件执行结束,检查是否有传入 next 回调函数 * 此 next 并非中间件执行的 next 参数 / if (i === middleware.length) fn = next /* * 所有的返回都是Promise对象 * Promise对象可以保证中间件和返回请求对象之间的执行顺序 / if (!fn) return Promise.resolve() try { // 执行第 i 个中间件,并传入第 i + 1 个中间件 return Promise.resolve(fn(context, dispatch.bind(null, i + 1))); } catch (err) { return Promise.reject(err) } } }}通过解析可以发现,源码相对于我们的实现更加健全:更完善的异常处理在执行前统一对传入参数进行检查多次执行 next 函数抛出异常处理等最终返回结果 Promise 化,保证中间件和整个处理函数在 Koa 中的执行顺序,具体可参考下面 Koa 源码片段:/* * application.js * fnMiddleware(ctx) 就是 compose 函数返回的函数,默认不传入 next 参数 * Promise 保证中间件,handleResponse 执行顺序。 */fnMiddleware(ctx).then(handleResponse).catch(onerror)3. 小结从最开始的编写 Koa 中间件,到现在阅读 compose 函数源码,Koa 中间件机制并不复杂,了解之后,我们可以运用、编写更合适的中间件,构建自己的 Koa 应用。本文首发于公众号,更多内容欢迎关注我的公众号: 阿夸漫谈 ...

January 19, 2019 · 2 min · jiezi

vue.js的项目实战

欢迎大家前往腾讯云+社区,获取更多腾讯海量技术实践干货哦本文由蔡述雄发表于云+社区专栏需求背景组件库是做UI和前端日常需求中经常用到的,把一个按钮,导航,列表之类的元素封装起来,方便日常使用,调用方法只需直接写上<qui-button></qui-button>或者<qui-nav></qui-nav>这样的代码就可以,是不是很方便呢,接下来我们将要完成以下页面:这是我们组件库的首页,包含三个子页面,按钮页面、列表页面、导航页面;点击进去子页面会由路由来配置。先看我们的目录结构:pages目录存放我们的页面,包括首页和三个子页面;components目录存放我们的具体组件,包括按钮组件,箭头组件,列表组件和导航组件(组件和页面其实是一样的文件类型,只是由于功能不一样,我们就叫不同的称呼)先看路由配置的代码吧!路由配置import Vue from ‘vue’import Router from ‘vue-router’// 引用页面模板->供路由使用import index from ‘../pages/index.vue’import pageQuiButton from ‘../pages/pageQuiButton.vue’import pageQuiList from ‘../pages/pageQuiList.vue’import pageQuiNav from ‘../pages/pageQuiNav.vue’Vue.use(Router)export default new Router({ routes: [ { path: ‘/’, name: ‘index’, component: index }, { path: ‘/btn’, name: ‘btn’, component: pageQuiButton }, { path: ‘/list’, name: ’list’, component: pageQuiList }, { path: ‘/nav’, name: ’nav’, component: pageQuiNav } ]})有了上一篇的分析之后,这里应该很容易看出来几个路由地址首页:http://localhost:8080/#/按钮子页:http://localhost:8080/#/btn列表子页:http://localhost:8080/#/list导航子页:http://localhost:8080/#/nav具体每一页的内容分别对应每一页的.vue文件,不知大家是否还记得入口页App.vue,这个文件承载着一些公用的元素,还有就是一个路由容器,我们的首页index.vue到时候也是挂载在路由容器中的,看看App.vue的代码入口页App.vue<template> <div id=“app”> <h1 class=“page-title”><a href="#/">开发组件库</a></h1> <router-view></router-view> </div></template><script> export default { name: ‘app’}</script><style scoped> @import ‘./assets/css/App.css’;</style>简单分析一下入口页的代码,h1标签是一个公用元素,也就是说到时候每个子页面都会带着这个h1,他的作用就是方便我们快速回到首页,子页面的内容会注入到router-view中。这里值得关注的地方是style标签,我们可以在style标签里面直接写样式,也可以直接引入一个样式文件,scoped关键字表示这个样式是私有的,也就是说,即使两个组件写着一样的#app{}样式也不会冲突,程序会加上命名空间,这也就是为什么在script标签中有个name参数。首页index.vue<template> <div class=“mod-module mod-parallel”> <div class=“img-list type-full”> <div class=“img-box”> <p class=“img-item”> <a class=“page-link” href="#/btn">按钮</a> </p> </div> <div class=“img-box”> <p class=“img-item”> <a class=“page-link” href="#/list">列表</a> </p> </div> <div class=“img-box”> <p class=“img-item”> <a class=“page-link” href="#/nav">导航</a> </p> </div> </div> </div></template><style scoped> @import ‘./css/index.css’;</style>首页的代码也是非常简单,和我们平时写html差不多,就是几个跳转链接跳到对应的子页面,程序运行的时候,会将<template>标签里面的内容都注入到App.vue页面中的router-view标签中,从而实现无刷新的路由跳转。从下面的内容开始,我们的知识将会深入一些。我们先不急着看其他几个子页面,因为子页面里面只是引用对应的组件,所以我们先从组件开始入手。按钮组件quiButton.vue<template> <button class=“qui-btn”> <span>{{msg}}</span> </button></template><script> export default { data:function(){ return { msg:‘下载’ } } }</script><style scoped> @import ‘./css/reset.import.css’; @import ‘./css/qui-btn.import.css’;</style>按钮组件很简单,就是一个正常的button标签,script标签中暴露这个组件的data属性(data是Vue的属性值,不是乱写的~~)。当按钮组件被初始化的时候,msg自定义属性会被绑定到<span>标签中的{{msg}}中,两个花括号用来绑定属性,这种写法学过模版化前端代码的人应该都比较熟悉。这里需要注意一个地方,如果不是组件的话,正常data的写法可以直接写一个对象,比如data:{ msg : ’ 下载 ’ },但由于组件是会在多个地方引用的,JS中直接共享对象会造成引用传递,也就是说修改了msg后所有按钮的msg都会跟着修改,所以这里用function来每次返回一个对象实例。这就是一个非常简单的按钮组件,结构、样式+文案。这时候问题来了,按钮中的文案我希望可以异化,不能每次都初始化一个叫做“下载”文案的按钮吧,希望可以以属性的方式来使用,比如这样子写就可以改变我们的按钮文案:<qui-btn msg=“确定” class=“small”></qui-btn>没问题,属性的接口暴露只需要写在prosp里面就可以了,如下所示修改下script标签的内容:<script> export default { props: { msg: { default: ‘下载’ } } }</script>把属性写在props里面,就可以暴露给其他页面调用了,在组件中,props是专门用来暴露组件的属性接口的,这里给了一个默认值‘下载’,后面我们要使用的话,只需要<btn msg=“确认”></btn> 就可以修改按钮的默认文案了。我们在上一篇文章的开头就讲了Vue是数据驱动模式的,当我在btn结构写上msg=“确认"的时候,对应script里面的msg属性就会自动修改了。按钮事件按钮总少不了点击事件吧,那在Vue中怎么绑定事件呢,用methods属性,看下代码:<template> <button class=“qui-btn” v-on:click=“btnClickEvent”> <span>{{msg}}</span> </button></template><script> export default { props: { msg: { default: ‘下载’ } }, methods: { //绑定事件的关键代码 btnClickEvent: function(){ alert(this.msg); } } }</script>methods属性中可以写任何的自定义函数,写完之后绑定的方式也很简单,在button上写关键字v-on:click,把对应的事件写上就可以了,以上代码实现的就是点击按钮弹出按钮中的文案,v-XXX是Vue里的一些关键字,叫做指令,我们后面会慢慢学到更多的指令;v-on:click可以缩写为@click,当然还有其他的事件比如v-on:tab等等;使用按钮组件pageQuiButton.vue现在我们大致做了一个按钮组件了,那么怎么调用它呢,去到我们的pageQuiButton子页面。//pageQuiButton.vue<template> <div id=“pageQuiButton”> <!–使用–> <qui-btn msg=“确定” class=“small”></qui-btn> </div></template><script> import quiBtn from ‘../components/quiButton.vue’ /引用/ export default { name: ‘pageQuiButton’, components: { ‘qui-btn’: quiBtn /注册自定义标签/ } }</script>从script开始解析,首先引入我们的组件赋值给变量quiBtn,使用时候直接将quiBtn作为对象的一部分写进components属性,这是Vue用来存储引用组件的关键字,同时对应我们自定义的标签 “qui-btn”,完成这些操作之后,我们就可以在template中使用自定义的按钮组件<qui-btn>上面也说了用msg属性来自定义按钮的文案。完成之后,我们就可以在页面中看到具体效果,点击按钮弹出对应的文案。上述我们将按钮事件写成默认的alert(this.msg),如果有些按钮想要异化怎么办。之前说了msg属性可以支持自定义,那么按钮的点击事件如何支持自定义呢?//pageQuiButton.vue//监听子组件的事件<qui-btn v-on:btnClickEvent=“doSth” msg=“我可以点击” ></qui-btn>上面的代码在引用组件的时候,注册了一个事件,这个btnClickEvent事件是之前我们在按钮组件中绑定到按钮的click事件中的,然后我们给这个事件一个自定义的方法doSth,同时,在script中声明这个自定义的方法如下://pageQuiButton.vue//页面中引用子组件并监听子组件的事件<script> import quiBtn from ‘../components/quiButton.vue’ export default { name: ‘pageQuiButton’, components: { ‘qui-btn’: quiBtn }, methods: { doSth: function(){ alert(‘你点击了组件的click:btnClickEvent’); } } }</script>专业一点的说,这种做法叫做监听,由引用方(暂且叫做父组件)监听子组件的内置方法;同时在子组件中,需要触发这个事件,以下是在子组件中的关键代码://quiButton.vue//子组件中的代码<script> export default { props: { msg: { default: ‘下载’ } }, methods: { btnClickEvent: function(){ alert(“先弹出默认的文案”); this.$emit(‘btnClickEvent’);//关键代码父组件触发自定义事件 } } }</script>这里的关键代码就是$emit,也叫触发机制,父组件监听,子组件触发。如果觉得绕,以下描述可能会比较好理解:小B(子组件)有一个电话号码(子组件注册的事件),有一天小B把电话号码告诉了小A(父组件),让小A打电话给他,于是小A就拨打了小B的电话号码(监听),这时候整个沟通流程没有结束,必须要小B接听了电话(触发),两人之间才算完成了打电话这件事情。完成这步之后,引用方(父组件)就可以给不同子组件调用不同的事件处理了:<qui-btn v-on:btnClickEvent=“doSth1” msg=“确定” ></qui-btn><qui-btn v-on:btnClickEvent=“doSth2” msg=“取消” ></qui-btn><script>/这里只是简单展示/ methods: { doSth1: function(){ alert(‘111’); }, doSth2: function(){ alert(‘222’); } }</script>给按钮加图标有时候单纯的文案异化还不够,比如一些按钮是图标+文字类型的,而且图标还可能不一样,那应该怎么办呢?如果按钮组件的结构除了开发时候预设的那些dom结构之外,允许我们在调用的时候添加一些自己想要的结构,那是不是解决了呢,是的,Vue早就为我们考虑了这一点,他就是slot标签。下面给我们的按钮组件加上一段结构//quiButton.vue<template> <button class=“qui-btn” v-on:click=“btnClickEvent”> <slot name=“icon”></slot><!–重点在这里–> <span>{{msg}}</span> </button></template>加入了关键字slot并赋予一个name值之后,我们再看看引用如何使用//pageQuiButton.vue<qui-btn msg=“下载” class=“with-icon”> <img slot=“icon” class=“ico” src=“xxx.png” /></qui-btn>img上有个关键字slot=“icon"对应组件中的name=“icon”,渲染的时候,会将img整个替换掉组件中的对应name的<slot>标签,其实很好理解,slot的翻译是插槽的意思,相当于把img这块内容插到一个名叫icon的插槽里面去。中场休息一下学到这里,我们已经学会了用props给按钮自定义文案,用on和emit给按钮自定义点击触发,用slot给按钮添加一些自定义结构。当你回头去翻文档的时候,你会发现props,事件,slot这三样刚好就是学习组件通讯中最最最关键的三个环节。将这三个环节以实际案例解析出来后,好像也没有那么难了吧!上述我们已经讨论了如何制作一个按钮组件,以及如何使用我们的按钮组件。接下来我们通过制作一个导航组件,来了解Vue中对于for循环的巧妙使用。导航组件quiNav.vue我们将完成这样一个导航组件,点击导航中的tab,可以给当前tab加上一个active类,同时切换底部的黄色滑条,并且输出当前tab的文案,同时支持自定义事件。由于在现实项目中,我们导航的tab个数是不定的,所以制作组件的时候,我们希望可以暴露一个属性来支持导航的tab个数,而tab的长相和应用其实是一样的,那么这时候我们可以用一个for循环来输出每一个tab。先看看关键代码://quiNav.vue<template> <div class=“qui-nav nav-type-1”> <a v-for="(item, index) in items” ><!–关键代码v-for–> <span class=“nav-txt”>{{item.text}}</span> </a> </div></template><script> export default { data:function(){ return { items:[ { text: ‘首页’, active : true }, { text: ‘列表’, active : false }, { text: ‘关于’, active : false }, { text: ‘招聘’, active : false } ] } } } }</script>该段代码的关键地方在于a标签上v-for关键字(还记得我们在前面说过的v-on绑定事件吗,v-XXX关键字是Vue预留的)可以把它理解为js中的for in 循环,items是我们在data里面定义的对象(还记得为什么data要写在function中返回吗?)。v-for="(item,index) in items"暴露了item和index两个接口,这是Vue提供的,代表items中的每一项以及该项对应的下标,接着我们就可以在标签中使用绑定{{item.text}}了。这段代码理解了之后,我们再延伸一个动态添加class的概念。我们希望每个tab都有默认的class类名(比如nav-item类),在点击每个tab的时候,当前tab添加active类,其他的tab删除这个active类。在Vue怎么实现呢?动态类名//quiNav.vue<template> <div class=“qui-nav nav-type-1”> <a v-for="(item, index) in items” :class="[commonClass,item.active ? activeClass : ‘’]" > <span class=“nav-txt”>{{item.text}}</span> </a> </div></template><script> export default { data:function(){ return { commonClass:’nav-item’, activeClass:‘active’, items:[ …//数据 ] } } }</script>在template中添加了一句关键代码:class="[commonClass,item.active ? activeClass : ‘’]":class给组件绑定一个class属性(类似jQuery中的attr方法),这里的写法是缩写,他的全拼应该是v-bind:(又一个v-XXX写法)。注意到最前面有个冒号,:class=XXX和class=XXX的区别在于不带冒号的是静态的字符串绑定,带冒号的是动态的变量绑定。我们给class绑定了一个数组,这个数组带有变量,先看commonClass,这个变量在data中定义了,然后数组的第二个元素是一个JS的三元运算符:item.active?activeClass:’’,当每个item中的active值为true时,绑定activeClass变量对应的类,如果为false,则为空。最后的结果是当item.active为true时候,tab的class值为’nav-item active’,当为false,就只有’nav-item’。上面的代码可以理解的话,那么我们切换tab的active类,就转换为修改每个item里面的active的值(再次体现数据驱动)。那么问题来了,怎么去修改每个item里面的active值呢?没错,给每个tab绑定一个点击事件,当点击事件触发的时候,修改当前tab对应item的active值。于是代码变成了如下:<template> <div class=“qui-nav nav-type-1”> <a v-for="(item, index) in items" :class="[commonClass,item.active ? activeClass : ‘’]" v-on:click=“navClickEvent(items,index)” > <span class=“nav-txt”>{{item.text}}</span> </a> </div></template><script> export default { data:function(){ return { commonClass:’nav-item’, activeClass:‘active’, items:[ { text: ‘首页’, active : true }, …… ] } }, methods:{ navClickEvent:function(items,index){ /默认切换类的动作/ items.forEach(function(el){ el.active = false; }); items[index].active = true; /开放用户自定义的接口/ this.$emit(’navClickEvent’,items,index); } } }</script>我们利用for循环给每个a标签绑定了一个click事件,对应methods中定义的navClickEvent,接收两个参数items和index(你也可以传人item和index,看个人代码喜好),然后当点击的时候,把items中的每个item.active置为false,把当前的tab的active值置为true,这样就可以动态切换active类了。最后再触发一次自定义事件(参考按钮制作自定义事件)。以上就是我们导航组件的内容了,回想下我们做了啥?for循环输出每个tab,为每个tab绑定动态的class类名,同时在点击事件中动态切换类(底部的小黄条其实是利用active类做的CSS)小结回顾下我们这一篇章都学了什么内容。页面路由的配置按钮组件自定义属性props按钮组件自定义事件 $on $emit按钮组件自定义子块slotfor循环实现导航组件动态类名上述内容已经基本上涵盖了组件的重要知识点,主要是父组件(页面)和子组件之间的调用和通讯(数据交互绑定),好好消耗一下我们会发现,其实Vue的总体逻辑思想和jQuery是一样的,毕竟最后都回归到javascript,只是由于代码设计角度的不同,我们可能看到和以前调用jQuery时候的写法不一致,但其实都有对方的影子在里面,相信理解了Vue的代码思想之后,以后我们学习React等其他类似的框架的时候,也会比较得心应手了。下一篇文章《包学会之浅入浅出Vue.js:结业篇》中,我们将会学习如何用多个组件来组成一个大的组件,也就是真正意义上的父子组件之间的关系。再忍耐一下,就可以出山了,新领域的大门就在前面,让我们大步往前跨吧。文末附上所有相关代码和官方文档地址~~~http://cn.vuejs.org/v2/guide/相关阅读【每日课程推荐】机器学习实战!快速入门在线广告业务及CTR相应知识 ...

November 15, 2018 · 3 min · jiezi