Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 久久精品亚洲综合一品,在线播放三级,男女下面进入的视频

          整合營(yíng)銷服務(wù)商

          電腦端+手機(jī)端+微信端=數(shù)據(jù)同步管理

          免費(fèi)咨詢熱線:

          「day-ui」 Alert 組件學(xué)習(xí)

          「day-ui」 Alert 組件學(xué)習(xí)


          樣式功能來(lái)看,整體不是很復(fù)雜,alert 組件主要包括了主題色,title,關(guān)閉按鈕,關(guān)閉事件,居中,加粗等

          源碼

          • template
          <template>
            <!-- 顯示隱藏有動(dòng)畫效果 -->
            <!-- 開發(fā)沒用過,不是很理解為什么使用v-show判斷顯示 -->
            <transition name="d-alert-fade">
              <div
                class="d-alert"
                :class="[typeClass, center ? 'is-center' : '', 'is-' + effect]"
                v-show="visible"
                role="alert"
              >
                <!-- 左側(cè)圖標(biāo) -->
                <i
                  class="d-alert__icon"
                  :class="[iconClass, isBigIcon]"
                  v-if="showIcon"
                ></i>
                <!-- title 和 描述 -->
                <div class="d-alert__content">
                  <span
                    class="d-alert__title"
                    :class="[isBoldTitle]"
                    v-if="title || $slots.title"
                  >
                    <slot name="title">{{ title }}</slot>
                  </span>
                  <p v-if="$slots.default && !description" class="d-alert__description">
                    <slot></slot>
                  </p>
                  <p v-if="description && !$slots.default" class="d-alert__description">
                    {{ description }}
                  </p>
                  <i
                    class="d-alert__closebtn"
                    :class="{
                      'is-customed': closeText !=='',
                      'd-icon-close': closeText===''
                    }"
                    v-show="closable"
                    @click="close"
                    >{{ closeText }}</i
                  >
                </div>
              </div>
            </transition>
          </template>
          

          使用 role 屬性告訴輔助設(shè)備(如屏幕閱讀器)這個(gè)元素所扮演的角色。本質(zhì)上是增強(qiáng)語(yǔ)義性,當(dāng)現(xiàn)有的 HTML標(biāo)簽不能充分表達(dá)語(yǔ)義性的時(shí)候,就可以借助 role 來(lái)說明。

          這里不是很理解為什么 titledescription 使用了屬性和 slot 判斷,有清楚的朋友可以幫忙解答

          • props 屬性比較常規(guī),這里就不介紹了哈
          setup(props, { emit, slots }) {
              // 接受的屬性轉(zhuǎn)為響應(yīng)式
              const { description, type }=toRefs(props)
              // 使用 v-show 顯示隱藏
              const visible=ref(true)
              // 關(guān)閉事件
              const close=()=> {
                visible.value=false
                emit('close')
              }
              const typeClass=computed(()=> {
                return `d-alert--${type.value}`
              })
          
              const iconClass=computed(()=> {
                return TYPE_CLASSES_MAP[type.value] || 'd-icon-info'
              })
          
              const isBigIcon=computed(()=> {
                return description.value || slots.default ? 'is-big' : ''
              })
              const isBoldTitle=computed(()=> {
                return description.value || slots.default ? 'is-bold' : ''
              })
              return {
                close,
                visible,
                typeClass,
                iconClass,
                isBigIcon,
                isBoldTitle
              }
            }
          

          組件介紹到這里就結(jié)束了,比較簡(jiǎn)單。為了湊字呢,這里在介紹下 transition 組件

          transition

          大部分朋友都了解這是設(shè)置組件動(dòng)畫的內(nèi)置動(dòng)畫組件。通常有三種使用方式:

          1. CSS 過渡
          2. CSS 動(dòng)畫
          3. Javascript 鉤子

          CSS 過渡

          我們通常使用的方法,css 配置 enterleave

          <template>
            <div class="app">
              <button @click="show=!show">
                Toggle render
              </button>
              <transition name="fade">
                <p v-if="show">我是測(cè)試</p>
              </transition>
            </div>
          </template>
          <script>
            export default {
              data() {
                return {
                  show: true
                }
              }
            }
          </script>
          <style>
            .fade-enter-active,
            .fade-leave-active {
              transition: opacity 0.5s ease;
            }
            .fade-enter-from,
            .fade-leave-to {
              opacity: 0;
            }
          </style>
          

          CSS 動(dòng)畫

          <template>
            <div class="app">
              <button @click="show=!show">Toggle show</button>
              <transition name="bounce">
                <p v-if="show">我是測(cè)試</p>
              </transition>
            </div>
          </template>
          <script>
            export default {
              data() {
                return {
                  show: true
                }
              }
            }
          </script>
          <style>
            .bounce-enter-active {
              animation: bounce-in 0.5s;
            }
            .bounce-leave-active {
              // reverse 很關(guān)鍵
              animation: bounce-in 0.5s reverse;
            }
            @keyframes bounce-in {
              0% {
                transform: scale(0);
              }
              50% {
                transform: scale(1.5);
              }
              100% {
                transform: scale(1);
              }
            }
          </style>
          

          js 鉤子

          監(jiān)聽 transition 組件的內(nèi)置方法,js 控制動(dòng)畫

          <template>
            <div class="app">
              <button @click="show=!show">
                Toggle render
              </button>
              <transition
                @before-enter="beforeEnter"
                @enter="enter"
                @before-leave="beforeLeave"
                @leave="leave"
                css="false"
              >
                <p v-if="show">hello</p>
              </transition>
            </div>
          </template>
          <script>
            export default {
              data() {
                return {
                  show: true
                }
              },
              methods: {
                beforeEnter(el) {
                  el.style.opacity=0
                  el.style.transition='opacity 0.5s ease'
                },
                enter(el) {
                  this.$el.offsetHeight
                  el.style.opacity=1
                },
                beforeLeave(el) {
                  el.style.opacity=1
                },
                leave(el) {
                  el.style.transition='opacity 0.5s ease'
                  el.style.opacity=0
                }
              }
            }
          </script>
          

          如果形參不指定 done ,則表明用戶不手動(dòng)控制動(dòng)畫的結(jié)束,而轉(zhuǎn)由節(jié)點(diǎn)的 transition 或者 animationEnd 來(lái)標(biāo)識(shí)動(dòng)畫結(jié)束,開始回調(diào) afterEnter

          鉤子函數(shù)的形參的個(gè)數(shù)大于1,表示形參中有 done, 也就是說用戶必須手動(dòng)控制動(dòng)畫何時(shí)結(jié)束。所以一旦你配置了 done 形參,則轉(zhuǎn)由你告訴框架,動(dòng)畫何時(shí)結(jié)束。需要在合適的時(shí)機(jī)調(diào)用 done,否則 afterEnter 接口就沒法被調(diào)用了。

          動(dòng)畫觸發(fā)條件

          • 條件渲染(v-if)
          • 條件展示(v-show)
          • 動(dòng)態(tài)組件
          • 組件根節(jié)點(diǎn)

          執(zhí)行原理

          實(shí)例

          <template>
            <div class="app">
              <button @click="show=!show">
                Toggle render
              </button>
              <transition name="fade">
                <p v-if="show">hello</p>
              </transition>
            </div>
          </template>
          

          編譯生成的 render 函數(shù)(不是使用的模板組件)

          import {
            createVNode as _createVNode,
            openBlock as _openBlock,
            createBlock as _createBlock,
            createCommentVNode as _createCommentVNode,
            Transition as _Transition,
            withCtx as _withCtx,
          } from "vue";
          export function render(_ctx, _cache, $props, $setup, $data, $options) {
            return (
              // 收集動(dòng)態(tài)節(jié)點(diǎn) 如 v-if v-for
              _openBlock(),
              _createBlock("template", null, [
                _createVNode("div", { class: "app" }, [
                  _createVNode(
                    "button",
                    {
                      onClick: ($event)=> (_ctx.show=!_ctx.show),
                    },
                    " Toggle render ",
                    8 /* PROPS */,
                    ["onClick"]
                  ),
                  _createVNode(
                    _Transition,
                    { name: "fade" },
                    {
                      // transition 只有一個(gè)子節(jié)點(diǎn),默認(rèn)插槽。多個(gè)子節(jié)點(diǎn)報(bào)錯(cuò)
                      default: _withCtx(()=> [
                        _ctx.show
                          ? (_openBlock(), _createBlock("p", { key: 0 }, "hello"))
                          : _createCommentVNode("v-if", true),
                      ]),
                      _: 1,
                    }
                  ),
                ]),
              ])
            );
          }
          

          那么如何在組建創(chuàng)建和銷毀的時(shí)候執(zhí)行事件呢?————?jiǎng)?chuàng)建鉤子函數(shù) transition 組件返回的是處理過的第一個(gè)子節(jié)點(diǎn)

          • 如果 Transition 組件內(nèi)部嵌套的是 KeepAlive 組件,那么它會(huì)繼續(xù)查找 KeepAlive 組件嵌套的第一個(gè)子元素節(jié)點(diǎn),來(lái)作為渲染的元素節(jié)點(diǎn)。
          • 如果 Transition 組件內(nèi)部沒有嵌套任何子節(jié)點(diǎn),那么它會(huì)渲染空的注釋節(jié)點(diǎn)。

          trantion 組件定義

          const Transition=(props, { slots })=>
            //esolveTransitionProps 函數(shù)主要作用是,在我們給 Transition 傳遞的 Props 基礎(chǔ)上做一層封裝,然后返回一個(gè)新的 Props 對(duì)象,由于它包含了所有的 Props 處理
            h(BaseTransition, resolveTransitionProps(props), slots);
          const BaseTransition={
            name: `BaseTransition`,
            props: {
              mode: String,
              appear: Boolean,
              persisted: Boolean,
              // enter
              onBeforeEnter: TransitionHookValidator,
              onEnter: TransitionHookValidator,
              onAfterEnter: TransitionHookValidator,
              onEnterCancelled: TransitionHookValidator,
              // leave
              onBeforeLeave: TransitionHookValidator,
              onLeave: TransitionHookValidator,
              onAfterLeave: TransitionHookValidator,
              onLeaveCancelled: TransitionHookValidator,
              // appear
              onBeforeAppear: TransitionHookValidator,
              onAppear: TransitionHookValidator,
              onAfterAppear: TransitionHookValidator,
              onAppearCancelled: TransitionHookValidator,
            },
            setup(props, { slots }) {
              const instance=getCurrentInstance();
              const state=useTransitionState();
              let prevTransitionKey;
              return ()=> {
                const children=slots.default && getTransitionRawChildren(slots.default(), true);
                if (!children || !children.length) {
                  return;
                }
                // Transition 組件只允許一個(gè)子元素節(jié)點(diǎn),多個(gè)報(bào)警告,提示使用 TransitionGroup 組件
                if (process.env.NODE_ENV !=="production" && children.length > 1) {
                  warn(
                    "<transition> can only be used on a single element or component. Use " +
                      "<transition-group> for lists."
                  );
                }
                // 不需要追蹤響應(yīng)式,所以改成原始值,提升性能
                const rawProps=toRaw(props);
                const { mode }=rawProps;
                // 檢查 mode 是否合法
                if (
                  process.env.NODE_ENV !=="production" &&
                  mode &&
                  !["in-out", "out-in", "default"].includes(mode)
                ) {
                  warn(`invalid <transition> mode: ${mode}`);
                }
                // 獲取第一個(gè)子元素節(jié)點(diǎn)
                const child=children[0];
                if (state.isLeaving) {
                  return emptyPlaceholder(child);
                }
                // 處理 <transition><keep-alive/></transition> 的情況
                const innerChild=getKeepAliveChild(child);
                if (!innerChild) {
                  return emptyPlaceholder(child);
                }
                const enterHooks=resolveTransitionHooks(
                  innerChild,
                  rawProps,
                  state,
                  instance
                );
                setTransitionHooks(innerChild, enterHooks);
                const oldChild=instance.subTree;
                const oldInnerChild=oldChild && getKeepAliveChild(oldChild);
                let transitionKeyChanged=false;
                const { getTransitionKey }=innerChild.type;
                if (getTransitionKey) {
                  const key=getTransitionKey();
                  if (prevTransitionKey===undefined) {
                    prevTransitionKey=key;
                  } else if (key !==prevTransitionKey) {
                    prevTransitionKey=key;
                    transitionKeyChanged=true;
                  }
                }
                if (
                  oldInnerChild &&
                  oldInnerChild.type !==Comment &&
                  (!isSameVNodeType(innerChild, oldInnerChild) || transitionKeyChanged)
                ) {
                  const leavingHooks=resolveTransitionHooks(
                    oldInnerChild,
                    rawProps,
                    state,
                    instance
                  );
                  // 更新舊樹的鉤子函數(shù)
                  setTransitionHooks(oldInnerChild, leavingHooks);
                  // 在兩個(gè)視圖之間切換
                  if (mode==="out-in") {
                    state.isLeaving=true;
                    // 返回空的占位符節(jié)點(diǎn),當(dāng)離開過渡結(jié)束后,重新渲染組件
                    leavingHooks.afterLeave=()=> {
                      state.isLeaving=false;
                      instance.update();
                    };
                    return emptyPlaceholder(child);
                  } else if (mode==="in-out") {
                    leavingHooks.delayLeave=(el, earlyRemove, delayedLeave)=> {
                      const leavingVNodesCache=getLeavingNodesForType(
                        state,
                        oldInnerChild
                      );
                      leavingVNodesCache[String(oldInnerChild.key)]=oldInnerChild;
                      // early removal callback
                      el._leaveCb=()=> {
                        earlyRemove();
                        el._leaveCb=undefined;
                        delete enterHooks.delayedLeave;
                      };
                      enterHooks.delayedLeave=delayedLeave;
                    };
                  }
                }
                return child;
              };
            },
          };
          

          在渲染的過程中,Transition 組件還會(huì)通過 resolveTransitionHooks 去定義組件創(chuàng)建和刪除階段的鉤子函數(shù)對(duì)象,然后再通過 setTransitionHooks 函數(shù)去把這個(gè)鉤子函數(shù)對(duì)象設(shè)置到 vnode.transition 上。

          hooks定義

          const hooks={
              mode,
              persisted,
              beforeEnter(el) {
                let hook=onBeforeEnter;
                if (!state.isMounted) {
                  if (appear) {
                    hook=onBeforeAppear || onBeforeEnter;
                  } else {
                    return;
                  }
                }
                if (el._leaveCb) {
                  el._leaveCb(true /* cancelled */);
                }
                const leavingVNode=leavingVNodesCache[key];
                if (
                  leavingVNode &&
                  isSameVNodeType(vnode, leavingVNode) &&
                  leavingVNode.el._leaveCb
                ) {
                  leavingVNode.el._leaveCb();
                }
                callHook(hook, [el]);
              },
              enter(el) {
                let hook=onEnter;
                let afterHook=onAfterEnter;
                let cancelHook=onEnterCancelled;
                if (!state.isMounted) {
                  if (appear) {
                    hook=onAppear || onEnter;
                    afterHook=onAfterAppear || onAfterEnter;
                    cancelHook=onAppearCancelled || onEnterCancelled;
                  } else {
                    return;
                  }
                }
                let called=false;
                const done=(el._enterCb=(cancelled)=> {
                  if (called) return;
                  called=true;
                  if (cancelled) {
                    callHook(cancelHook, [el]);
                  } else {
                    callHook(afterHook, [el]);
                  }
                  if (hooks.delayedLeave) {
                    hooks.delayedLeave();
                  }
                  el._enterCb=undefined;
                });
                if (hook) {
                  hook(el, done);
                  if (hook.length <=1) {
                    done();
                  }
                } else {
                  done();
                }
              },
              leave(el, remove) {
                const key=String(vnode.key);
                if (el._enterCb) {
                  el._enterCb(true /* cancelled */);
                }
                if (state.isUnmounting) {
                  return remove();
                }
                callHook(onBeforeLeave, [el]);
                let called=false;
                const done=(el._leaveCb=(cancelled)=> {
                  if (called) return;
                  called=true;
                  remove();
                  if (cancelled) {
                    callHook(onLeaveCancelled, [el]);
                  } else {
                    callHook(onAfterLeave, [el]);
                  }
                  el._leaveCb=undefined;
                  if (leavingVNodesCache[key]===vnode) {
                    delete leavingVNodesCache[key];
                  }
                });
                leavingVNodesCache[key]=vnode;
                if (onLeave) {
                  onLeave(el, done);
                  if (onLeave.length <=1) {
                    done();
                  }
                } else {
                  done();
                }
              },
              clone(vnode) {
                return resolveTransitionHooks(vnode, props, state, instance);
              },
            };
          

          鉤子函數(shù)對(duì)象定義了 4 個(gè)鉤子函數(shù),分別是 beforeEnterenterleaveclone。在節(jié)點(diǎn) patch 階段的 mountElement 函數(shù)中,在插入節(jié)點(diǎn)前且存在過度會(huì)執(zhí)行 vnode.transition 中的 beforeEnter 函數(shù)

          //beforeEnter 鉤子函數(shù)主要做的事情就是根據(jù) appear 的值和 DOM 是否掛載,來(lái)執(zhí)行 onBeforeEnter 函數(shù)或者是 onBeforeAppear 函數(shù)。appear 是否節(jié)點(diǎn)現(xiàn)實(shí)的時(shí)候執(zhí)行動(dòng)畫
          beforeEnter(el) {
            let hook=onBeforeEnter
            if (!state.isMounted) {
              if (appear) {
                hook=onBeforeAppear || onBeforeEnter
              }
              else {
                return
              }
            }
            if (el._leaveCb) {
              el._leaveCb(true /* cancelled */)
            }
            const leavingVNode=leavingVNodesCache[key]
            if (leavingVNode &&
              isSameVNodeType(vnode, leavingVNode) &&
              leavingVNode.el._leaveCb) {
              leavingVNode.el._leaveCb()
            }
            callHook(hook, [el])
          }
          

          resolveTransitionProps 函數(shù)

          function resolveTransitionProps(rawProps) {
            let {
              name="v",
              type,
              css=true,
              duration,
              enterFromClass=`${name}-enter-from`,
              enterActiveClass=`${name}-enter-active`,
              enterToClass=`${name}-enter-to`,
              appearFromClass=enterFromClass,
              appearActiveClass=enterActiveClass,
              appearToClass=enterToClass,
              leaveFromClass=`${name}-leave-from`,
              leaveActiveClass=`${name}-leave-active`,
              leaveToClass=`${name}-leave-to`,
            }=rawProps;
            const baseProps={};
            for (const key in rawProps) {
              if (!(key in DOMTransitionPropsValidators)) {
                baseProps[key]=rawProps[key];
              }
            }
            if (!css) {
              return baseProps;
            }
            const durations=normalizeDuration(duration);
            const enterDuration=durations && durations[0];
            const leaveDuration=durations && durations[1];
            const {
              onBeforeEnter,
              onEnter,
              onEnterCancelled,
              onLeave,
              onLeaveCancelled,
              onBeforeAppear=onBeforeEnter,
              onAppear=onEnter,
              onAppearCancelled=onEnterCancelled,
            }=baseProps;
            const finishEnter=(el, isAppear, done)=> {
              removeTransitionClass(el, isAppear ? appearToClass : enterToClass);
              removeTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass);
              done && done();
            };
            const finishLeave=(el, done)=> {
              removeTransitionClass(el, leaveToClass);
              removeTransitionClass(el, leaveActiveClass);
              done && done();
            };
            const makeEnterHook=(isAppear)=> {
              return (el, done)=> {
                const hook=isAppear ? onAppear : onEnter;
                const resolve=()=> finishEnter(el, isAppear, done);
                hook && hook(el, resolve);
                nextFrame(()=> {
                  removeTransitionClass(el, isAppear ? appearFromClass : enterFromClass);
                  addTransitionClass(el, isAppear ? appearToClass : enterToClass);
                  if (!(hook && hook.length > 1)) {
                    if (enterDuration) {
                      setTimeout(resolve, enterDuration);
                    } else {
                      whenTransitionEnds(el, type, resolve);
                    }
                  }
                });
              };
            };
            return extend(baseProps, {
              onBeforeEnter(el) {
                onBeforeEnter && onBeforeEnter(el);
                addTransitionClass(el, enterActiveClass);
                addTransitionClass(el, enterFromClass);
              },
              onBeforeAppear(el) {
                onBeforeAppear && onBeforeAppear(el);
                addTransitionClass(el, appearActiveClass);
                addTransitionClass(el, appearFromClass);
              },
              onEnter: makeEnterHook(false),
              onAppear: makeEnterHook(true),
              onLeave(el, done) {
                const resolve=()=> finishLeave(el, done);
                addTransitionClass(el, leaveActiveClass);
                addTransitionClass(el, leaveFromClass);
                nextFrame(()=> {
                  removeTransitionClass(el, leaveFromClass);
                  addTransitionClass(el, leaveToClass);
                  if (!(onLeave && onLeave.length > 1)) {
                    if (leaveDuration) {
                      setTimeout(resolve, leaveDuration);
                    } else {
                      whenTransitionEnds(el, type, resolve);
                    }
                  }
                });
                onLeave && onLeave(el, resolve);
              },
              onEnterCancelled(el) {
                finishEnter(el, false);
                onEnterCancelled && onEnterCancelled(el);
              },
              onAppearCancelled(el) {
                finishEnter(el, true);
                onAppearCancelled && onAppearCancelled(el);
              },
              onLeaveCancelled(el) {
                finishLeave(el);
                onLeaveCancelled && onLeaveCancelled(el);
              },
            });
          }
          

          我們來(lái)看 onBeforeEnter 函數(shù),它的內(nèi)部執(zhí)行了基礎(chǔ) props 傳入的 onBeforeEnter 鉤子函數(shù),并且給 DOM 元素 el 添加了 enterActiveClassenterFromClass 樣式。

          其中,props 傳入的 onBeforeEnter 函數(shù)就是我們寫 Transition 組件時(shí)添加的 beforeEnter 鉤子函數(shù)。enterActiveClass 默認(rèn)值是 v-enter-activeenterFromClass 默認(rèn)值是 v-enter-from,如果給 Transition 組件傳入了 nameprop,比如 fade,那么 enterActiveClass 的值就是 fade-enter-activeenterFromClass 的值就是 fade-enter-from。(onBeforeAppearonBeforeEnter 的邏輯類似,就不贅述了,它是在我們給 Transition 組件傳入 appearProp,且首次掛載的時(shí)候執(zhí)行的。執(zhí)行完 beforeEnter 鉤子函數(shù),接著插入元素到頁(yè)面,然后會(huì)執(zhí)行 vnode.transition 中的 enter 鉤子函數(shù),上面的 hooks 中)

          enter 函數(shù)內(nèi)部,首先執(zhí)行基礎(chǔ) props 傳入的 onEnter 鉤子函數(shù),然后在下一幀給 DOM 元素 el 移除了 enterFromClass,同時(shí)添加了 enterToClass 樣式(動(dòng)畫也就是所謂的樣式交替改變)

          Transition 組件允許我們傳入 enterDuration 這個(gè) prop,它會(huì)指定進(jìn)入過渡的動(dòng)畫時(shí)長(zhǎng),當(dāng)然如果你不指定,Vue.js 內(nèi)部會(huì)監(jiān)聽動(dòng)畫結(jié)束事件,然后在動(dòng)畫結(jié)束后,執(zhí)行 finishEnter 函數(shù)

          來(lái)看它的實(shí)現(xiàn)

          const finishEnter=(el, isAppear, done)=> {
            removeTransitionClass(el, isAppear ? appearToClass : enterToClass);
            removeTransitionClass(el, isAppear ? appearActiveClass : enterActiveClass);
            done && done();
          };
          

          其實(shí)就是給 DOM 元素移除 enterToClass 以及 enterActiveClass,同時(shí)執(zhí)行 done 函數(shù),進(jìn)而執(zhí)行 onAfterEnter 鉤子函數(shù)

          leave 鉤子主要功能和 enter 相反。小伙伴們可自行查閱。

          以上就是對(duì) alert 組件的學(xué)習(xí)。如有不對(duì)歡迎指正。

          么是JavaScript

          JavaScript是一種基于對(duì)象和事件驅(qū)動(dòng)的、并具有安全性能的腳本語(yǔ)言,已經(jīng)被廣泛用于Web應(yīng)用開發(fā),常用來(lái)為網(wǎng)頁(yè)添加各式各樣的動(dòng)態(tài)功能,為用戶提供更流暢美觀的瀏覽效果。通常JavaScript腳本是通過嵌入在HTML中來(lái)實(shí)現(xiàn)自身的功能的。

          JavaScript特點(diǎn)

          是一種解釋性腳本語(yǔ)言(代碼不進(jìn)行預(yù)編譯)。

          主要用來(lái)向HTML(標(biāo)準(zhǔn)通用標(biāo)記語(yǔ)言下的一個(gè)應(yīng)用)頁(yè)面添加交互行為。

          可以直接嵌入HTML頁(yè)面,但寫成單獨(dú)的js文件有利于結(jié)構(gòu)和行為的分離

          跨平臺(tái)特性,在絕大多數(shù)瀏覽器的支持下,可以在多種平臺(tái)下運(yùn)行(如Windows、Linux、Mac、Android、iOS等)。

          JavaScript組成


          JavaScript日常用途

          1、嵌入動(dòng)態(tài)文本于HTML頁(yè)面。

          2、對(duì)瀏覽器事件做出響應(yīng)。

          3、讀寫HTML元素

          4、在數(shù)據(jù)被提交到服務(wù)器之前驗(yàn)證數(shù)據(jù)。

          5、檢測(cè)訪客的瀏覽器信息。

          6、控制cookies,包括創(chuàng)建和修改等。

          7、基于Node.js技術(shù)進(jìn)行服務(wù)器端編程。

          JavaScript的基本結(jié)構(gòu)

          <script type="text/javascript">
           <!—
           JavaScript 語(yǔ)句;
           —>
          </script >
          


          示例:

          ……
          <title>初學(xué)JavaScript</title>
          </head>
          <body>
          <script type="text/javascript">
           document.write("初學(xué)JavaScript");
           document.write("<h1>Hello,JavaScript</h1>");
          </script>
          </body>
          </html>
          


          <script>…</script>可以包含在文檔中的任何地方,只要保證這些代碼在被使用前已讀取并加載到內(nèi)存即可

          JavaScript的執(zhí)行原理


          網(wǎng)頁(yè)中引用JavaScript的方式

          1、使用<script>標(biāo)簽

          2、外部JS文件

          <script src="export.js" type="text/javascript"></script>
          


          3.直接在HTML標(biāo)簽中

          <input name="btn" type="button" value="彈出消息框" 
           onclick="javascript:alert('歡迎你');"/>
          


          JavaScript核心語(yǔ)法:


          1. 變量

          ①先聲明變量再賦值

          var width;
          width=5;
          var - 用于聲明變量的關(guān)鍵字
          width - 變量名
          


          ②同時(shí)聲明和賦值變量

          var catName="皮皮";
          var x, y, z=10;
          


          ③不聲明直接賦值【一般不使用】

          width=5;
          


          變量可以不經(jīng)聲明而直接使用,但這種方法很容易出錯(cuò),也很難查找排錯(cuò),不推薦使用。

          2. 數(shù)據(jù)類型

          ①undefined:示例:var width;

          變量width沒有初始值,將被賦予值undefined

          ②null:表示一個(gè)空值,與undefined值相等

          ③number:

          var iNum=23; //整數(shù)

          var iNum=23.0; //浮點(diǎn)數(shù)

          ④Boolean:true和false 但是JS會(huì)把他們解析成1;0

          ⑤String:一組被引號(hào)(單引號(hào)或雙引號(hào))括起來(lái)的文本 var string1="This is a string";

          3. typeof運(yùn)算符

          typeof檢測(cè)變量的返回值;typeof運(yùn)算符返回值如下:

          ①undefined:變量被聲明后,但未被賦值.

          ②string:用單引號(hào)或雙引號(hào)來(lái)聲明的字符串。

          ③boolean:true或false。

          ④number:整數(shù)或浮點(diǎn)數(shù)。

          ⑤object:javascript中的對(duì)象、數(shù)組和null。

          rometheus發(fā)出告警時(shí)分為兩部分。首先,Prometheus按告警規(guī)則(rule_files配置塊)向Alertmanager發(fā)送告警(即告警規(guī)則是在Prometheus上定義的)。然后,由Alertmanager來(lái)管理這些告警,包括去重(Deduplicating)、分組(Grouping)、靜音(silencing)、抑制(inhibition)、聚合(aggregation ),最終將面要發(fā)出的告警通過電子郵件、webhook等方式將告警通知路由(route)給對(duì)應(yīng)的聯(lián)系人。

          分組:就是將具有相同性質(zhì)的告警先分類,然后當(dāng)作單個(gè)通知發(fā)送出來(lái)。比如A和B兩臺(tái)主機(jī)的磁盤(CPU/內(nèi)存)使用率都在告警,則磁盤的告警就可以合并在一個(gè)通知中發(fā)送出來(lái)。可以想像某個(gè)服務(wù)部署了100個(gè)節(jié)點(diǎn),在一次升版后因?yàn)閎ug,日志中均報(bào)同樣一類錯(cuò)誤,如果不合并這類通知,那就是告警風(fēng)暴。

          抑制:就是某些告警觸發(fā)后,則抑制(禁止)另一些告警。比如收到一條告警提示集群故障無(wú)法訪問,那么在該集群上的所有其他警告應(yīng)該被抑制。

          靜音(默):將某些在預(yù)期內(nèi)的告警設(shè)置為靜默(即不發(fā)送告警)。靜默是基于配置匹配規(guī)則。Alertmanager會(huì)檢查從Prometheus推送過來(lái)的告警事件,看這些告警事件是否與配置的靜默規(guī)則能匹配上,如果匹配則不發(fā)送任何通知。配置靜默方法是在Alertmanager的Web界面中,也可以使用amtool工具。

          總之:Alertmanager制定這一系列規(guī)則目的只有一個(gè),就是提高告警質(zhì)量。


          配置Alertmanager來(lái)做告警通知主要分三個(gè)步驟:

          一、安裝并配置Alertmanager

          # tar -xvf alertmanager-0.20.0.linux-amd64.tar.gz

          mv alertmanager-0.20.0.linux-amd64 /usr/local/alertmanager


          # cat alertmanager.yml

          global:

          resolve_timeout: 5m

          smtp_smarthost: 'smtp.mxhichina.com:465'

          smtp_from: 'noreply@demo.com'

          smtp_auth_username: 'noreply@demo.com'

          smtp_auth_password: '1235698'

          smtp_require_tls: false

          templates:

          - '/usr/local/alertmanager/template/default.tmpl'

          route:

          group_by: ['alertname']

          group_wait: 30s

          group_interval: 2m

          repeat_interval: 10m

          receiver: 'email'

          # continue default is false

          continue: true

          receivers:

          - name: 'email'

          email_configs:

          - to: 'cookingit222@163.com,itcooking222@163.com'

          send_resolved: true

          html: '{{ template "default.html" . }}'

          headers: { Subject: "{{ .GroupLabels.SortedPairs.Values }} [{{ .Status | toUpper }}:{{ .Alerts.Firing | len }}]" }

          inhibit_rules:

          - source_match:

          severity: 'critical'

          target_match:

          severity: 'warning'

          equal: ['alertname', 'dev', 'instance']


          alertmanager配置簡(jiǎn)要說明:

          global:全局配置,主要配置告警方式,如郵件、webhook等。

          route:Prometheus的告警先是到達(dá)alertmanager的根路由(route),alertmanager的根路由不能包含任何匹配項(xiàng),因?yàn)楦酚墒撬懈婢娜肟邳c(diǎn)。另外,根路由需要配置一個(gè)接收器(receiver),用來(lái)處理那些沒有匹配到任何子路由的告警(如果沒有配置子路由,則全部由根路由發(fā)送告警),即缺省接收器。告警進(jìn)入到根route后開始遍歷子route節(jié)點(diǎn),如果匹配到,則將告警發(fā)送到該子route定義的receiver中,然后就停止匹配了。因?yàn)樵趓oute中continue默認(rèn)為false,如果continue為true,則告警會(huì)繼續(xù)進(jìn)行后續(xù)子route匹配。如果當(dāng)前告警仍匹配不到任何的子route,則該告警將從其上一級(jí)(匹配)route或者根route發(fā)出(按最后匹配到的規(guī)則發(fā)出郵件)。

          group_by:用于分組聚合,對(duì)告警通知按標(biāo)簽(label)進(jìn)行分組,將具有相同標(biāo)簽或相同告警名稱(alertname)的告警通知聚合在一個(gè)組,然后作為一個(gè)通知發(fā)送。如果想完全禁用聚合,可以設(shè)置為group_by: [...]

          group_wait: 當(dāng)一個(gè)新的告警組被創(chuàng)建時(shí),需要等待'group_wait'后才發(fā)送初始通知。這樣可以確保在發(fā)送等待前能聚合更多具有相同標(biāo)簽的告警,最后合并為一個(gè)通知發(fā)送。

          group_interval: 當(dāng)?shù)谝淮胃婢ㄖl(fā)出后,在新的評(píng)估周期內(nèi)又收到了該分組最新的告警,則需等待'group_interval'時(shí)間后,開始發(fā)送為該組觸發(fā)的新告警,可以簡(jiǎn)單理解為,group就相當(dāng)于一個(gè)通道(channel)。

          repeat_interval: 告警通知成功發(fā)送后,若問題一直未恢復(fù),需再次重復(fù)發(fā)送的間隔。


          查看你的告警路由樹,將alertmanager.yml配置文件復(fù)制到對(duì)話框,然后點(diǎn)擊"Draw Routing Tree"

          https://www.prometheus.io/webtools/alerting/routing-tree-editor/


          修改好配置文件后,可以使用amtool工具檢查配置

          # ./amtool check-config alertmanager.yml

          Checking 'alertmanager.yml' SUCCESS


          # cat >/usr/lib/systemd/system/alertmanager.service <<EOF

          [Unit]

          Description=alertmanager

          [Service]

          ExecStart=/usr/local/alertmanager/alertmanager --config.file=/usr/local/alertmanager/alertmanager.yml --storage.path=/usr/local/alertmanager/data --web.listen-address=:9093 --data.retention=120h

          Restart=on-failure

          [Install]

          WantedBy=multi-user.target


          EOF


          # systemctl enable alertmanager

          # systemctl restart alertmanager


          alertmanager默認(rèn)運(yùn)行端口是:9093

          alertmanager也可以同prometheus一樣熱加載配置

          1)向alertmanager進(jìn)程發(fā)送SIGHUP信號(hào),如:kill -SIGHUP alertmanager_pid

          2)curl -X POST http://prometheus_ip:9093/-/reload


          二、修改prometheus的配置,關(guān)聯(lián)Alertmanager服務(wù),同時(shí)添加對(duì)alertmanager的監(jiān)控

          # Alertmanager configuration

          alerting:

          alertmanagers:

          - static_configs:

          - targets:

          - monitor01:9093

          rule_files:

          - "rules/*_rules.yml"

          - "rules/*_alerts.yml"

          ......

          - job_name: 'alertmanager'

          static_configs:

          - targets: ['localhost:9093']

          labels:

          app: alertmanager


          三、修改prometheus的配置,添加記錄規(guī)則和告警規(guī)則。

          # cat node_rules.yml

          groups:

          - name: node_rules

          #interval: 15s

          rules:

          - record: instance:node_cpu_usage

          expr: 100 - avg(irate(node_cpu_seconds_total{mode="idle"}[1m])) by (nodename) * 100

          labels:

          metric_type: CPU_monitor

          - record: instance:node_1m_load

          expr: node_load1

          labels:

          metric_type: load1m_monitor

          - record: instance:node_mem_usage

          expr: 100 - (node_memory_MemAvailable_bytes)/(node_memory_MemTotal_bytes) * 100

          labels:

          metric_type: Memory_monitor

          - record: instance:node_root_partition_predit

          expr: round(predict_linear(node_filesystem_free_bytes{device="rootfs",mountpoint="/"}[2h],12*3600)/(1024*1024*1024), 1)

          labels:

          metric_type: root_partition_monitor


          # cat node_alerts.yml

          groups:

          - name: node_alerts

          rules:

          - alert: cpu_usage_over_threshold

          expr: instance:node_cpu_usage > 80

          for: 1m

          labels:

          severity: warning

          annotations:

          summary: 主機(jī) {{ $labels.nodename }} 的 CPU使用率持續(xù)1分鐘超出閾值,當(dāng)前為 {{humanize $value}} %

          - alert: system_1m_load_over_threshold

          expr: instance:node_1m_load > 20

          for: 1m

          labels:

          severity: warning

          annotations:

          summary: 主機(jī) {{ $labels.nodename }} 的 1分負(fù)載超出閾值,當(dāng)前為 {{humanize $value}}

          - alert: mem_usage_over_threshold

          expr: instance:node_mem_usage > 80

          for: 1m

          annotations:

          summary: 主機(jī) {{ $labels.nodename }} 的 內(nèi)存 使用率持續(xù)1分鐘超出閾值,當(dāng)前為 {{humanize $value}} %

          - alert: root_partition_usage_over_threshold

          expr: instance:node_root_partition_predit < 60

          for: 1m

          annotations:

          summary: 主機(jī) {{ $labels.nodename }} 的 根分區(qū) 預(yù)計(jì)在12小時(shí)使用將達(dá)到 {{humanize $value}}GB,超出當(dāng)前可用空間,請(qǐng)及時(shí)擴(kuò)容!


          for 表示告警持續(xù)的時(shí)長(zhǎng),若持續(xù)時(shí)長(zhǎng)小于該時(shí)間就不發(fā)給alertmanager了,大于該時(shí)間再發(fā)。for的值不要小于prometheus中的scrape_interval,例如scrape_interval為30s,for為15s,如果觸發(fā)告警規(guī)則,則再經(jīng)過for時(shí)長(zhǎng)后也一定會(huì)告警,這是因?yàn)樽钚碌亩攘恐笜?biāo)還沒有拉取,在15s時(shí)仍會(huì)用原來(lái)值進(jìn)行計(jì)算。另外,要注意的是只有在第一次觸發(fā)告警時(shí)才會(huì)等待(for)時(shí)長(zhǎng)。

          例如:10:43:00 觸發(fā)了集群A中的h1告警;10:43:10又觸發(fā)了集群A中的h2告警。則在10:44:10后發(fā)生一條告警是只包含h1的郵件,在10:44:20時(shí)會(huì)收到h1和h2聚合后的告警郵件,若h1和h2持續(xù)未恢復(fù),則在repeat_interval后仍以聚合方式發(fā)送告警。

          注:h1和h2告警名相同,只是在不同主機(jī)上。


          完成上述配置后,主機(jī)CPU、負(fù)載、內(nèi)存、磁盤超出閾值時(shí)就發(fā)觸發(fā)郵件告警。

          上述配置僅是對(duì)主機(jī)資源做了監(jiān)控,并且告警只發(fā)到了缺省聯(lián)系人組。設(shè)想一下,在實(shí)際生產(chǎn)環(huán)境中,可能會(huì)按產(chǎn)品線或業(yè)務(wù)功能進(jìn)行分組來(lái)研發(fā),不同的服務(wù)出現(xiàn)告警時(shí)只發(fā)送通知到對(duì)應(yīng)的聯(lián)系人組,其他不相關(guān)的組不需要接告警收通知,這就需要我們修改告警路由規(guī)則,而Alertmanager的核心和最復(fù)雜的地方就在告警路由規(guī)則的設(shè)置上。


          Prometheus的告警規(guī)則在推送給Alertmanager前有的三種狀態(tài):

          1、沒有觸發(fā)告警閾值時(shí),狀態(tài)為:inactive

          2、觸發(fā)了告警閾值但未滿足告警持續(xù)時(shí)間(for)時(shí),狀態(tài)為:pending,如果不配置for或者指定for的值為0,則將跳過pending狀態(tài)。

          3、已觸發(fā)告警閾值并達(dá)到告警持續(xù)時(shí)間,開始將告警事件推送到Alertmanager,此時(shí)狀態(tài)為:firing。


          配置告警靜默(silence),用于在預(yù)期內(nèi)的維護(hù)升級(jí)等操作。

          當(dāng)我們?cè)趯?duì)系統(tǒng)進(jìn)行維護(hù)升級(jí)時(shí),通常不希望觸發(fā)告警通知;另外,當(dāng)上游服務(wù)出現(xiàn)異常,想讓下游的服務(wù)不觸發(fā)告警,Prometheus將用于這種配置稱為silence(靜默)。silence用于設(shè)定一個(gè)(維護(hù))時(shí)間段,如1小時(shí),也可提前手動(dòng)觸發(fā)silence過期,表示維護(hù)結(jié)束,恢復(fù)對(duì)應(yīng)服務(wù)的告警通知功能。

          設(shè)置silence的方式有以下2種:

          1、登錄到alertmanager的控制臺(tái)操作

          2、通過amtool命令進(jìn)行操作


          配置告警模板

          Alertmanager的通知模板是基于Go模板系統(tǒng),詳細(xì)可參考官網(wǎng)。

          https://golang.org/pkg/text/template/

          https://prometheus.io/docs/alerting/latest/notifications/#alert

          https://prometheus.io/docs/prometheus/latest/configuration/template_reference/

          模板配置步驟:

          1、修改alertmanager.yml,配置模板地址,然后在每個(gè)receiver引用模板

          templates:

          - '/usr/local/alertmanager/template/default.tmpl'

          ...

          ...

          html: '{{ template "default.html" . }}'

          headers: { Subject: "{{ .GroupLabels.SortedPairs.Values }} [{{ .Status | toUpper }}:{{ .Alerts.Firing | len }}]" }


          2、配置模板

          default.tmpl

          {{ define "default.html" }}

          {{- if gt (len .Alerts.Firing) 0 -}}

          [{{ .Status | toUpper }}:{{ .Alerts.Firing | len }}]

          {{ range $i, $alert :=.Alerts }}

          <pre>

          告警節(jié)點(diǎn):{{ index $alert.Labels "nodename" }}

          告警服務(wù):{{ index $alert.Labels "alertname" }}

          報(bào)警詳情:{{ index $alert.Annotations "summary" }}

          開始時(shí)間:{{ $alert.StartsAt }}

          </pre>

          {{ end }}

          {{ end }}

          {{- if gt (len .Alerts.Resolved) 0 -}}

          [{{ .Status | toUpper }}:{{ .Alerts.Resolved | len }}]

          {{ range $i, $alert :=.Alerts }}

          <pre>

          恢復(fù)節(jié)點(diǎn):{{ index $alert.Labels "nodename" }}

          恢復(fù)服務(wù):{{ index $alert.Labels "alertname" }}

          狀 態(tài):{{ index $alert.Status }}

          開始時(shí)間:{{ $alert.StartsAt }}

          恢復(fù)時(shí)間:{{ $alert.EndsAt }}

          </pre>

          {{ end }}

          {{ end }}

          {{- end }}


          注:告警模板如果配置有問題,會(huì)導(dǎo)致郵件發(fā)送失敗,注意觀察日志。


          以下是靜默設(shè)置步驟:

          1、登錄到alertmanager控制臺(tái)(http://IP:9093/#/alerts),點(diǎn)擊上方菜單欄中Alerts,可看到當(dāng)前有2個(gè)告警。

          2、點(diǎn)擊右上角"New Silence",創(chuàng)建Silence任務(wù),具體設(shè)置如下,匹配規(guī)則支持正則。

          注:可按instance或job_name等方式來(lái)進(jìn)行正則匹配。


          3、Silence創(chuàng)建成功后,可以看到處于Active狀態(tài)的Silence

          總之,多實(shí)踐。


          主站蜘蛛池模板: 日韩人妻精品无码一区二区三区| 亚洲AV日韩精品一区二区三区| 国产视频一区二区在线观看| 亚洲日本一区二区三区在线| 免费高清av一区二区三区| 亚洲AV综合色区无码一区爱AV| 无码日韩人妻AV一区免费l| 尤物精品视频一区二区三区 | 亚洲bt加勒比一区二区| 香蕉视频一区二区| 亚洲免费一区二区| 无码人妻精品一区二| 内射一区二区精品视频在线观看| 亚洲丰满熟女一区二区哦| 无码人妻一区二区三区一| 国产成人精品久久一区二区三区| 亚洲成AV人片一区二区| 色老头在线一区二区三区 | 精品久久久久久中文字幕一区| 精品欧洲AV无码一区二区男男| 麻豆一区二区三区精品视频| 少妇激情一区二区三区视频| 国产亚洲福利精品一区| 国产精品丝袜一区二区三区| 亚洲A∨无码一区二区三区| 日韩国产精品无码一区二区三区| 中文字幕在线一区| 一区二区三区在线免费看| 精品无码人妻一区二区三区品| 国产一区二区三区韩国女主播| 伊人无码精品久久一区二区| 国产一区二区在线观看麻豆| 亚洲av片一区二区三区| 国产一区二区电影| 中文字幕一区在线观看视频 | 国产成人一区二区三区高清| 亚洲av成人一区二区三区在线观看| 97久久精品午夜一区二区| 久久精品一区二区三区资源网| 久久精品免费一区二区| 国产主播福利精品一区二区|