一套代码小程序&Web&Native运行的探索06——组件系统

接上文:一套代码小程序&Web&Native运行的探索05——snabbdom

对应Git代码地址请见:https://github.com/yexiaochai/wxdemo/tree/master/mvvm

参考:

https://github.com/fastCreator/MVVM(极度参考,十分感谢该作者,直接看Vue会比较吃力的,但是看完这个作者的代码便会轻易很多,可惜这个作者没有对应博客说明,不然就爽了)

https://www.tangshuang.net/3756.html

https://www.cnblogs.com/kidney/p/8018226.html

http://www.cnblogs.com/kidney/p/6052935.html

https://github.com/livoras/blog/issues/13

通过之前的学习,我们断断续续的了解到了一套MVVM框架需要了解的精华(我觉得的精华):

① 模板解析,由模板生成框架element

② 生成渲染函数,由element生成render匿名函数,这里便涉及到了指令的解析,render函数执行后生成了最终Vnode需要的数据字典,这里完成了HTML->Vnode的全部工作

③ 使用snabbdom进行页面渲染,后续数据更新调用发布订阅系统更新数据

而MVVM系统还有个比较关键的点是组件系统,一般认为MVVM的量大特点其实是响应式数据更新(Vnode相关),然后就是组件体系,这两者需要完成的工作都是让我们更搞笑的开发代码,一个为了解决纷乱的dom操作,一个为了解决负责的业务逻辑结构,所以我们今天便来学习组件体系相关逻辑

其实组件体系的实例化事实上跟new MVVM是一致的,只不过需要一点特殊处理,这里我们看其渲染时候的变化:

1 if (typeof tag == ‘string‘) {
2   let Ctor = resolveAsset(this.$options, ‘components‘, tag)
3   if (Ctor) {
4     return this._createComponent(Ctor, data, children, tag)
5   }
6 }

这里对tag做了判断,如果是字符串,并且我们参数里面传递了components参数,这里便会拿出来执行createComponent逻辑:

 1 //创建组件
 2 //子组件option,属性,子元素,tag
 3 _createComponent(Ctor, data, children, sel) {
 4  Ctor.data = mergeOptions(Ctor.data);
 5  let componentVm;
 6  let Factory = this.constructor
 7  let parentData = this.$data
 8  data.hook.insert = (vnode) => {
 9     //...
10  }
11  Ctor._vnode = new VNode(sel,null,data, [], undefined, createElement(sel));
12  return Ctor._vnode
13 }

这里创建vnode的时候没有做什么特殊处理,所以我们的会形成这样的dom结构:

<my-component></my-component>
<div m-for="(val, key, index) in arr">索引 1 :叶小钗</div>
<div m-for="(val, key, index) in arr">索引 2 :素还真</div>
<div m-for="(val, key, index) in arr">索引 3 :一页书</div>

但是这里有一个hook,在my-component作为dom插入的时候回被调用:

 1 _createComponent(Ctor, data, children, sel) {
 2  Ctor.data = mergeOptions(Ctor.data);
 3  let componentVm;
 4  let Factory = this.constructor
 5  let parentData = this.$data
 6  data.hook.insert = (vnode) => {
 7    Ctor.data = Ctor.data || {};
 8    var el =createElement(‘sel‘)
 9    vnode.elm.append(el)
10    Ctor.el = el;
11    componentVm = new Factory(Ctor);
12    vnode.key = componentVm.uid;
13    componentVm._isComponent = true
14    componentVm.$parent = this;
15    (this.$children || (this.$children = [])).push(componentVm);
16    //写在调用父组件值
17    for (let key in data.attrs) {
18      if (Ctor.data[key]) {
19        warn(`data:${key},已存在`);
20        continue;
21      }
22    }
23  }
24  Ctor._vnode = new VNode(sel,null,data, [], undefined, createElement(sel));
25  return Ctor._vnode
26 }

这里先创建了一个空标签(sel)直接插入my-component中,然后执行与之前一样的实例化流程:

componentVm = new Factory(Ctor);

这个会在patch后将实际的dom节点更新上去:

this.$el = patch(this.$el, vnode); //$el现在为sel标签(dom标签)

这个就是snabbdom hook所干的工作,可以看到组件系统这里有这些特点:

① 组件是一个独立的mvvm实例,通过parent可以找到其父亲mvvm实例,可能跟实例,也可能是另一个组件

② 跟实例可以根据$children参数找到其下面所有的组件

③ 组件与跟实例通过data做交流,原则不允许在组件内部改变属性值,需要使用事件进行通信,事件通信就是在组件中的点击事件不做具体的工作,而是释放$emit(),这种东西让跟实例调用,最终还是以setData的方式改变基本数据,从而引发组件同步更新

所以只要把之前的内容搞懂了,组件一块会比较轻松,我们之前没涉及到属性,这里我们来试试数据传递:

html = `
  <div ontap="onclick">
    <my-component name="{{name}}"></my-component>
    <div m-for="(val, key, index) in arr">索引 {{key + 1}} :{{val}}</div>
  </div>
  `
let vm = new MVVM({
  el: ‘#app‘,
  template: html,
  components: {
    ‘my-component‘: {
      props: [‘name‘],
      template: ‘<div>{{name}}-children component!</div>‘
    }
  },
  data: {
    name: ‘叶小钗‘,
    age: 30,
    arr: [
      ‘叶小钗‘, ‘素还真‘, ‘一页书‘
    ]
  },
  methods: {
    onclick: function(e) {
      this.setData({
        name: ‘素还真‘,
        age: this.age + 1
      });
    }
  }
})

具体代码各位看这里吧:https://github.com/yexiaochai/wxdemo/tree/master/mvvm

经过简单的学习,我们大概了解了组件的流程,接下来我们做下阶段的整理,把之前学的东西连起来

原文地址:https://www.cnblogs.com/yexiaochai/p/9747452.html

时间: 2024-10-09 23:58:50

一套代码小程序&Web&Native运行的探索06——组件系统的相关文章

一套代码小程序&amp;Web&amp;Native运行的探索05——snabbdom

接上文:一套代码小程序&Web&Native运行的探索04——数据更新 对应Git代码地址请见:https://github.com/yexiaochai/wxdemo/tree/master/mvvm 参考: https://github.com/fastCreator/MVVM(极度参考,十分感谢该作者,直接看Vue会比较吃力的,但是看完这个作者的代码便会轻易很多,可惜这个作者没有对应博客说明,不然就爽了) https://www.tangshuang.net/3756.html ht

一套代码小程序&amp;Web&amp;Native运行的探索01

前言 前面我们对微信小程序进行了研究:[微信小程序项目实践总结]30分钟从陌生到熟悉 并且用小程序翻写了之前一个demo:[组件化开发]前端进阶篇之如何编写可维护可升级的代码 之前一直在跟业务方打交道后面研究了下后端,期间还做了一些运营.管理相关工作,哈哈,最近一年工作经历十分丰富啊,生命在于不断的尝试嘛. 当然,不可避免的在前端技术一块也稍微有点落后,对React&Vue没有进行过深入一点的研究,这里得空我们便来一起研究一番(回想起来写代码的日子才是最快乐的??),因为我们现在也慢慢在切Rea

微信小程序把玩(二十三)modal组件

原文:微信小程序把玩(二十三)modal组件 modal弹出框常用在提示一些信息比如:退出应用,清楚缓存,修改资料提交时一些提示等等. 常用属性: wxml <!--监听button点击事件--> <button bindtap="listenerButton" type="primary">弹出modal</button> <!--弹出框--> <modal title="退出应用" hid

微信小程序把玩(二十一)switch组件

原文:微信小程序把玩(二十一)switch组件 switch开关组件使用主要属性: wxml <!--switch类型开关--> <view>switch类型开关</view> <switch type="switch" checked="true" bindchange="listenerSwitch"/> <!--checkbox类型开关--> <view>checkbo

微信小程序把玩(二十七)audio组件

原文:微信小程序把玩(二十七)audio组件 音频播放已经封装的很好!只需配合属性设置即可! (method和data配合使用) 主要属性: wxml <audio action="{{action}}" src='http://sc1.111ttt.com/2016/1/09/26/202261732256.mp3' poster= 'http://avatar.csdn.net/E/3/9/1_u014360817.jpg' controls="true"

微信小程序把玩(二十)slider组件

原文:微信小程序把玩(二十)slider组件 slider滑动组件用的不太多,在其他平台反正我是用的不多 主要属性: wxml <slider max="100" step="10" show-value="true" bindchange="listenerSlider" /> js Page({ data:{ // text:"这是一个页面" }, /** * 监听slider */ lis

小程序之如和使用view内部组件来进行页面的排版功能

这篇文章主要介绍了关于小程序之如和使用view内部组件来进行页面的排版功能,有着一定的参考价值,现在分享给大家,有需要的朋友可以参考一下 涉及知识点: 1.垂直排列,水平排列 2.居中对齐 示例: 1.默认排版 , 一个父组件里面两个子view 显示效果: 2.先给父view设置一个高度和颜色值,用于看效果 3.实现水平排列和垂直排列的样式 水平排列: 垂直排列(不进行设置,默认垂直排列): 4.实现居中效果 居中效果分为两种情况,依赖于3中的水平排列还是垂直排列. ①.当水平排列的时候 , j

原创:微信小程序+WEB使用JS实现注册【60s】倒计时功能

1.效果图: 2.页面仅仅利用了JS的相关功能,包含:wxml.js.wxss 2.1wxml页面代码: <text>绑定手机</text> <form bindsubmit="bindMobile"> <view class="form_group"> <text>手 机:</text> <input type="number" placeholder="请

微信小程序获取今日天气预报代码 小程序获取七日天气

代码是天气api的小程序demo, 粘贴上js和wxml就可以运行看效果了, 有问题的加我qq 445899710, 可提供源代码, 效果如图 如果是测试, 请勾选配置 不校验合法域名.web-view(业务域名).TLS 版本以及 HTTPS 证书 如果正式使用, 请添加安全域名两个 (ip.tianqiapi.com 和 tianqiapi.com) index.js代码 //index.js //获取应用实例 const app = getApp() Page({ data: { weat