具名组件

当一个组件作为另一个组件的子组件使用时,我们可以通过具名组件简化成一个HTML标签的写法,这样可以极大的简化我们的代码。

具名组件一般会把组件内所有的交互和行为以及模板都封装起来,使用的时候就当成类型的HTML标签使用就很方便了。

定义一个具名组件

组件的名字必须全部为小写,中间包含至少一个横杆,如ui-view

// es5
drunk.Component.define('my-component', {
  template: '<div>This is my component</div>',
  // templateUrl: 'tpl/my-component.html',
});
// es6
class MyComponent extends drunk.Component {
  init() {
    this.template = '<div>This is my component</div>';
    // this.templateUrl = 'tpl/my-component.html';
  }
}

drunk.Component.register('my-component', MyComponent);
// ts
@drunk.component('my-component')
class MyComponent extends drunk.Component {
  template = '<div>This is my component</div>';
  // templateUrl = 'tpl/my-component.html';
}
  • template 模板的HTML字符串
  • templateUrl 模板文件的url

template的优先级比templateUrl高,创建组件实例时会先检测是否存在template字段,再检测templateUrltemplateUrl会发送XMLHttpRequest请求加载得到HTML字符串,然后和template字段的处理流程一样,先创建成DOM节点,再调用组件实例的$mount方法挂载,然后解析编译等。

使用具名组件

<body>
  <my-component></my-component>
</body>
new drunk.Component().$mount(document.body);

渲染为:

<body>
  <div>This is my component</div>
</body>

组件的数据和事件

具名组件有自己的作用域,但和repeat指令不一样,它无法直接访问父级的作用域,所以具名组件的使用方法和HTML标签一样,需要通过属性传递数据,注册事件。

// alert-view.js
@drunk.component('ui-alert-view')
class UIAlertView extends drunk.Component {
  templateUrl = 'alert-view.html';

  visible: boolean = false;
  title: string = '';
  content: string = '';

  onConfirm() {
    this.visible = false;
    this.$emit('confirm');
  }
}
<!-- alert-view.html -->
<style>
.alert-container {
  position: fixed;
  top: 50%;
  left: 50%;
  width: 300px;
  height: 100px;
  transform: translate(-50%, -50%);
  text-align: center;
}
</style>

<div class="alert-container">
  <p>{{title}}</p>
  <p>{{content}}</p>
  <button drunk-on="click: onConfirm()>确认</button>
</div>

使用例子:

<body>
  <button drunk-on="click: showAlert()">点击显示ui-alert-view</button>
  <ui-alert-view title="温馨提示" content="{{alertContent}}" visible="{{alertVisible}}" on-confirm="alertVisible = false">
  </ui-alert-view>
</body>
// app.js
var app = new drunk.Component();
app.$mount(document.body);
app.showAlert = function () {
  this.alertContent = '一个随机数' + Math.random();
  this.alertVisible = true;
};
  • ui-alert-viewtitle, content, visible属性都和普通的HTML标签一样可以直接赋值传递到组件内部,如果需要进行数据绑定,可以用双大括号这的插值表达式。
  • ui-alert-view里的button在点击后会把visible状态设置成false,同时触发一个confirm事件,在组件外部想要接收这个事件,可以在<ui-alert-view>标签上添加on-confirm(on-${eventName},这里的eventName为confirm)属性进行事件注册。也可以通过on指令进行注册,如:drunk-on="confirm: alertVisible = false"

因为HTML属性语法忽略大小写,所以所有驼峰式的组件属性和事件名都要换成带-横杆的写法,如alertVisible要在标签上用时要写成alert-visiblemyEvent事件在标签上用时要写成on-my-event

组件数据的双向绑定

在组件上使用two-way这个属性来声明哪个属性需要进行双向绑定

<ui-alert-view visible="{{alertVisible}}" two-way="visible"></ui-alert-view>

组件内部的visible属性的值变化时,会同步到父级的alertVisible属性。如果有多个属性需要进行双向绑定时,只需要用空格隔开: two-way="prop1 prop2 prop3"

组件样式的独立作用域

如果需要实现组件的样式有独立的作用域,可以在模板中引入的<style><link>标签上加上scoped属性,如:<style scoped><link rel="stylesheet" scoped href="...">。drunk会在解析模板的时候检测到这个属性存在时,先对样式规则前添加一个唯一的样式名,使其不会被其他样式影响。

可复用的组件逻辑

原理上组件的所有属性都可以通过在标签上传值去修改,所以当我们的某个组件的逻辑不变而只是在UI上有一些变化时,我们可以通过修改组件的templatetemplateUrl属性去替换模板以达到复用逻辑的效果,当然这个场景并不常用。

<ui-alert-view></ui-alert-view>
<ui-alert-view template-url="new-alert-view.html"></ui-alert-view>

results matching ""

    No results matching ""