diff --git a/src/notice-bar/index.js b/src/notice-bar/index.js
index b088bc36d..8b3f9c080 100644
--- a/src/notice-bar/index.js
+++ b/src/notice-bar/index.js
@@ -1,5 +1,7 @@
+import { ref, reactive, nextTick, onActivated, watch } from 'vue';
import { createNamespace, isDef } from '../utils';
import { doubleRaf } from '../utils/dom/raf';
+import { useWidth } from '../composition/use-rect';
import Icon from '../icon';
const [createComponent, bem] = createNamespace('notice-bar');
@@ -28,158 +30,149 @@ export default createComponent({
emits: ['close', 'replay'],
- data() {
- return {
+ setup(props, { emit, slots }) {
+ let wrapWidth = 0;
+ let contentWidth = 0;
+
+ const wrapRef = ref();
+ const contentRef = ref();
+
+ const state = reactive({
show: true,
offset: 0,
duration: 0,
- wrapWidth: 0,
- contentWidth: 0,
- };
- },
+ });
- watch: {
- scrollable() {
- this.start();
- },
- text: {
- handler() {
- this.start();
- },
- immediate: true,
- },
- },
-
- activated() {
- this.start();
- },
-
- methods: {
- onClickIcon(event) {
- if (this.mode === 'closeable') {
- this.show = false;
- this.$emit('close', event);
- }
- },
-
- onTransitionEnd() {
- this.offset = this.wrapWidth;
- this.duration = 0;
-
- // wait for Vue to render offset
- this.$nextTick(() => {
- // use double raf to ensure animation can start
- doubleRaf(() => {
- this.offset = -this.contentWidth;
- this.duration = (this.contentWidth + this.wrapWidth) / this.speed;
- this.$emit('replay');
- });
- });
- },
-
- reset() {
- this.offset = 0;
- this.duration = 0;
- this.wrapWidth = 0;
- this.contentWidth = 0;
- },
-
- start() {
- const delay = isDef(this.delay) ? this.delay * 1000 : 0;
-
- this.reset();
-
- setTimeout(() => {
- const { wrap, content } = this.$refs;
- if (!wrap || !content || this.scrollable === false) {
- return;
- }
-
- const wrapWidth = wrap.getBoundingClientRect().width;
- const contentWidth = content.getBoundingClientRect().width;
-
- if (this.scrollable || contentWidth > wrapWidth) {
- doubleRaf(() => {
- this.offset = -contentWidth;
- this.duration = contentWidth / this.speed;
- this.wrapWidth = wrapWidth;
- this.contentWidth = contentWidth;
- });
- }
- }, delay);
- },
- },
-
- render() {
- const slots = this.$slots;
- const { mode, leftIcon, onClickIcon } = this;
-
- const barStyle = {
- color: this.color,
- background: this.background,
- };
-
- const contentStyle = {
- transform: this.offset ? `translateX(${this.offset}px)` : '',
- transitionDuration: this.duration + 's',
- };
-
- function LeftIcon() {
+ const renderLeftIcon = () => {
if (slots['left-icon']) {
return slots['left-icon']();
}
-
- if (leftIcon) {
- return