整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          Stimulus:連接HTML和Javascript的橋梁,實現復制到粘貼板的按鈕

          一篇文章Stimulus:連接HTML和JavaScript的橋梁,實現簡單的controller,并學習了Stimulus是如何連接HTML與JavaScript的?,F在我們使用Stimulus來實現復制文本到粘貼板的按鈕。

          比如說,我們現在有一個需求,就是幫助用戶生成密碼,在密碼旁邊放置一個按鈕,點擊按鈕后密碼就被拷貝到粘貼板上了,這樣就方便用戶使用這個密碼了。

          打開public/index.html,修改body內容,填充一個簡單的按鈕,如下:

          <div>
              PIN: <input type="text" value="1234" readonly>
              <button>Copy to Clipboard</button>
          </div>



          下一步,創建src/controllers/clipboard_controller.js,然后添加一個copy()方法:

          import { Controller } from "@hotwired/stimulus"
          
          export default class extends Controller {
              copy() {
              }
          }

          然后,給div添加data-controller=“clipboard”。只要是給元素添加了data-controller屬性,Stimulus就會連接一個controller實例。

          <div data-controller="clipboard">

          我們還需要一個對輸入框的引用,這樣我們就可以在調用粘貼板API之前獲取輸入框的內容。給文本框添加data-clipboard-target=“source“:

          PIN: <input data-clipboard-target="source" type="text" value="1234" readonly>

          在controller中定義一個target,然后就可以通過this.sourceTarget訪問文本框了。

          import { Controller } from "@hotwired/stimulus"
          
          export default class extends Controller {
              static targets = [ "source" ]
              
              copy() {
              }
          }


          解釋一下這個targets:

          當Stimulus加載你的controller類時,它會查看靜態數組targets的字符串元素,對于每一個字符串,Stimulus會在controller中添加3個屬性。在這里,對于“source”,會添加如下屬性:

          this.sourceTarget 在controller的域內的第一個source

          this.sourceTargets 在controller的域內所有的source組成的一個數組

          this.hasSourceTarget 在controller的域內是否有source


          我們希望點擊按鈕時調用controller中的copy()方法,所以我們需要添加data-action=“clipboard#copy“

          <button data-action="clipboard#copy">Copy to Clipboard</button>

          你可以已經注意到在上面的動作描述符中省略了click->。那是因為Stimulus給button設置了click作為它默認的事件。


          某些其他元素也有默認事件。下面是個全部列表:

          元素

          默認事件

          a

          click

          button

          click

          details

          toggle

          form

          submit

          input

          input

          input type=“submit”

          click

          select

          change

          textarea

          input

          最終,在copy()方法中,我們獲取輸入框的內容,調用粘貼板API

          copy() {
              navigator.clipboard.writeText(this.sourceTarget.value)
          }


          刷新頁面,點擊按鈕,然后快捷鍵粘貼到Greet按鈕前到輸入框,可以看到1234。



          到目前為止,在頁面上同一時間只有一個controller實例。在頁面上同時有一個controller的多個實例也是很正常的。


          我們的controller是可以復用的,只要你需要在頁面上添加復制內容的按鈕,無論是哪個頁面,只要把對應的屬性值寫好,我們的controller都是生效的。


          還是上面的例子,再添加另外一個復制按鈕:

          <div data-controller="clipboard">
              PIN: <input data-clipboard-target="source" type="text" value="3737" readonly>
              <button data-action="clipboard#copy" class="clipboard-button">Copy to Clipboard</button>
          </div>


          刷新頁面,驗證一下兩個復制按鈕是否都生效。

          我們再添加一個可以復制的元素,不用button,我們用a標簽,

          <div data-controller="clipboard">
              PIN: <input data-clipboard-target="source" type="text" value="6666" readonly>
              <a href="#" data-action="clipboard#copy" class="clipboard-button">Copy to Clipboard</a>
          </div>



          Stimulus允許我們使用任何元素,只要它設置了合適的data-action屬性,就可以觸發復制。

          這個例子里,要注意一點,點擊鏈接會使瀏覽器追蹤a標簽內的href屬性跳轉,可以取消這種默認行為,只需要在action中調用 event.preventDefault()就可以了。

          copy(event) {
              event.preventDefault()    
              navigator.clipboard.writeText(this.sourceTarget.value)
          }


          還有另外一個方法,拷貝粘貼板上

          copy(event) {
              event.preventDefault()    
              this.sourceTarget.select()
              document.execCommand("copy")
          }


          在本文中,我們看了一個在現實中把瀏覽器API包裝在Stimulus的controller中的例子。還有一個controller的多個實例如何同時出現在頁面上,我們還探索了actions和targets如何保持HTML和JavaScript的松散耦合。


          下一篇文章,我們將優化一下這個復制粘貼板的功能,讓它運行起來更加健壯。

          Stimulus:瀏覽器不支持復制或者弱網條件下,怎么辦?

          ueuse擁有大量出色的組合。但是量太大,要把它們全部看完可能會讓人抓不到重點。下面來介紹一些有用到的組合,它們如下:

          1. onClickOutside
          2. useFocusTrap
          3. useHead
          4. useStorage
          5. useVModel
          6. useImage
          7. useDark

          1. onClickOutside

          檢測點擊非常簡單。但是,當點擊發生在一個元素之外時,如何檢測?那就有點棘手了。但使用VueUse中的 onClickOutside 組件就很容易能做到這點。代碼如下:

          <script setup>
          import { ref } from 'vue'
          import { onClickOutside } from '@vueuse/core'
          
          const container = ref(null)
          onClickOutside(container, () => alert('Good. Better to click outside.'))
          </script>
          
          <template>
            <div>
              <p>Hey there, here's some text.</p>
              <div class="container" ref="container">
                <p>Please don't click in here.</p>
              </div>
            </div>
          </template>
          

          為想要追蹤的 container 元素創建一個 ref :

          const container = ref(null);
          

          然后我們用元素上的ref屬性把它變成一個模板ref。

          <div class="container" ref="container">
            <p>Please don't click in here.</p>
          </div>
          

          有了容器的ref 之后,我們把它和一個處理程序一起傳遞給onClickOutside組合。

          onClickOutside(
            container,
            () => alert('Good. Better to click outside.')
          )
          

          這種可組合對于管理窗口或下拉菜單很有用。當用戶點擊下拉菜單以外的地方時,你可以關閉它。

          模態框也通常表現出這種行為。

          事例地址:https://stackblitz.com/edit/vue3-script-setup-with-vite-18scsl?file=src%2FApp.vue

          2.useFocusTrap

          為了擁有可訪問的應用程序,正確地管理焦點非常重要。

          沒有什么比不小心在模態后面加tab,并且無法將焦點返回到模態更糟糕的了。這就是焦點陷阱的作用。

          將鍵盤焦點鎖定在一個特定的DOM元素上,不是在整個頁面中循環,而是在瀏覽器本身中循環,鍵盤焦點只在該DOM元素中循環。

          下面是一個使用VueUse的useFocusTrap的例子:

          <script setup>
          import { ref } from 'vue'
          import { useFocusTrap } from '@vueuse/integrations/useFocusTrap'
          
          const container = ref(null)
          useFocusTrap(container, { immediate: true })
          </script>
          
          <template>
            <div>
              <button tab-index="-1">Can't click me</button>
              <div class="container" ref="container">
                <button tab-index="-1">Inside the trap</button>
                <button tab-index="-1">Can't break out</button>
                <button tab-index="-1">Stuck here forever</button>
              </div>
              <button tab-index="-1">Can't click me</button>
            </div>
          </template>
          

          immediate設置為true,頁面加載時,焦點將被放置在 container 元素中。然后,就不可能在該容器之外的地方做標簽。

          到達第三個按鈕后,再次點擊tab鍵將回到第一個按鈕。

          就像onClickOutside一樣,我們首先為 container 設置了模板ref。

          const container = ref(null)
          
          <div class="container" ref="container">
            <button tab-index="-1">Inside the trap</button>
            <button tab-index="-1">Can't break out</button>
            <button tab-index="-1">Stuck here forever</button>
          </div>
          

          然后我們把這個模板引用傳遞給useFocusTrap組合。

          useFocusTrap(container, { immediate: true });
          

          immediate 選項將自動把焦點設置到容器內第一個可關注的元素上。

          事例地址:https://stackblitz.com/edit/vue3-script-setup-with-vite-eocc6w?file=src%2FApp.vue

          3. useHead

          VueUse為我們提供了一種簡單的方法來更新我們應用程序的 head 部分--頁面 title、scripts和其他可能放在這里的的東西。

          useHead 組合要求我們首先設置一個插件

          import { createApp } from 'vue'
          import { createHead } from '@vueuse/head'
          import App from './App.vue'
          
          const app = createApp(App)
          const head = createHead()
          
          app.use(head)
          app.mount('#app')
          

          一旦我們使用了這個插件,我們就可以隨心所欲地更新標題部分。在這個例子中,我們將在一個按鈕上注入一些自定義樣式。

          <script setup>
          import { ref } from 'vue'
          import { useHead } from '@vueuse/head'
          
          const styles = ref('')
          useHead({
            // Inject a style tag into the head
            style: [{ children: styles }],
          })
          
          const injectStyles = () => {
            styles.value = 'button { background: red }'
          }
          </script>
          
          <template>
            <div>
              <button @click="injectStyles">Inject new styles</button>
            </div>
          </template>
          

          首先,我們創建一個ref來表示我們要注入的樣式,默認為空:

          const styles = ref('');
          

          第二,設置 useHead 將樣式注入到頁面中。

          useHead({
            // Inject a style tag into the head
            style: [{ children: styles }],
          })
          

          然后,添加注入這些樣式的方法:

          const injectStyles = () => {
            styles.value = 'button { background: red }'
          }
          

          當然,我們并不局限于注入樣式。我們可以在我們的<head>中添加任何這些內容:

          1. title
          2. meta tags
          3. link tags
          4. base tag
          5. style tags
          6. script tags
          7. html attributes
          8. body attributes

          事例地址:https://stackblitz.com/edit/vue3-script-setup-with-vite-szhedp?file=src%2FApp.vue

          4. useStorage

          useStorage真的很酷,因為它會自動將 ref 同步到 localstorage,事例如下:

          <script setup>
          import { useStorage } from '@vueuse/core'
          const input = useStorage('unique-key', 'Hello, world!')
          </script>
          
          <template>
            <div>
              <input v-model="input" />
            </div>
          </template>
          

          第一次加載時, input 顯示 'Hello, world!',但最后,它會顯示你最后在 input 中輸入的內容,因為它被保存在localstorage中。

          除了 localstorage,我們也可以指定 sessionstorage:

          const input = useStorage('unique-key', 'Hello, world!', sessionStorage)
          

          當然,也可以自己實現存儲系統,只要它實現了StorageLike接口。

          export interface StorageLike {
            getItem(key: string): string | null
            setItem(key: string, value: string): void
            removeItem(key: string): void
          }
          

          5. useVModel

          v-model指令是很好的語法糖,使雙向數據綁定更容易。

          useVModel更進一步,擺脫了一堆沒有人真正想寫的模板代碼。

          <script setup>
          import { useVModel } from '@vueuse/core'
          
          const props = defineProps({
            count: Number,
          })
          const emit = defineEmits(['update:count'])
          
          const count = useVModel(props, 'count', emit)
          </script>
          
          <template>
            <div>
              <button @click="count = count - 1">-</button>
              <button @click="count = 0">Reset to 0</button>
              <button @click="count = count + 1">+</button>
            </div>
          </template>
          

          在這個例子中,我們首先定義了要附加到v-model上的 props:

          const props = defineProps({
            count: Number,
          })
          

          然后我們發出一個事件,使用v-model的命名慣例update:<propName>:

          const emit = defineEmits(['update:count'])
          

          現在,我們可以使用useVModel組合來將 prop和事件綁定到一個ref。

          const count = useVModel(props, 'count', emit)
          

          每當 prop 發生變化時,這個 count 就會改變。但只要它從這個組件中被改變,它就會發出update:count事件,通過v-model指令觸發更新。

          我們可以像這樣使用這個 Input 組件。

          <script setup>
          import { ref } from 'vue'
          import Input from './components/Input.vue'
          
          const count = ref(50)
          </script>
          
          <template>
            <div>
              <Input v-model:count="count" />
              {{ count }}
            </div>
          </template>
          

          這里的count ref是通過v-model綁定與 Input組件內部的count ref同步的。

          事例地址:https://stackblitz.com/edit/vue3-script-setup-with-vite-ut5ap8?file=src%2FApp.vue

          6. useImage

          隨著時間的推移,web應用中的圖像變得越來越漂亮。我們已經有了帶有srcset的響應式圖像,漸進式加載庫,以及只有在圖像滾動到視口時才會加載的庫。

          但你知道嗎,我們也可以訪問圖像本身的加載和錯誤狀態?

          我以前主要通過監聽每個HTML元素發出的onloadonerror事件來做到這一點,但VueUse給我們提供了一個更簡單的方法,那就是useImage組合。

          <script setup>
          import { useImage } from '@vueuse/core'
          
          // Change this to a non-existent URL to see the error state
          const url = 'https://source.unsplash.com/random/400x300'
          const { isLoading, error } = useImage(
            {
              src: url,
            },
            {
              // Just to show the loading effect more clearly
              delay: 2000,
            }
          )
          </script>
          
          <template>
            <div>
              <div v-if="isLoading" class="loading gradient"></div>
              <div v-else-if="error">Couldn't load the image :(</div>
              <img v-else :src="url" />
            </div>
          </template>
          

          第一步,通過useImage 設置圖片的src:

          const { isLoading, error } = useImage({ src: url })
          

          獲取它返回的isLoadingerror引用,以便跟蹤狀態。這個組合在內部使用useAsyncState,因此它返回的值與該組合的值相同。

          安排好后,useImage 就會加載我們的圖像并將事件處理程序附加到它上面。

          我們所要做的就是在我們的模板中使用相同的URL來使用該圖片。由于瀏覽器會重復使用任何緩存的圖片,它將重復使用由useImage加載的圖片。

          <template>
            <div>
              <div v-if="isLoading" class="loading gradient"></div>
              <div v-else-if="error">Couldn't load the image :(</div>
              <img v-else :src="url" />
            </div>
          </template>
          

          在這里,我們設置了一個基本的加載和錯誤狀態處理程序。當圖片正在加載時,我們顯示一個帶有動畫漸變的占位符。如果有錯誤,我們顯示一個錯誤信息。否則我們可以渲染圖像。

          UseImage 還有其他一些很棒的特性!如果想讓它成為響應式圖像,那么它支持srcsetsizes屬性,這些屬性在幕后傳遞給img元素。

          如果你想把所有內容都放在模板中,還有一個無渲染組件。它的工作原理與組合的相同:

          <template>
           <UseImage src="https://source.unsplash.com/random/401x301">
              <template #loading>
             <div class="loading gradient"></div>
            </template>
              <template #error>
             Oops!
            </template>
            </UseImage>
          </template>
          

          事例:https://stackblitz.com/edit/vue3-script-setup-with-vite-d1jsec?file=src%2FApp.vue

          7. 暗黑模式 useDark

          最近,每個網站和應用程序似乎都有暗黑模式。最難的部分是造型的改變。但是一旦你有了這些,來回切換就很簡單了。

          如果你使用的是Tailwind,你只需要在html元素中添加dark類,就可以在整個頁面中啟用。

          <html class="dark"><!-- ... --></html>
          

          然而,在黑暗模式和光明模式之間切換時,有幾件事需要考慮。首先,我們要考慮到用戶的系統設置。第二,我們要記住他們是否已經推翻了這個選擇。

          VueUse的useDark組合性為我們把所有這些東西都包起來。默認情況下,它查看系統設置,但任何變化都會被持久化到localStorage,所以設置會被記住。

          <script setup>
          import { useDark, useToggle } from '@vueuse/core'
          
          const isDark = useDark()
          const toggleDark = useToggle(isDark)
          </script>
          
          <template>
            <div class="container">
              Changes with dark/light mode.
          
              <button @click="toggleDark()">
             Enable {{ isDark ? 'Light' : 'Dark' }} Mode
            </button>
            </div>
          </template>
          

          黑暗模式的樣式:

          .dark .container {
            background: slategrey;
            color: white;
            border-color: black;
          }
          
          .dark button {
            background: lightgrey;
            color: black;
          }
          
          .dark body {
            background: darkgrey;
          }
          

          如果你沒有使用Tailwind,你可以通過傳入一個選項對象來完全定制黑暗模式的應用方式。下面是默認的Tailwind:

          const isDark = useDark({
            selector: 'html',
            attribute: 'class',
            valueDark: 'dark',
            valueLight: '',
          })
          

          也可以提供一個onChanged處理程序,這樣你就可以編寫任何你需要的Javascript。這兩種方法使你可以使它與你已有的任何造型系統一起工作。

          總結

          Vueuse 擁有一個巨大的庫,其中包含出色的組合,而我們在這里只涵蓋了其中的一小部分。我強烈建議你花些時間去探索這些文檔,看看所有可用的東西。這是一個非常好的資源,它將使你免于大量的模板代碼和不斷地重新發明車輪。


          作者:Noveo 譯者:小智 來源:vuemastery 原文:https://www.vuemastery.com/blog/best-vueue-composables

          、需求分析

          1、需求:點擊關閉之后,頂部廣告圖可以關閉

          2、分析:

          點擊的是關閉按鈕

          關閉的是父盒子

          利用樣式的顯示和隱藏完成, display:none 隱藏元素 display:block 顯示元素


          <script src="https://lf6-cdn-tos.bytescm.com/obj/cdn-static-resource/tt_player/tt.player.js?v=20160723"></script>


          二、HTML代碼準備

          準備好一個div盒子,在里面放上圖片和一個小的div盒子


          HTML代碼準備

          三、CSS樣式設置

          1、導入css外部樣式文件

          導入css外部樣式文件

          2、給大的div盒子設置寬高1190px*80px


          div大盒子樣式設置

          3、小的div盒子設置寬高20px*20px,背景色為#666,文字X水平居中、行高20px(行高為了垂直居中),鼠標移到上面的時候變為小手(cursor: pointer)


          div小盒子樣式設置


          4、定位小盒子到廣告圖右上角,利用父相對,子絕對的定位方法,將小盒子移動到距離圖片頂部和右側5px的位置


          定位小盒子到廣告圖右上角

          CSS樣式設置好后效果圖

          四、點擊關閉功能實現

          1、導入js外部文件


          導入js外部文件

          2、獲取元素對象,分別獲取大盒子和小盒子的元素對象


          獲取元素對象

          3、點擊小盒子時,關閉大盒子(將大盒子隱藏,即將大盒子的display屬性值改為none

          點擊小盒子時,關閉大盒子


          以上就是如何實現京東點擊關閉頂部廣告功能的方法,你學“廢”了嗎


          主站蜘蛛池模板: www亚洲精品少妇裸乳一区二区| 精品免费AV一区二区三区| 国产伦一区二区三区免费| 人妻免费一区二区三区最新| 精品一区二区三区在线播放视频| 国产精品视频免费一区二区三区| 国产高清不卡一区二区| 美女视频黄a视频全免费网站一区| 亚洲成AV人片一区二区密柚| 精品乱人伦一区二区| 欧美日韩精品一区二区在线视频| 三上悠亚精品一区二区久久| 国产在线一区二区三区av| 久久久久人妻一区精品色| 中文日韩字幕一区在线观看| 免费高清av一区二区三区| 激情亚洲一区国产精品| 另类免费视频一区二区在线观看| 日本美女一区二区三区| 国产精品视频一区国模私拍| 精品无码一区二区三区在线| 精品一区二区在线观看| 中文字幕一区二区区免| 美女视频一区二区三区| 午夜视频一区二区三区| 最新欧美精品一区二区三区| 午夜影视日本亚洲欧洲精品一区| 波多野结衣高清一区二区三区| 在线不卡一区二区三区日韩| 国产精品视频一区二区猎奇| 麻豆AV一区二区三区| 色噜噜狠狠一区二区三区果冻| 精品国产一区二区三区久久| 色狠狠色噜噜Av天堂一区| 色婷婷AV一区二区三区浪潮| 伊人精品视频一区二区三区| 无人码一区二区三区视频| 国产在线精品一区二区中文| 亚洲乱码日产一区三区| 日韩精品无码一区二区视频| 91久久精一区二区三区大全|