浅谈vue项目重构技术中央和小结,或许是visualization的新突破

pwa重构新加坡地铁线路图

2018/03/28 · JavaScript
· 澳门葡京 ,PWA

初稿出处:
Neal   

前边一向有在爱戴一个香港地铁线路图的 pwa,最要紧的风味就是 “offline
first”。然则由于代码都是透过原生的 js
去落实,以前我都不是很欣赏去用框架,不想拥有其他框架的偏好。可是到末代随着代码量的扩展,代码的确变得混乱不堪,拓展新职能也变得更为困难。由此,花了濒临三个礼拜的时候对于使用举办了一遍完整的重构。网站访问地址:

前言

浅谈vue项目重构技术核心和统计,vue技术要点

前言

新近太忙了,博客好久没有改进了。前几日忙里偷闲,简单总括一下近年来vue项目重构的部分技能中央。

vue数据更新, 视图未更新

其一题材我们平日会遇见,一般是vue数据赋值的时候,vue数据变动了,可是视图没有更新。这一个不到底项目重构的技术要旨,也和豪门享受一下vue2.0平常的缓解方案吗!

缓解方案如下:

1、通过vue.set形式赋值

Vue.set(数据源, key, newValue)

2、 通过Array.prototype.splice方法

数据源.splice(indexOfItem, 1, newValue)

3、修改数据的尺寸

数据源.splice(newLength)

4、变异方法

Vue.js
包装了被考察数组的演进方法,故它们能触发视图更新。被卷入的点子有:

push()
pop()
shift()
unshift()
splice()
sort()
reverse()

prop 对象数组应用

在 JavaScript 中目的和数组是援引类型,指向同一个内存空间,假如 prop
是一个对象或数组, 在子组件内部改变它会潜移默化父组件的气象
。利用这一点,我们在子组件中改变prop数组或者目的,父组件以及拥有应用到prop中多少的地点都会转移。我前边写过一篇js深拷贝和浅拷贝的稿子,感兴趣的去看下,其实,原理是相同的。

案例如下:

<input class="pinput max" type="text" v-model="itemData.data.did">

<script>
export default {
 components: {
 },
 data() {
 },
 props: {
 itemData: Object
 },
 methods: {
 }
};
</script>

具有应用到itemData的地点都会转移!

地方这种转移prop,Vue
不会在控制台给出警告,假设我们一齐改变或者赋值prop,控制台会发出警示!引用官方给出的化解方案如下:

1、定义一个部分变量,并用 prop 的值起初化它:

props: ['initialCounter'],
data: function () {
 return { counter: this.initialCounter }
}

2、定义一个盘算属性,处理 prop 的值并重返:

props: ['size'],
computed: {
 normalizedSize: function () {
 return this.size.trim().toLowerCase()
 }
}

v-model 的部分坑

实在v-model和sync都是部分语法糖,我前面有成文介绍过,官网也能找到类似的案例!

v-model
数据有时是undefined的时候,不会报错,所以,一定要留意,v-model不可能是undefined,否则有些莫名的题材!

重构-动态组件的创设

有时候大家有许多接近的零件,只有一点点地方不同等,我们可以把这样的类似组件写到配置文件中,动态创制和引用组件

主意一:component 和is配合使用

由此选用保留的 元素,并对其 is
特性举办动态绑定,你可以在同一个挂载点动态切换多少个零部件:

var vm = new Vue({
 el: '#example',
 data: {
 currentView: 'home'
 },
 components: {
 home: { /* ... */ },
 posts: { /* ... */ },
 archive: { /* ... */ }
 }
})
<component v-bind:is="currentView">
 <!-- 组件在 vm.currentview 变化时改变! -->
</component>

措施二:通过render方法创设

<script>
export default {
 data() {
 return {
 };
 },
 render: function(createElement) {
 let _type = bi.chart.data.type;
 let _attr = bi.chart.components[_type]["attr"];
 return createElement(_attr, {
  props: {
  }
 });
 }
};
</script>

bi.chart.components[_type][“attr”]其一是在安排文件中动态配置的,type点击的时候会改变,会取不同type上边的attr属性!

公家性质抽离

浅谈vue项目重构技术中央和小结,或许是visualization的新突破。俺们在品种中,通常会用很多景色或者数额,我们能够把许多公共数据抽离出来,放到一个目的中,后边大家得以监听这个数额对象变化。举办数据保存仍然取得。

c: {
 handler: function (val, oldVal) { /* ... */ },
 deep: true
},
// 该回调将会在侦听开始之后被立即调用
d: {
 handler: function (val, oldVal) { /* ... */ },
 immediate: true
},

可以行使方面深度监听。假若起始化的时候要即刻执行,大家得以用当下施行监听!

require动态加载依赖

俺们可以选用require同步特性,在代码中动态加载倚重,例如下边echart主题,大家可以点击切换的时候,动态加载!

require("echarts/theme/"+ data.theme);

import加载要放权头部,初叶化的时候,能够把默认主题用import加载进来!

以上就是本文的整体内容,希望对大家的学习抱有协助,也盼望大家多多协理帮客之家。

前言
近日太忙了,博客好久没有革新了。明天忙里偷闲,简单总括一下近日vue项目重构的一…

自出生之初截止近年来(2016开春),React可以说是前端界最风靡的话题,假设您还不亮堂React是何物,你就该需要充充电了。

准备

未雨绸缪工作先做好,在 vue 和 react 之间,我或者拔取了后者。基于
create-react-app
来搭建环境,crp 为您准备了一个开箱即用的付出环境,由此你无需协调亲手配置
webpack,因而你也不需要变成一名 webpack 配置工程师了。

除此以外一方面,我们还亟需部分数码,包括站点消息,线路途径,文字表明等等。基于此前的行使,可以透过一小段的代码获取信息。就此如要大家收获我们原先的站点在
svg 图中的相关属性,普通的站点使用 circle 元素,为了得到其特性:

const circles = document.querySelectorAll(‘circle’); let result = [];
circles.forEach(circle => { let ele = { cx: circle.cx, cy: circle.cy,
sroke: circle.stroke, id: circle.id }; result.push(ele); }) const str =
JSON.stringify(result);

1
2
3
4
5
6
7
8
9
10
11
12
13
const circles = document.querySelectorAll(‘circle’);
let result = [];
circles.forEach(circle => {
  let ele = {
    cx: circle.cx,
    cy: circle.cy,
    sroke: circle.stroke,
    id: circle.id
  };
  result.push(ele);
})
const str = JSON.stringify(result);
 

透过这样的代码我们就可以拿走 svg
普通站点信息,同理还可得到中转站音信,线路途径音信以及站点以及线路 label
信息。还有,我们还需要取得每个站点的时刻表新闻,卫生间地方音讯,无障碍电梯信息以及出入口消息。这里是写了有些爬虫去官网爬取并做了有些数量处理,再度就不一一赘述。

日前太忙了,博客好久没有更新了。前天忙里偷闲,简单总结一下近年来vue项目重构的有的技巧中央。

d3是由伦敦时报工程师开源的一个制图基于svg的数额可视化工具,是近几年最盛行的visualization工具库之一。d3提供充裕的svg绘制API、动画甚至布局等功用,近日市面上大多数visualization仓库是由d3构建的。d3的优势在于将data与DOM绑定,理想化的方案是一向操作data而不是操作DOM来落实UI的改进,从这个角度上讲,d3的观点与React有异曲同工之妙。

设计

多少准备好将来,就是采纳的计划了。首先,对组件举办三遍拆分:

vue数据更新, 视图未更新

既然两者有相似之处,那么双方的重组会迸发出什么样的灯火呢?

组件结构

将全部地图知道成一个 Map 组件,再将其分成 4 个小组件:

澳门葡京 1

  • Label: 地图上的文本音讯,包括地铁站名,线路名称
  • Station: 地铁站点,包括一般站点和转发站点
  • Line: 地铁线路
  • InfoCard:
    状态最复杂的一个零部件,重要涵盖时刻表新闻、卫生间地方消息、出入口讯息、无障碍电梯音讯

那是一个大约的零件划分,里面或者带有更多的其它元素,比如 InfoCard 就有
InfoCard => 提姆(Tim)eSheet => 提姆esheetTable 这样的嵌套。

以此题材我们日常会遇见,一般是vue数据赋值的时候,vue数据变化了,但是视图没有立异。这一个不算是项目重构的技巧主题,也和大家享受一下vue2.0平时的化解方案吧!

注:React和d3的组合优势重要呈现在动态化的charts上,静态的charts并不明确。

零件通信和意况管理

本地开发的最大的难点应该就是这一块的始最终。本来出于组件的层级并不算特别复杂,所以自己并不打算上
Redux
这序列型的大局状态管理库。首要组件之间的通信就是父子通信和兄弟组件通信。父子组件通信相比较简单,父组件的
state 即为子组件的
props,可以通过这些实现父子组件通信。兄弟组件略为复杂性,兄弟组件通过共享父组件的状态来拓展通信。假诺这样的情景,我点击站点,希望可以弹出信息指示窗,这就是
Station 组件和 InfoCard 组件之间的通信,通过 Map 组件来展开共享。点击
Station 组件触发事件,通过回调更新 Map 组件状态的换代,同时也实现了
InfoCard
组件的更新。同时为了兑现,点击任何区域就可以关闭音讯指示窗,我们对 Map
组件举行监听,监听事件的冒泡来实现快速的倒闭,当然为了避免有些不必要的冒泡,还亟需在部分事件处理中阻止事件冒泡。

澳门葡京 2

InfoCard 是无比复杂的一个零部件,因为中间富含了少数个
icon,以及气象音讯的切换,同时需要贯彻切换不同的站点的时候能够更新音讯指示窗。需要注意音讯提醒窗信息初次点击音信的开始化,以及切换不同
icon
时分别显示不同的音信,比如卫生间音信仍然出入口音信,以及对此时刻表,切换不同的路线的时候更新对应的时刻表。那么些情况的转账,需要值得注意。其余值得一题的点就是,在切换不同站点的时候的气象,假若我正在看某个站点的盥洗室消息的时候,我点击其余一个站点,这时候弹出的消息提醒窗应该是时刻表消息或者卫生间音信吗?我的接纳仍然卫生间消息,我对此这场馆进行了维系,这样的用户体验从逻辑上来讲似乎更佳。具体贯彻的代码细节就不一一表明了,里面肯能包含更多的底细,欢迎使用体验。

化解方案如下:

首先我们分析一下React和d3应用在visualization领域的优势和不足。

特性优化

上述这一个的开销得益于在此以前的维护,所以重构过程或者比较快的,稍微谙习了下
react 的用法就完了了重构。然则,在上线之后接纳 lighthouse
做分析,performan 的得分是 0 分。首屏渲染以及可互相得分都是 0
分,首先来分析一下。因为任何应用都是经过 js 来渲染,而最为主旨的就是相当svg。整个看下去,有几点值得注意:

  • 代码直接将 json 导入,导致 js 体积过大
  • 具有组件都在渲染的时候举行加载

找到题目点,就足以想到一些解决方案了。第一个相比简单,压缩 json
数据,去除一些不需要的音信。第二个,好的解决办法就是透过异步加载来兑现组件加载,效果分明,尤其是对此
InfoCard 组件:

1、通过vue.set形式赋值

React的优势:

同步

class InfoCard extends React.Component { constructor(props) {  
 super(props) { …    }  }  … }

1
2
3
4
5
6
7
8
9
class InfoCard extends React.Component {
  constructor(props) {
   super(props) {
    …
   }
 }
 …
}
 
Vue.set(数据源, key, newValue)
  • 飞速的diff算法可以升官动态化chart的习性表现;
  • React将props和state分离的见地非凡适合visualization,将不变的数码定义为props,动态的数额定义为state。这样数据变动时,使用setState()更新组件UI。

异步

export default function asyncInfoCard (importComp) { class InfoCard
extends React.Component {    constructor(props) { super(props);
this.state = { component: null }; } asyncComponentDidMount() { const {
default: component } = await importComp(); this.setState({ component:
component })    }  } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
export default function asyncInfoCard (importComp) {
  class InfoCard extends React.Component {
   constructor(props) {
      super(props);
      this.state = {
        component: null
      };
    }
    
    asyncComponentDidMount() {
      const { default: component } = await importComp();
      this.setState({
        component: component
      })
   }
 }
}
 

这么大家就落实了将联手组件改造成一个异步加载的零件,这样就无需一下子加载所有的零件。这样大家就可以在
Map 中利用异步的法门来展开零部件的加载:

import asyncInfoCard from ‘./InfoCard’ const InfoCard = asyncInfoCard(()
=> import(‘./InfoCard’)

1
2
3
import asyncInfoCard from ‘./InfoCard’
const InfoCard = asyncInfoCard(() => import(‘./InfoCard’)
 

透过上线之后的性质分析,lighthouse 性能评分一下子就升起到了 80
多分,注明那样的改进要么相比有效的。此外一个值得提的点就是首屏,因为历史由来,整张图
svg 中元素的岗位都是定死的,及横坐标和纵坐标都已经是概念好的,而 svg
被定为在中等。在移动端加载时,显示的就是左手的空域区域,所以给用户一种程序未加载完毕的错觉。在此之前的本子的做法就是因此scroll 来促成滚动条的滚动,将视图的关键移动到中游地点。本次的想法是经过
transform 来实现:

.svg { transform: translate(-100px, -300px) }

1
2
3
.svg {
transform: translate(-100px, -300px)
}

如此这般实现了全体 svg 图地点的舞狮,使用 lighthouse 举办剖析,性能分降到了
70
多分。继续考虑有没有其他的艺术,后来自己想在最左上上角定义一个箭头动画。

img src=”right_arrow.png” alt=”right arrow” title=”right arrow”
class=”right-arrow”/>

1
img src="right_arrow.png" alt="right arrow" title="right arrow" class="right-arrow"/>

.right-arrow { animation: moveright 3s linear infinite; } @keyframs
moveright { 0% { transform: translateX(2rem); } 50% { transform:
translateX(3rem); } 100% { transform: translateX(5rem); } }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
.right-arrow {
  animation: moveright 3s linear infinite;
}
@keyframs moveright {
  0% {
    transform: translateX(2rem);
  }
  50% {
    transform: translateX(3rem);
  }
  100% {
    transform: translateX(5rem);
  }
}

澳门葡京 3

诸如此类大家就可以成立一个巡回向右移动的卡通,提醒用户向右滑动。部署之后察觉性能分立马降到
0,索性也就放任了这个做法。最终来时控制运用
transform: translateX(-200px) translateY(-300px); ,因为这么经过 css3
的习性可以在有的活动设备上还是可以够利用 GPU 加速,并且 translateX
不会挑起页面的重绘或者重排,只会导致图层重组,最小避免对性能的震慑。

2、 通过Array.prototype.splice方法

React的不足:

部署

当前的布置方案是使用 create-react-app 的合法提出,通过 gh-pages 实现将
build 的打包文件上传到 gh-pages 分支上从而实现部署。

数据源.splice(indexOfItem, 1, newValue)

  • 动画库不增长;
  • 在svg的操作和算法方面不如d3早熟。

兼容性

眼下该选拔在 Chrome 浏览器的辅助性是最好的,安卓浏览器提议安装 Chrome
浏览器采取,我一般也都相比较欣赏在表哥大上选拔Google浏览器。对于 Safari
浏览器,此外的浏览功效似乎并未什么样大问题,如今应有还没帮忙添加到主屏幕。然而在未来的
ios 版本好像对于 pwa 有着更进一步的协理。

3、修改数据的尺寸

d3的优势:

结语

澳门葡京 4

花了多个礼拜的岁月成功了品种的总体的重构,从这一年来的 commit
记录可以看看一月份疯狂 commit
了一波,重要是第一个星期四花费了两天的时刻修改了诸多代码,被百般 InfoCard
的意况切换搞了很久,后边就是针对性性能做了一些优化。过程很惨痛,一度怀疑自己的
coding 能力。不过最后仍然有以下感悟:

  • 世界上尚未最好的言语,最好的框架,只有最合适的
  • 最优雅的落实都不是容易的,都是一个个试出来的

末段一个冷笑话:

青春问禅师:“请问大师,我写的次序为啥没有博得预期的出口?”
禅师答到:“年轻人,这是因为你的程序只会按你怎么写的举办,不会按您怎么想的推行啊……”

源代码地址,欢迎 star 或者 pr。

 

1 赞 收藏
评论

澳门葡京 5

数据源.splice(newLength)

  • data与DOM绑定,操作data实现UI更新;
  • 增长的svg API和卡通,同时提供基本的chart布局方案。

4、变异方法

d3的不足:

Vue.js
包装了被考察数组的多变方法,故它们能触发视图更新。被卷入的不二法门有:

  • UI更新算法不够高效,大多数境况下,细节数量的转移需要重新绘制整个chart;
push()
pop()
shift()
unshift()
splice()
sort()
reverse()

相比React和d3各自的优缺点会发现互相在好几地点是互补的,笔者在档次技术选型初期对两端的重组分外看好(固然项目最终并未行使双边的其他一个,但并不是因为双方不符合,而是因为要配合万恶的低版本IE…)。

prop 对象数组应用

上边简单介绍一下实现方案,读者可以相比demo阅读:

在 JavaScript 中目的和数组是援引类型,指向同一个内存空间,即使 prop
是一个对象或数组, 在子组件内部改变它会影响父组件的情况。利用这或多或少,我们在子组件中改变prop数组或者目的,父组件以及有着应用到prop中数据的地点都会生成。我事先写过一篇js深拷贝和浅拷贝的著作,感兴趣的去看下,其实,原理是一律的。

See the Pen
react-d3-dial_chart by Joe
(@ihardcoder) on
CodePen.

案例如下:

咱俩的目的是充裕利用React和d3各自的优势,结合上文提到的性状,最后使用如下方案:

<input class="pinput max" type="text" v-model="itemData.data.did">

<script>
export default {
 components: {
 },
 data() {
 },
 props: {
 itemData: Object
 },
 methods: {
 }
};
</script>
  • 不采纳d3的绘图API,而是由React生成DOM,这样便可以将UI更新细节到每个节点;
  • 动用d3的svg算法,生成的结果作为React组件的props或state;
  • 应用d3的卡通API弥补React动画方面的供不应求;
  • 一点特殊动画需要利用d3的绘图API。

抱有应用到itemData的地点都会转移!

比较demo,我们创立一个Dialchart。首先我们要创制一个供全局调用的class:

下面这种改变prop,Vue
不会在控制台给出警告,假使我们一齐改变或者赋值prop,控制台会发出警告!引用官方给出的化解方案如下:

/**
 * @desc 入口函数
 * @param container-{DOM Element}: chart外层容器,一般由模板指定
 * @param opts-{Object}: 数据和配置选型的集合对象
 * @return chart实例-{React Object}
 **/
class Dial {
  constructor(container,opts){
    // ...
    this.init();
  }
  init(){
    // ...
    this.DOM = React.render(
      <DialDOM size={_size} fontSize={_fontSize} fontFamily={_fontFamily} dataset={this.dataset}/>,
      this.container
    );
  }
  /**
   * @desc 更新组件的state,可用于响应式
   * @param opts-{Object}: 配置参数
   **/
  update(opts){
    if(!opts){
      return;
    }
    if(opts.fontSize){
      this.DOM.setState({
        fontSize: opts.fontSize
      });
    }
    if(opts.size){
      this.DOM.setState({
        size: opts.size
      });
    }
  }
}

1、定义一个片段变量,并用 prop 的值初阶化它:

咱俩简要了有的细节代码,完整代码请参考demo

props: ['initialCounter'],
data: function () {
 return { counter: this.initialCounter }
}

上述代码中最着重的动作是render了一个React组件,有一个细节需要注意,俺们将size等数码作为props传入组件,可是在update函数中却采用的是setState,这里面有一个不胜重大的步子:在DialDOM组件内首先要把props映射为state。这样我们在setState时便足以不破坏React的props不可能改改的约定。

2、定义一个测算属性,处理 prop 的值并重临:

DialDOM组件的代码如下:

props: ['size'],
computed: {
 normalizedSize: function () {
 return this.size.trim().toLowerCase()
 }
}
const DialDOM = React.createClass({
  getDefaultProps() {
    return {
        fontSize: 12,
        fontFamily: 'inherit',
        fontColor: 'inherit'  
    };
  },
  getInitialState() {
    // size和fontSize可以改变,所以作为组件的state使用
    return {
      size: this.props.size,
      fontSize: this.props.fontSize        
    };
  },
  render(){
    const _data = this.props.dataset.children;
    let _Arcs = [];
    let _total = _data.length;
    let _average = 2/_total*Math.PI;

    if(_data){
      for(let i=0;i<_total;i++){
        let _startAngle = _average*i - _rotate;
        let _endAngle = _startAngle + _step;        
        _Arcs.push(<DialArc radius={this.state.size/2} 
                   dataset={_data[i]} 
                   key={i} />);
      }
    }
    let _transform = d3.transform('translate('+this.state.size/2+','+this.state.size/2+')');               
    return(
      <DialBox size={this.state.size} fontSize={this.props.fontSize} fontFamily={this.props.fontFamily} >
        {_Arcs}
        <DialMidText 
        finalscore={this.props.dataset.score} 
        rank={this.props.dataset.rank} 
        transform={_transform}/>
      </DialBox>
    );
  }
});

v-model 的部分坑

上述代码并不是一体化的,完整代码请参见demo

实际上v-model和sync都是有些语法糖,我以前有成文介绍过,官网也能找到类似的案例!

上述代码有以下几点需要注意:

v-model
数据有时是undefined的时候,不会报错,所以,一定要留心,v-model不可以是undefined,否则有些莫名的问题!

  1. getDefaultProps措施注解一些默认的props,保证渲染出的UI正确性;
  2. getInitialState主意将props映射为state。正如上文提到的,这样做是为了保险props的唯一不变性。不是富有的props都需要映射为state,state应当只是一些动态的多少。当然,demo中的代码并不是应有尽有的,有趣味的读者能够探讨更是优化。
  3. 上述代码中利用d3的transform方法总计svg的transform,正如上文所述,这是React与d3结合的一个细节。

重构-动态组件的创制

DialDOM组件小范围整合了React和d3,这只是多头结合的优势之一。下边我们参照DialArc组件展示什么将d3的卡通片应用到零部件内:

有时候我们有成千上万近似的组件,唯有一点点地点不均等,我们得以把这样的接近组件写到配置文件中,动态创造和引用组件

    // 表盘外围圆弧
    const DialArc = React.createClass({
      getInitialState() {
          return {
            pathArc: '',
            arcID: 'arc_' + this.props.range + (new Date()).getTime()
          };
        },
        componentDidMount() {
          let _arcAniTime = 600,
            _textAniTime = 300,
            _tickAniTime = 50;
          // path动画
          let _endAngle =  this.props.endAngle;
          let _arc = d3.svg.arc().innerRadius(this.props.radius-this.props.padding-this.props.border).outerRadius(this.props.radius-this.props.padding).startAngle(this.props.startAngle);
          let path = d3.select(this.refs.path);
          path.datum({endAngle: this.props.startAngle});
          path.transition().duration(_arcAniTime).attrTween('d', function(d){
            let interpolate = d3.interpolate(d.endAngle,_endAngle);
            return function(t){
              d.endAngle = interpolate(t);
              return _arc(d);
            }
          });  
          //text动画
          let text = d3.select(this.refs.text);
          text.transition().delay(_arcAniTime).duration(_textAniTime).style('opacity','1');
          // tick动画
          for (let i = 0; i < 20; i++) {
            d3.select(React.findDOMNode(this.refs['tick_' + i])).transition().delay(30 * i).duration(30).style('opacity', 0.4);
          }
          let score_ticks_num = Math.floor(this.props.dataset.score * this.props.ticksum / 100);
          for (let i = 0; i < score_ticks_num; i++) {
            d3.select(React.findDOMNode(this.refs['tick_' + i])).transition().delay(_arcAniTime+_textAniTime + _tickAniTime * i).duration(_tickAniTime).style('opacity', 1);
          }
        },
        render() {
          let _arc = d3.svg.arc().innerRadius(this.props.radius - this.props.padding - this.props.border).outerRadius(this.props.radius - this.props.padding).startAngle(this.props.startAngle).endAngle(this.props.endAngle);
          let _transform = d3.transform('translate(' + this.props.radius + ',' + this.props.radius + ')');
          let ticks = [];
          for (let i = 0; i < this.props.ticksum; i++) {
            let _ref = 'tick_' + i;
            ticks.push( <DialTick startAngle = {this.props.startAngle + this.props.tickstep * i}
              endAngle = {this.props.startAngle + this.props.tickstep * (i + 2 / 3)}
              radius = {this.props.radius - this.props.padding - this.props.border}
              color = {this.props.dataset.color}
              key = {i}
              ref = {_ref}/>);
            }
            return ( 
            <g transform = {_transform}>
              <path ref = 'path' id = {this.state.arcID} d = {_arc()} fill = {this.props.dataset.color}> </path>
              <text ref='text' dx='50%' dy='-10px'textAnchor='end' style={{opacity:0,fontSize: this.props.fontSize}}
              fill={this.props.fontColor}>
                 <textPath xlinkHref={'#'+this.state.arcID}>{this.props.dataset.name}</textPath>
              </text>
              {ticks}
              </g>
            );
          }
    });

主意一:component 和is配合使用

DialArc组件中运用了React组件生命周期中的componentDidMount方法,这多少个模式在render方法执行完毕后被实施。

经过应用保留的 元素,并对其 is
特性举行动态绑定,你可以在同一个挂载点动态切换四个零件:

咱俩在render方法中只创造了起始状态的机件UI,然后再componentDidMount方法中应用d3创建了一些动画。这个动画片是直接操作DOM,可是尚未对组件的props或state做其余操作。

var vm = new Vue({
 el: '#example',
 data: {
 currentView: 'home'
 },
 components: {
 home: { /* ... */ },
 posts: { /* ... */ },
 archive: { /* ... */ }
 }
})
<component v-bind:is="currentView">
 <!-- 组件在 vm.currentview 变化时改变! -->
</component>

这般做的原由根本是受限于React并不成熟的动画片机制,为了防止重新接触组件render,所以向来操作DOM。即便如此做是React的反形式(React不提出DOM操作),不过当下的话,这是作者可以想到的最佳方案了。

方法二:通过render方法创设

总结

以上便是笔者对React结合d3实现visualization的上马探索,希望可以提供给有连锁开发人士一些启发,肯定不是顶级方案,假使有趣味,可以互换笔者一起座谈。

笔者的品类最后并未使用上述方案,因为React对IE8的兼容性并不能够,d3更是完全不包容IE8及以下版本。项目最终拔取拉菲尔(Raphael)。Raphael(Raphael)不是面向svg的,在不匡助svg的浏览器中生成vml格式的chart以落实包容,demo可以点击这里。

<script>
export default {
 data() {
 return {
 };
 },
 render: function(createElement) {
 let _type = bi.chart.data.type;
 let _attr = bi.chart.components[_type]["attr"];
 return createElement(_attr, {
  props: {
  }
 });
 }
};
</script>

bi.chart.components[_type][“attr”]其一是在布置文件中动态配置的,type点击的时候会改变,会取不同type下边的attr属性!

公共属性抽离

咱俩在类型中,通常会用很多景色或者数额,我们得以把众多公共数据抽离出来,放到一个对象中,后边我们可以监听这多少个数据对象变化。举行数据保存或者取得。

c: {
 handler: function (val, oldVal) { /* ... */ },
 deep: true
},
// 该回调将会在侦听开始之后被立即调用
d: {
 handler: function (val, oldVal) { /* ... */ },
 immediate: true
},

可以动用方面深度监听。假设初步化的时候要顿时执行,大家可以用当下施行监听!

require动态加载看重

咱们可以运用require同步特性,在代码中动态加载倚重,例如上面echart核心,我们可以点击切换的时候,动态加载!

require("echarts/theme/"+ data.theme);

import加载要放置头部,起首化的时候,可以把默认核心用import加载进来!

以上就是本文的全部内容,希望对我们的就学抱有补助,也期望我们多多帮忙脚本之家。

您或许感兴趣的稿子:

  • Map.vue基于百度地图组件重构笔记分享

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website