亚洲乱码中文字幕综合,中国熟女仑乱hd,亚洲精品乱拍国产一区二区三区,一本大道卡一卡二卡三乱码全集资源,又粗又黄又硬又爽的免费视频

前端如何實(shí)現(xiàn)動(dòng)畫過渡效果

 更新時(shí)間:2021年02月05日 09:18:24   作者:donglegend  
這篇文章主要介紹了前端如何實(shí)現(xiàn)動(dòng)畫過渡效果,幫助大家更好的理解和學(xué)習(xí)前端開發(fā)網(wǎng)頁,感興趣的朋友可以了解下

簡介

動(dòng)畫這個(gè)概念非常寬泛,涉及各個(gè)領(lǐng)域,這里我們把范圍縮小到前端網(wǎng)頁應(yīng)用層面上,不用講游戲領(lǐng)域的Animate,一切從最簡單的開始。

目前大部分網(wǎng)頁應(yīng)用都是基于框架開發(fā)的,比如Vue,React等,它們都是基于數(shù)據(jù)驅(qū)動(dòng)視圖的,那么讓我們來對(duì)比一下,還沒有這些框架的時(shí)候我們?nèi)绾螌?shí)現(xiàn)動(dòng)畫或者過渡效果,然后使用數(shù)據(jù)驅(qū)動(dòng)又是如何實(shí)現(xiàn)的。

傳統(tǒng)過渡動(dòng)畫

動(dòng)畫效果對(duì)體驗(yàn)有著非常重要的效果,但是對(duì)于很多開發(fā)者來講,可能是個(gè)非常薄弱的環(huán)節(jié)。在css3出現(xiàn)之后,很多初學(xué)者最常用的動(dòng)畫過渡可能就是css3的能力了。

css過渡動(dòng)畫

css啟動(dòng)過渡動(dòng)畫非常簡單,書寫transition屬性就可以了,下面寫一個(gè)demo

<div id="app" class="normal"></div>
.normal {
  width: 100px;
  height: 100px;
  background-color: red;
  transition: all 0.3s;
}
.normal:hover {
  background-color: yellow;
  width: 200px;
  height: 200px;
}

效果還是很贊的,css3的transition基本滿足了大部分動(dòng)畫需求,如果不滿足還有真正的css3 animation。

animate-css

大名鼎鼎的css動(dòng)畫庫,誰用誰知道。

不管是css3 transition 還是 css3 animation,我們簡單使用都是通過切換class類名,如果要做回調(diào)處理,瀏覽器也提供了 ontransitionend , onanimationend等動(dòng)畫幀事件,通過js接口進(jìn)行監(jiān)聽即可。

var el = document.querySelector('#app')
el.addEventListener('transitionstart', () => {
  console.log('transition start')
})
el.addEventListener('transitionend', () => {
  console.log('transition end')
})

ok,這就是css動(dòng)畫的基礎(chǔ)了,通過js封裝也可以實(shí)現(xiàn)大部分的動(dòng)畫過渡需求,但是局限性在與只能控制css支持的屬性動(dòng)畫,相對(duì)來說控制力還是稍微弱一點(diǎn)。

js動(dòng)畫

js畢竟是自定義編碼程序,對(duì)于動(dòng)畫的控制力就很強(qiáng)大了,而且能實(shí)現(xiàn)各種css不支持的效果。 那么 js 實(shí)現(xiàn)動(dòng)畫的基礎(chǔ)是什么?
簡單來講,所謂動(dòng)畫就是在 時(shí)間軸上不斷更新某個(gè)元素的屬性,然后交給瀏覽器重新繪制,在視覺上就成了動(dòng)畫。廢話少說,還是先來個(gè)栗子:

 <div id="app" class="normal"></div>
// Tween僅僅是個(gè)緩動(dòng)函數(shù)
var el = document.querySelector('#app')
var time = 0, begin = 0, change = 500, duration = 1000, fps = 1000 / 60;
function startSport() {
  var val = Tween.Elastic.easeInOut(time, begin, change, duration);
  el.style.transform = 'translateX(' + val + 'px)';
  if (time <= duration) {
    time += fps
  } else {
    console.log('動(dòng)畫結(jié)束重新開始')
    time = 0;
  }
  setTimeout(() => {
    startSport()
  }, fps)
}
startSport()

在時(shí)間軸上不斷更新屬性,可以通過setTimeout或者requestAnimation來實(shí)現(xiàn)。至于Tween緩動(dòng)函數(shù),就是類似于插值的概念,給定一系列變量,然后在區(qū)間段上可以獲取任意時(shí)刻的值,純數(shù)學(xué)公式,幾乎所有的動(dòng)畫框架都會(huì)使用,想了解的可以參考張鑫旭的Tween.js

OK,這個(gè)極簡demo也是js實(shí)現(xiàn)動(dòng)畫的核心基礎(chǔ)了,可以看到我們通過程序完美的控制了過渡值的生成過程,所有其他復(fù)雜的動(dòng)畫機(jī)制都是這個(gè)模式。

傳統(tǒng)和Vue/React框架對(duì)比

通過前面的例子,無論是css過渡還是js過渡,我們都是直接獲取到 dom元素的,然后對(duì)dom元素進(jìn)行屬性操作。
Vue/React都引入了虛擬dom的概念,數(shù)據(jù)驅(qū)動(dòng)視圖,我們盡量不去操作dom,只控制數(shù)據(jù),那么我們?nèi)绾卧跀?shù)據(jù)層面驅(qū)動(dòng)動(dòng)畫呢?

Vue框架下的過渡動(dòng)畫

可以先看一遍文檔

Vue過渡動(dòng)畫

我們就不講如何使用了,我們來分析一下Vue提供的transition組件是如何實(shí)現(xiàn)動(dòng)畫過渡支持的。

transition組件

先看transition組件代碼,路徑 “src/platforms/web/runtime/components/transition.js”
核心代碼如下:

// 輔助函數(shù),復(fù)制props的數(shù)據(jù)
export function extractTransitionData (comp: Component): Object {
 const data = {}
 const options: ComponentOptions = comp.$options
 // props
 for (const key in options.propsData) {
  data[key] = comp[key]
 }
 // events.
 const listeners: ?Object = options._parentListeners
 for (const key in listeners) {
  data[camelize(key)] = listeners[key]
 }
 return data
}

export default {
 name: 'transition',
 props: transitionProps,
 abstract: true, // 抽象組件,意思是不會(huì)真實(shí)渲染成dom,輔助開發(fā)

 render (h: Function) {
  // 通過slots獲取到真實(shí)渲染元素children
  let children: any = this.$slots.default
  
  const mode: string = this.mode

  const rawChild: VNode = children[0]

  // 添加唯一key
  // component instance. This key will be used to remove pending leaving nodes
  // during entering.
  const id: string = `__transition-${this._uid}-`
  child.key = getKey(id)
    : child.key
  // data上注入transition屬性,保存通過props傳遞的數(shù)據(jù)
  const data: Object = (child.data || (child.data = {})).transition = extractTransitionData(this)
  const oldRawChild: VNode = this._vnode
  const oldChild: VNode = getRealChild(oldRawChild)

  
   // important for dynamic transitions!
   const oldData: Object = oldChild.data.transition = extend({}, data)
 // handle transition mode
   if (mode === 'out-in') {
    // return placeholder node and queue update when leave finishes
    this._leaving = true
    mergeVNodeHook(oldData, 'afterLeave', () => {
     this._leaving = false
     this.$forceUpdate()
    })
    return placeholder(h, rawChild)
   } else if (mode === 'in-out') {
    let delayedLeave
    const performLeave = () => { delayedLeave() }
    mergeVNodeHook(data, 'afterEnter', performLeave)
    mergeVNodeHook(data, 'enterCancelled', performLeave)
    mergeVNodeHook(oldData, 'delayLeave', leave => { delayedLeave = leave })
   }
  return rawChild
 }
}

可以看到,這個(gè)組件本身功能比較簡單,就是通過slots拿到需要渲染的元素children,然后把 transition的props屬性數(shù)據(jù)copy到data的transtion屬性上,供后續(xù)注入生命周期使用,mergeVNodeHook就是做生命周期管理的。

modules/transition

接著往下看生命周期相關(guān),路徑:
src/platforms/web/runtime/modules/transition.js
先看默認(rèn)導(dǎo)出:

function _enter (_: any, vnode: VNodeWithData) {
 if (vnode.data.show !== true) {
  enter(vnode)
 }
}
export default inBrowser ? {
 create: _enter,
 activate: _enter,
 remove (vnode: VNode, rm: Function) {
  if (vnode.data.show !== true) {
   leave(vnode, rm)
  } 
 }
} : {}

這里inBrowser就當(dāng)做true,因?yàn)槲覀兎治龅氖菫g覽器環(huán)境。
接著看enter 和 leave函數(shù),先看enter:

export function addTransitionClass (el: any, cls: string) {
 const transitionClasses = el._transitionClasses || (el._transitionClasses = [])
 if (transitionClasses.indexOf(cls) < 0) {
  transitionClasses.push(cls)
  addClass(el, cls)
 }
}

export function removeTransitionClass (el: any, cls: string) {
 if (el._transitionClasses) {
  remove(el._transitionClasses, cls)
 }
 removeClass(el, cls)
}
export function enter (vnode: VNodeWithData, toggleDisplay: ?() => void) {
 const el: any = vnode.elm

 // call leave callback now
 if (isDef(el._leaveCb)) {
  el._leaveCb.cancelled = true
  el._leaveCb()
 }
 // 上一步注入data的transition數(shù)據(jù)
 const data = resolveTransition(vnode.data.transition)
 if (isUndef(data)) {
  return
 }

 /* istanbul ignore if */
 if (isDef(el._enterCb) || el.nodeType !== 1) {
  return
 }

 const {
  css,
  type,
  enterClass,
  enterToClass,
  enterActiveClass,
  appearClass,
  appearToClass,
  appearActiveClass,
  beforeEnter,
  enter,
  afterEnter,
  enterCancelled,
  beforeAppear,
  appear,
  afterAppear,
  appearCancelled,
  duration
 } = data

 
 let context = activeInstance
 let transitionNode = activeInstance.$vnode

 const isAppear = !context._isMounted || !vnode.isRootInsert

 if (isAppear && !appear && appear !== '') {
  return
 }
 // 獲取合適的時(shí)機(jī)應(yīng)該注入的className
 const startClass = isAppear && appearClass
  ? appearClass
  : enterClass
 const activeClass = isAppear && appearActiveClass
  ? appearActiveClass
  : enterActiveClass
 const toClass = isAppear && appearToClass
  ? appearToClass
  : enterToClass

 const beforeEnterHook = isAppear
  ? (beforeAppear || beforeEnter)
  : beforeEnter
 const enterHook = isAppear
  ? (typeof appear === 'function' ? appear : enter)
  : enter
 const afterEnterHook = isAppear
  ? (afterAppear || afterEnter)
  : afterEnter
 const enterCancelledHook = isAppear
  ? (appearCancelled || enterCancelled)
  : enterCancelled

 const explicitEnterDuration: any = toNumber(
  isObject(duration)
   ? duration.enter
   : duration
 )

 const expectsCSS = css !== false && !isIE9
 const userWantsControl = getHookArgumentsLength(enterHook)
 // 過渡結(jié)束之后的回調(diào)處理,刪掉進(jìn)入時(shí)的class
 const cb = el._enterCb = once(() => {
  if (expectsCSS) {
   removeTransitionClass(el, toClass)
   removeTransitionClass(el, activeClass)
  }
  if (cb.cancelled) {
   if (expectsCSS) {
    removeTransitionClass(el, startClass)
   }
   enterCancelledHook && enterCancelledHook(el)
  } else {
   afterEnterHook && afterEnterHook(el)
  }
  el._enterCb = null
 })


 // dom進(jìn)入時(shí),添加start class進(jìn)行過渡
 beforeEnterHook && beforeEnterHook(el)
 if (expectsCSS) {
  // 設(shè)置過渡開始之前的默認(rèn)樣式
  addTransitionClass(el, startClass)
  addTransitionClass(el, activeClass)
  // 瀏覽器渲染下一幀 刪除默認(rèn)樣式,添加toClass
  // 添加end事件監(jiān)聽,回調(diào)就是上面的cb
  nextFrame(() => {
   removeTransitionClass(el, startClass)
   if (!cb.cancelled) {
    addTransitionClass(el, toClass)
    if (!userWantsControl) {
     if (isValidDuration(explicitEnterDuration)) {
      setTimeout(cb, explicitEnterDuration)
     } else {
      whenTransitionEnds(el, type, cb)
     }
    }
   }
  })
 }

 if (vnode.data.show) {
  toggleDisplay && toggleDisplay()
  enterHook && enterHook(el, cb)
 }

 if (!expectsCSS && !userWantsControl) {
  cb()
 }
}

enter里使用了一個(gè)函數(shù)whenTransitionEnds,其實(shí)就是監(jiān)聽過渡或者動(dòng)畫結(jié)束的事件:

export let transitionEndEvent = 'transitionend'
export let animationEndEvent = 'animationend'
export function whenTransitionEnds (
 el: Element,
 expectedType: ?string,
 cb: Function
) {
 const { type, timeout, propCount } = getTransitionInfo(el, expectedType)
 if (!type) return cb()
 const event: string = type === TRANSITION ? transitionEndEvent : animationEndEvent
 let ended = 0
 const end = () => {
  el.removeEventListener(event, onEnd)
  cb()
 }
 const onEnd = e => {
  if (e.target === el) {
   if (++ended >= propCount) {
    end()
   }
  }
 }
 setTimeout(() => {
  if (ended < propCount) {
   end()
  }
 }, timeout + 1)
 el.addEventListener(event, onEnd)
}

OK,到了這里,根據(jù)上面源代碼的注釋分析,我們可以發(fā)現(xiàn):

  • Vue先是封裝了一些列操作dom className的輔助方法addClass/removeClass等。
  • 然后在生命周期enterHook之后,馬上設(shè)置了startClass也就是enterClass的默認(rèn)初始樣式,還有activeClass
  • 緊接著在瀏覽器nextFrame下一幀,移除了startClass,添加了toClass,并且添加了過渡動(dòng)畫的end事件監(jiān)聽處理
  • 監(jiān)聽到end事件之后,調(diào)動(dòng)cb,移除了toClass和activeClass

leave的過程和enter的處理過程是一樣,只不過是反向添加移除className

結(jié)論:Vue的動(dòng)畫過渡處理方式和 傳統(tǒng)dom本質(zhì)上是一樣,只不過融入了Vue的各個(gè)生命周期里進(jìn)行處理,本質(zhì)上還是在dom 添加刪除的時(shí)機(jī)進(jìn)行處理

React里的過渡動(dòng)畫

噢,我們翻篇了React的文檔,也沒有發(fā)現(xiàn)有過渡動(dòng)畫的處理。嘿,看來官方不原生支持。

但是我們可以自己實(shí)現(xiàn),比如通過useState維護(hù)一個(gè)狀態(tài),在render里根據(jù)狀態(tài)進(jìn)行className的切換,但是復(fù)雜的該怎么辦?

所幸在社區(qū)找到了一個(gè)輪子插件react-transition-group
嗯,直接貼源碼,有了前面Vue的分析,這個(gè)非常容易理解,反而更簡單:

class Transition extends React.Component {
 static contextType = TransitionGroupContext

 constructor(props, context) {
  super(props, context)
  let parentGroup = context
  let appear =
   parentGroup && !parentGroup.isMounting ? props.enter : props.appear

  let initialStatus

  this.appearStatus = null

  if (props.in) {
   if (appear) {
    initialStatus = EXITED
    this.appearStatus = ENTERING
   } else {
    initialStatus = ENTERED
   }
  } else {
   if (props.unmountOnExit || props.mountOnEnter) {
    initialStatus = UNMOUNTED
   } else {
    initialStatus = EXITED
   }
  }

  this.state = { status: initialStatus }

  this.nextCallback = null
 }

 // 初始dom的時(shí)候,更新默認(rèn)初始狀態(tài)
 componentDidMount() {
  this.updateStatus(true, this.appearStatus)
 }
 // data更新的時(shí)候,更新對(duì)應(yīng)的狀態(tài)
 componentDidUpdate(prevProps) {
  let nextStatus = null
  if (prevProps !== this.props) {
   const { status } = this.state

   if (this.props.in) {
    if (status !== ENTERING && status !== ENTERED) {
     nextStatus = ENTERING
    }
   } else {
    if (status === ENTERING || status === ENTERED) {
     nextStatus = EXITING
    }
   }
  }
  this.updateStatus(false, nextStatus)
 }

 updateStatus(mounting = false, nextStatus) {
  if (nextStatus !== null) {
   // nextStatus will always be ENTERING or EXITING.
   this.cancelNextCallback()

   if (nextStatus === ENTERING) {
    this.performEnter(mounting)
   } else {
    this.performExit()
   }
  } else if (this.props.unmountOnExit && this.state.status === EXITED) {
   this.setState({ status: UNMOUNTED })
  }
 }

 performEnter(mounting) {
  const { enter } = this.props
  const appearing = this.context ? this.context.isMounting : mounting
  const [maybeNode, maybeAppearing] = this.props.nodeRef
   ? [appearing]
   : [ReactDOM.findDOMNode(this), appearing]

  const timeouts = this.getTimeouts()
  const enterTimeout = appearing ? timeouts.appear : timeouts.enter
  // no enter animation skip right to ENTERED
  // if we are mounting and running this it means appear _must_ be set
  if ((!mounting && !enter) || config.disabled) {
   this.safeSetState({ status: ENTERED }, () => {
    this.props.onEntered(maybeNode)
   })
   return
  }

  this.props.onEnter(maybeNode, maybeAppearing)

  this.safeSetState({ status: ENTERING }, () => {
   this.props.onEntering(maybeNode, maybeAppearing)

   this.onTransitionEnd(enterTimeout, () => {
    this.safeSetState({ status: ENTERED }, () => {
     this.props.onEntered(maybeNode, maybeAppearing)
    })
   })
  })
 }

 performExit() {
  const { exit } = this.props
  const timeouts = this.getTimeouts()
  const maybeNode = this.props.nodeRef
   ? undefined
   : ReactDOM.findDOMNode(this)

  // no exit animation skip right to EXITED
  if (!exit || config.disabled) {
   this.safeSetState({ status: EXITED }, () => {
    this.props.onExited(maybeNode)
   })
   return
  }

  this.props.onExit(maybeNode)

  this.safeSetState({ status: EXITING }, () => {
   this.props.onExiting(maybeNode)

   this.onTransitionEnd(timeouts.exit, () => {
    this.safeSetState({ status: EXITED }, () => {
     this.props.onExited(maybeNode)
    })
   })
  })
 }

 cancelNextCallback() {
  if (this.nextCallback !== null) {
   this.nextCallback.cancel()
   this.nextCallback = null
  }
 }

 safeSetState(nextState, callback) {
  // This shouldn't be necessary, but there are weird race conditions with
  // setState callbacks and unmounting in testing, so always make sure that
  // we can cancel any pending setState callbacks after we unmount.
  callback = this.setNextCallback(callback)
  this.setState(nextState, callback)
 }

 setNextCallback(callback) {
  let active = true

  this.nextCallback = event => {
   if (active) {
    active = false
    this.nextCallback = null

    callback(event)
   }
  }

  this.nextCallback.cancel = () => {
   active = false
  }

  return this.nextCallback
 }
 // 監(jiān)聽過渡end
 onTransitionEnd(timeout, handler) {
  this.setNextCallback(handler)
  const node = this.props.nodeRef
   ? this.props.nodeRef.current
   : ReactDOM.findDOMNode(this)

  const doesNotHaveTimeoutOrListener =
   timeout == null && !this.props.addEndListener
  if (!node || doesNotHaveTimeoutOrListener) {
   setTimeout(this.nextCallback, 0)
   return
  }

  if (this.props.addEndListener) {
   const [maybeNode, maybeNextCallback] = this.props.nodeRef
    ? [this.nextCallback]
    : [node, this.nextCallback]
   this.props.addEndListener(maybeNode, maybeNextCallback)
  }

  if (timeout != null) {
   setTimeout(this.nextCallback, timeout)
  }
 }

 render() {
  const status = this.state.status

  if (status === UNMOUNTED) {
   return null
  }

  const {
   children,
   // filter props for `Transition`
   in: _in,
   mountOnEnter: _mountOnEnter,
   unmountOnExit: _unmountOnExit,
   appear: _appear,
   enter: _enter,
   exit: _exit,
   timeout: _timeout,
   addEndListener: _addEndListener,
   onEnter: _onEnter,
   onEntering: _onEntering,
   onEntered: _onEntered,
   onExit: _onExit,
   onExiting: _onExiting,
   onExited: _onExited,
   nodeRef: _nodeRef,
   ...childProps
  } = this.props

  return (
   // allows for nested Transitions
   <TransitionGroupContext.Provider value={null}>
    {typeof children === 'function'
     ? children(status, childProps)
     : React.cloneElement(React.Children.only(children), childProps)}
   </TransitionGroupContext.Provider>
  )
 }
}

可以看到,和Vue是非常相似的,只不過這里變成了在React的各個(gè)生命周期函數(shù)了進(jìn)行處理。

到了這里,我們會(huì)發(fā)現(xiàn)不管是Vue的transiton組件,還是React這個(gè)transiton-group組件,著重處理的都是css屬性的動(dòng)畫。

數(shù)據(jù)驅(qū)動(dòng)的動(dòng)畫

而實(shí)際場景中總是會(huì)遇到css無法處理的動(dòng)畫,這個(gè)時(shí)候,可以有兩種解決方案:

通過ref獲取dom,然后采用我們傳統(tǒng)的js方案。
通過state狀態(tài)維護(hù)繪制dom的數(shù)據(jù),不斷通過setState更新state類驅(qū)動(dòng)視圖自動(dòng)刷新

以上就是前端如何實(shí)現(xiàn)動(dòng)畫過渡效果的詳細(xì)內(nèi)容,更多關(guān)于前端實(shí)現(xiàn)動(dòng)畫過渡效果的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • DropDownList控件綁定數(shù)據(jù)源的三種方法

    DropDownList控件綁定數(shù)據(jù)源的三種方法

    本文給大家分享web 中 DropDownList綁定數(shù)據(jù)源的幾種方式以及DropdownList控件動(dòng)態(tài)綁定數(shù)據(jù)源的兩種方法,下面通過本文給大家詳細(xì)介紹,感興趣的朋友一起看看
    2016-12-12
  • canvas學(xué)習(xí)之API整理筆記(一)

    canvas學(xué)習(xí)之API整理筆記(一)

    本文主要介紹了canvas的相關(guān)知識(shí)。canvas本身很簡單,就是去學(xué)習(xí)它的API,多看實(shí)例,多自己動(dòng)手練習(xí),多總結(jié)。本文介紹了很多小例,具有一定的參考價(jià)值,下面跟著小編一起來看下吧
    2016-12-12
  • BootStrap的JS插件之輪播效果案例詳解

    BootStrap的JS插件之輪播效果案例詳解

    Bootstrap 是一個(gè)用于快速開發(fā) Web 應(yīng)用程序和網(wǎng)站的前端框架。這篇文章主要介紹了BootStrap的JS插件之輪播效果案例詳解的相關(guān)資料,需要的朋友可以參考下
    2016-05-05
  • ES6 javascript的異步操作實(shí)例詳解

    ES6 javascript的異步操作實(shí)例詳解

    這篇文章主要介紹了ES6 javascript的異步操作,結(jié)合實(shí)例形式分析了ES5中異步操作的概念、原理、使用方法及相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2017-10-10
  • 微信小程序?qū)崿F(xiàn)簡易table表格

    微信小程序?qū)崿F(xiàn)簡易table表格

    這篇文章主要為大家詳細(xì)介紹了微信小程序?qū)崿F(xiàn)簡易table表格,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2019-02-02
  • 匹配任意字符的正則表達(dá)式寫法

    匹配任意字符的正則表達(dá)式寫法

    今天在寫一個(gè)小應(yīng)用的時(shí)候遇到個(gè)問題,原本是想捕捉到頁面中所有電驢地址,以便迅雷抓取。
    2010-04-04
  • 琥珀無限級(jí)聯(lián)動(dòng)菜單-JavaScript版

    琥珀無限級(jí)聯(lián)動(dòng)菜單-JavaScript版

    琥珀無限級(jí)聯(lián)動(dòng)菜單-JavaScript版...
    2006-11-11
  • uniapp添加車牌組件的實(shí)現(xiàn)與使用

    uniapp添加車牌組件的實(shí)現(xiàn)與使用

    uniapp是2019年火爆的一個(gè)Dcloud開發(fā)跨平臺(tái)前端工具,下面這篇文章主要給大家介紹了關(guān)于uniapp添加車牌組件的實(shí)現(xiàn)與使用,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-05-05
  • js監(jiān)聽F11觸發(fā)全屏事件簡單代碼舉例

    js監(jiān)聽F11觸發(fā)全屏事件簡單代碼舉例

    這篇文章主要給大家介紹了關(guān)于js監(jiān)聽F11觸發(fā)全屏事件的相關(guān)資料,自己工作中遇到的一點(diǎn)點(diǎn)小問題,記錄一下,希望也能對(duì)你們有幫助,需要的朋友可以參考下
    2024-05-05
  • js實(shí)現(xiàn)按Ctrl+Enter發(fā)送效果

    js實(shí)現(xiàn)按Ctrl+Enter發(fā)送效果

    按Ctrl+Enter發(fā)送,思路是監(jiān)聽textarea的onkeydown事件,當(dāng)ctrl鍵被按下,并且,keycode為13(回車),時(shí),調(diào)用發(fā)送表單的函數(shù)
    2014-09-09

最新評(píng)論