Giter Club home page Giter Club logo

alex2wong.github.io's People

Contributors

alex2wong avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar

alex2wong.github.io's Issues

vue.js 实践总结(二)Render 函数

上一篇说了项目搭建和结构,这篇说说vue 的render 函数,比较核心的概念。去年写过一点react,所以知道render 函数是用来创建虚拟dom 的,那个时候写 jsx 还是不亦乐乎的。列出几个问题作为这篇的结构:

  • render 函数的作用?
  • 组件中的render 函数什么时候执行?
  • 什么时候需要在组件中写 jsx ?

常遇到这个问题:

[Vue warn]: Failed to mount component: template or render function not defined

这个问题是由于当前写的组件没注册为vue 组件,或者组件定义中没有template/render,所以组件没法和具体的element 挂载到一起,无法完成渲染。

render 的作用

render 函数实际上是template 的底层方法,通过调用createElement(h)来创建dom节点,实际上作用就是负责组件视图渲染的!createElement是render的核心方法。Vue编译的时候会把template 编译为对应的render 方法,所以有了render方法就可以不写template 了!

看实例:

<template>
  <div class="right-panel">
     <div class="right-panel-header">{title}</div>
     <div class="right-panel-content">
        {content}
     </div>
  </div>
</template>

如果不写template,对应的render 则是

render(h) {
  return (
      <div class="right-panel">
        <div class="right-panel-header">{this.title}</div>
        <div class="right-panel-content">
          {this.content}
        </div>
      </div>
    );
}

从生命周期出发,render执行时机

与render 相关的生命周期

还是得把组件的生命周期搬出来,created 钩子函数是组件injection和reactivity 属性初始化后,比如props、data 初始化,后面关键的:如果有template,则把视图编译为render function,如果没有则直接调用被override 的render 方法创建虚拟dom节点,并且把组件对应的 htmlElement 替换为 组件的dom 结构和数据,最后触发mounted 钩子。

所以执行顺序是 beforeMount -- render(h, data) -- mounted .

什么时候需要定义render

上面那个实例,panel content 内容可以是外部传入的一段内容(this.$props.content),假如内容很复杂呢,假如这个panel 组件需要接受用户自定义的复杂content 呢? 这时候就需要接受外部传入的函数来渲染一段dom。 这样panel 只是个容器,把内容渲染交给外部模块,实际上是组件拆分和模块化的**,使得panel 组件可以更好的复用。

我们把panel 的render 函数改为可以接受外部函数:

render(h) {
    let contentNode = (<div>default content</div>);
    if (this.contentRender && this.contentRender instanceof Function) {
      contentNode = this.contentRender(h, this.data); 
// 把数据用外部函数来渲染成用户想要的结构
    }
    console.warn(`rendering...`);
    return (
      <div class="right-panel">
        <div class="right-panel-header">Panel Header</div>
        <div class="right-panel-content">
          {contentNode}
// 插入dom 结构
        </div>
      </div>
    );
  }

contenRender 的定义可以是这样的:

contentRender (h, data) { 
   return (<div>Current Data: {data['app']}</div>); 
},

总结

render 真的很有趣,其实际上就是jquery 时代的 创建dom,构建dom tree 的过程,但是更加的智能化、更优雅。 掌握了render ,就可以自由构建可复用的组件容器。建议详细阅读官方文档,非常有用。

一些思考:

开发一个前端项目,不仅仅是视图和组件逻辑,更重要的是数据服务,现代化前端几乎都是数据驱动的。因为一个app 在组件初始化时完成了数据和视图绑定,对视图的监听,随着app 的运行,实际上是不断变化的数据在驱动视图的变化。

基于MVC 的架构或 MVVM的架构,在不断写组件的过程中,我们不断反思该如何写一个组件,怎么把多个组件集成到一个复杂组件中,组件中的逻辑部分是否应该合理拆分出其他几个通用的模块/类

比如api service 单独处理api相关的,api service 里面的网络请求有可以单独出 network 层,为了方便替换net 请求库,还有许多通用的数据格式转换层,都是可以单独成类或者service的概念。

参考文章:
官方文档:渲染函数 & JSX
支持 jsx 语法的插件,transform-vue-jsx
被误解的MVC和被神化的MVVM,rethinking-mvc-mvvm

最近书单,技术总结

不知不觉已经五月了,2018年已经过去三分之一。
周末宅家突然想起自己费尽心思做的slider有另外一种简单一万倍的方法实现。。整个人都不好了。那一个多周写的代码几乎都付诸东流,这都怪做slider 前没有好好调研前人的方法 : (

看图:
flexbox 实现的slider 布局,线框

flexbox 实现的slider 布局

最后发现用原生的input[type=range] ,隐藏浏览器原生样式,直接改css 就可以。。还可以改造为垂直效果,HollyShiiiiit !

基于vue的 input range组件 Github代码
把代码放这里,希望有帮助, 基于原生组件直接修改样式是最简单的办法。
基于vue的slider组件,支持主题,垂直slidrer

最近书单

今年看书也比较慢,不过也算是看到几本不错的。

**《刷新:重新发现商业与未来》**下载地址:https://sobooks.cc/books/7821.html
作者:萨提亚·纳德拉,微软现任CEO。书中记录了作者在上任后对微软改革的思考,也是对技术的思考。作者也是是微软的云技术专家,曾经负责Bing搜索。跳出编程本身,看看大佬对于未来技术的思考,结合微软近几年的巨大进步,还有IBM 等大公司对云计算,量子技术的看好。
部分笔记:

  • 对于领导而言,通过命令达成的共识并不是真正的共识。任何机构建设都源于清晰的, 既能自上而下也能自下而上推动进步的愿景与文化。
  • 我们的世界已经不再是以个人计算机为中心的世界。计算变得无所不在

《把生命浪费在美好的事物上》
作者:吴晓波。书中记录了许多作者对当代社会问题的看法,自己的经历。特别是一些对社会问题的一击即中,简明地指出问题的本质,也记录了许多社会经济往事。很赞。
部分笔记:

  • 现代社会的复杂和规模使得一般人难以对他有清楚的把握。现代人一般从事一种单一的工作,... 他们很少认真涉入公众事务讨论。... 摘自书中《我的偶像李普曼》
  • 一切以经济为中心,一切以财富为标杆,所谓的智慧、快乐与价值都似乎是可以被量化的,而伦理道德则成为一种可有可无的奢侈品,他们的底线往往可以被轻易击穿。

作者提到了很多现实问题,作为一个程序员,更作为一名有觉悟的市民。我们有理由和责任去全面理智地思考

  • 我们的公立教育能否保证教育公平,教育减负是否推高了私立教育
  • 我们的塑料垃圾能否有效地控制?外卖行业如何合理控制塑料消耗?

最近计划

由于已经开始基于Vue 的项目,而Vue的生态足够丰富,有很多可以把vue app 封装为PWA,hybrid移动app 或者微信小程序的 工具或者框架,要感谢开源社区让我们可以简单地做出兼容更多平台的应用。

准备以最近写的贷款计算器为demo,改造为小程序或者native app.
还有就是写一两篇文章记录下 做UI 组件的心路历程。
最后准备看看吴军的书,和吴晓波一样关心社会经济的运行规律,也许技术人对于世界的思考方式有所不同。

吴军的书目录

babel 修改抽象语法树——入门与实践

问题由来

最近有个想法,之前用Angular2.x 的时候,官方提供了ng-cli 可以一键生成component、service、directive 等代码文件,并且还可以修改对应的routes 配置文件,使得组件自动加入app 的前端路由中(一键生成或修改数个文件)。这使得前端开发效率大为提高,我们不必再手动去创建那么多文件夹、文件,并且手动修改route 配置。但是vue-cli 没有提供这种功能,所以我们想要写个node.js 脚本去做这个工作。除了用正则替换的解决办法,更科学的实际上就需要用到修改代码抽象语法树的方法。

babel 编译过程

我们通常用 babel 去编译ES6/ES7 为ES5,以便于 js 脚本运行在各种浏览器上。这个编译的过程实际上是语法转换的过程,比如箭头函数转为函数表达式,this 的显式绑定等等。那么babel 在做这个工作的时候实际上经历了几个步骤,parse => transform (AST) => generate

https://www.sitepoint.com/understanding-asts-building-babel-plugin/

所以要想完成这几个步骤,babel 提供了几个实用工具(Babylon,babel-traverse,babel-generator),我们的思路就是找到route 配置表中该插入新路由的地方,插入新路由并且保存文件。
babel.transform 核心函数接受源代码字符串和options 作为输入,返回一个Object 包含几个属性:新的代码字符串,sourcemap,ast 语法树对象。

babel.transform("code();", options, function(err, result) {
  result.code;
  result.map;
  result.ast;
});

实践新增一个route对象

以下是等待修改的路由配置文件,

// './src/router.ts'
export default new Router({
  routes: [
    {
      path: '/',
      name: 'home',
      component: Home
    },
    {
      path: '/about',
      name: 'about',
      component: About
    }
    // to be append new route.
  ]
})

以下是通过 babel 修改route 配置文件的过程

var fs = require('fs');
let babel = require('babel-core');
let t = require('babel-types');
let template = require('@babel/template');
// 读取需要修改的源代码内容
var content = fs.readFileSync('./src/router.ts').toString();

const newRoute = {
  path: '/list',
  name: 'list'
  // component: ListComponent
};

// 定义一个 babel 插件,拦截并修改 routes 的数组表达式
let visitor = {
  ArrayExpression(path) {
    const elements = path.node.elements;
    console.warn(`routes number:  ${elements.length}`);
    // 新增一个构建出来的 route 对象
    elements.push(t.objectExpression([
      t.objectProperty(t.identifier('path'), t.stringLiteral(newRoute.path)),
      t.objectProperty(t.identifier('name'), t.stringLiteral(newRoute.name)),
      t.objectProperty(t.identifier('component'), t.identifier('ListComponent'))
    ]));
  }
}

// 通过 plugin 转换源代码 parse 出来的AST 抽象语法树,并且返回结果
let result= babel.transform(content, {
   plugins: [
     { visitor }
   ]
 });

 console.warn(`res: ${result.code}`);
 // 把新代码写入新文件.
 fs.writeFileSync('newRoute.ts', result.code);

比较关键的部分就是在visitor 这个自定义的插件中,拦截ArrayExpression,这是routes: [] 对应的路由数组。而这个数组表达式包含了一个elements 数组,每个对象在AST 中都是ObjectExpression 类型。不论是数组表达式,还是对象表达式,都是对应 babel-types 中不同的节点(node)类型。所以我们在构建新的 AST 节点时,可以参考AST explorer 中已有的节点类型。

例如这里我们要新增一个route 对象,则是用babel-types 中的 types.objectExpression(objectProperty[]) 生成一个,根据智能提示传入参数,要求是objectProperty 数组,那么我们又利用 types.objectProperty(key: identifier, value: string) 生成一个。

t.objectExpression([ 
  // 对象中的第一个属性 path: string;
  t.objectProperty(t.identifier('path'), t.stringLiteral(newRoute.path)),
  // ...
]);

AST explorer 中源代码和AST的对应关系

根据官方docs,也可以利用 AST explorer 去寻找对应关系,结合 IDE 的智能提示来构建你所需要的 AST 语法树,就可以自动转换成你想要的代码了。实际上,搞懂了babel ,就可以做出ng-cli generate 这样智能高效的功能了。

参考文章:
https://www.sitepoint.com/understanding-asts-building-babel-plugin/
http://welefen.com/post/understanding-asts-by-building-your-own-babel-plugin.html
babel 官方文档
AST Explorer

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.