vue 遞歸創建菜單_如何在Vue中創建類似中等的突出顯示菜單

vue 遞歸創建菜單

by Taha Shashtari

由Taha Shashtari

如何在Vue中創建類似中等的突出顯示菜單 (How to Create a Medium-Like Highlight Menu in Vue)

A cool feature in Medium is the highlight menu that pops up when you select some text. This menu contains buttons that allow you to perform certain actions on the selected text like highlight and share.

在一個很酷的功能中是當你選擇一些文本在彈出的菜單中的亮點。 此菜單包含一些按鈕,這些按鈕使您可以對所選文本執行某些操作,例如突出顯示和共享。

If you like this feature and you want to have it in your site, I’m going to show you how to create a reusable component that enables this behavior on the text it contains.

如果您喜歡此功能,并且希望在您的網站中使用它,我將向您展示如何創建可重用的組件,以在其包含的文本上啟用此行為。

You can try a live demo on CodePen:

您可以在CodePen上嘗試現場演示:

View the CodePen here.

在此處查看CodePen。

使用Vue CLI 3創建一個新項目 (Creating a new project with Vue CLI 3)

With Vue CLI 3 instant prototyping, we can rapidly run a Vue app with just a single *.vue file.

借助Vue CLI 3 即時原型 ,我們可以僅使用一個*.vue文件快速運行Vue應用程序。

Note that this is only used for creating prototypes, not for production.

請注意,這僅用于創建原型,而不用于生產。

First, make sure that you have this installed globally:

首先,請確保已在全球范圍內安裝了此軟件:

npm install -g @vue/cli-service-global

npm install -g @vue/cli-service-global

In this app, we’ll only need two files: App.vue and Highlightable.vue.

在此應用程序中,我們僅需要兩個文件: App.vueHighlightable.vue

Highlightable.vue is our reusable highlight menu component. And App.vue is the main page component.

Highlightable.vue是我們可重用的突出顯示菜單組件。 而App.vue是主要的頁面組件。

Create both files in any directory you want; then, run vue serve on App.vue.

在所需的任何目錄中創建兩個文件; 然后,在App.vue上運行vue serve

vue serve App.vue

實施App.vue (Implementing App.vue)

In App.vue, we'll add two paragraphs. One that can be highlighted, and one that can't.

App.vue中 ,我們將添加兩個段落。 一種可以突出顯示,另一種不能突出顯示。

We’ll also import and use Highlightable.vue before even creating it. (This is helpful to see how we're going to use it.)

我們甚至會在創建之前導入并使用Highlightable.vue 。 (這有助于了解我們將如何使用它。)

Here’s how it should look in the end:

最終效果如下:

<template>  <div class="app">    <highlightable      @share="onShare"      @highlight="onHighlight"    >      <p>        Lorem ipsum dolor sit amet, consectetur adipisicing elit. Eveniet at debitis deserunt, optio rem eaque obcaecati non possimus nisi assumenda architecto exercitationem dolore quo praesentium, deleniti reiciendis sed ab nihil!      </p>    </highlightable>    <p>      <strong>This paragraph can't be highlighted.</strong> Lorem ipsum dolor sit amet, consectetur adipisicing elit. Labore ipsam repellat, fugiat aut ex incidunt ut quisquam quasi consequatur ducimus quo in, cum soluta eos dolores tempore unde voluptate modi.    <;/p&gt;  </div></template&gt;<script>import Highlightable from './Highlightable'export default {  components: { Highlightable },  methods: {    onShare (text) {      console.log('share:', text)    },    onHighlight (text) {      console.log('highlight:', text)    }  }}</script><style scoped>* {  box-sizing: border-box;}.app {  width: 800px;  margin: 40px auto;  padding: 10px;  font-family: Verdana;  color: #333;  width: 100%;}p {  line-height: 1.5;}</style>

As you can see above, we're handling two events from Highlightable. These two events are the actions of the buttons in the highlight menu. These are just examples. You can change them to whatever you want.

正如您在上面看到的,我們正在處理Highlightable中的兩個事件。 這兩個事件是高亮菜單中按鈕的動作。 這些僅僅是示例。 您可以將它們更改為任何您想要的。

實施Highlightable.vue (Implementing Highlightable.vue)

The template section consists of two parts: the menu element with buttons and <slot/> to display the text.

模板部分由兩部分組成:帶按鈕的菜單元素和用于顯示文本的<slo t />。

Let’s start with this code in the template:

讓我們從模板中的以下代碼開始:

<template>  <div>    <div      v-show="showMenu"      class="menu"    >      <span class="item">        Share      </span>      <span class="item">        Highlight      </span>      <!-- You can add more buttons here -->    </div>    <!-- The insterted text should be displayed here -->    <slot/>  </div></template>

Note that we're using showMenu, which we haven't created yet, to determine if we should display the menu.

請注意,我們使用尚未創建的showMenu來確定是否顯示菜單。

Now let's move to the styling part.

現在,讓我們轉到樣式部分。

Add the following CSS to <style> section:

將以下CSS添加到<sty le>部分:

&lt;style scoped>.menu {  height: 30px;  padding: 5px 10px;  background: #333;  border-radius: 3px;  position: absolute;  top: 0;  left: 0;  transform: translate(-50%, -100%);  transition: 0.2s all;  display: flex;  justify-content: center;  align-items: center;}.menu:after {  content: '';  position: absolute;  left: 50%;  bottom: -5px;  transform: translateX(-50%);  width: 0;  height: 0;  border-left: 6px solid transparent;  border-right: 6px solid transparent;  border-top: 6px solid #333;}.item {  color: #FFF;  cursor: pointer;}.item:hover {  color: #1199ff;}.item + .item {  margin-left: 10px;}&lt;/style>

Nothing is too complex here. .menu is for the highlight menu. menu:after is for the little triangle (arrow) in the bottom center of the menu.

這里沒有什么太復雜的。 .menu用于突出顯示菜單。 menu:aftermenu:after底部中心的小三角形(箭頭)。

One important thing to note here is that .menu has an absolute position. We need this to position it above the selected text.

這里要注意的重要一件事是.menu具有absolute位置。 我們需要將其放置在所選文本上方。

Finally, let's move to the <script> section.

最后,讓我們進入<scri pt>部分。

Let's start with the data.

讓我們從data開始。

export default {  data () {    return {      x: 0,      y: 0,      showMenu: false,      selectedText: ''    }  }}
  • x and y are for positioning the menu.

    xy用于放置菜單。

  • showMenu to show/hide the menu.

    showMenu顯示/隱藏菜單。

  • selectedText will contain the actual content of the selected text.

    selectedText將包含所選文本的實際內容。

Now, let's move to computed.

現在,讓我們開始計算

computed: {  highlightableEl () {    return this.$slots.default[0].elm  }}

We only have a single computed property that returns the element used in the slot section of Highlightable. In our example, it would be the <;p> tag between <highlightable></highlightable>.

我們只有一個計算屬性,該屬性返回Highlightable的插槽部分中使用的元素。 在我們的示例中,將是tween <highlightable>< / highlightable>之間的< ; p>標記。

Then, let's add mounted and beforeDestroy hook functions.

然后,讓我們添加mountedbeforeDestroy掛鉤函數。

mounted () {  window.addEventListener('mouseup', this.onMouseup)},beforeDestroy () {  window.removeEventListener('mouseup', this.onMouseup)}

We use these to listen for mouseup event, which we handle inside onMouseup method.

我們使用它們來監聽mouseup事件,該事件在onMouseup方法內部處理。

Now, let's create onMouseup method.

現在,讓我們創建onMouseup方法。

methods: {  onMouseup () {    const selection = window.getSelection()    const selectionRange = selection.getRangeAt(0)    // startNode is the element that the selection starts in    const startNode = selectionRange.startContainer.parentNode    // endNode is the element that the selection ends in    const endNode = selectionRange.endContainer.parentNode    // if the selected text is not part of the highlightableEl (i.e. <p>)    // OR    // if startNode !== endNode (i.e. the user selected multiple paragraphs)    // Then    // Don't show the menu (this selection is invalid)    if (!startNode.isSameNode(this.highlightableEl) || !startNode.isSameNode(endNode)) {      this.showMenu = false      return    }    // Get the x, y, and width of the selection    const { x, y, width } = selectionRange.getBoundingClientRect()    // If width === 0 (i.e. no selection)    // Then, hide the menu    if (!width) {      this.showMenu = false      return    }    // Finally, if the selection is valid,    // set the position of the menu element,    // set selectedText to content of the selection    // then, show the menu    this.x = x + (width / 2)    this.y = y + window.scrollY - 10    this.selectedText = selection.toString()    this.showMenu = true  }}

Now let's update the template of Highlightable.vue to reflect the new changes.

現在,讓我們更新Highlightable.vue的模板以反映新的更改。

<template>  <div>    <div      v-show="showMenu"      class="menu"      :style="{        left: `${x}px`,        top: `${y}px`      }"      @mousedown.prevent=""    >      <span        class="item"        @mousedown.prevent="handleAction('share')"      >        Share      </span>      <span        class="item"        @mousedown.prevent="handleAction('highlight')"      >        Highlight      </span>      <!-- You can add more buttons here -->    </div>    <!-- The insterted text should be displayed here -->    <slot/>  </div></template>

The changes are:

更改為:

  • Applied the positions to the menu element.

    將位置應用于菜單元素。
  • Added @mousedown.prevent="" to the menu element to prevent the menu from closing when clicking inside it.

    在菜單元素中添加了@mousedown.prevent="" ,以防止在內部單擊時關閉菜單。

  • Added @mousedown.prevent="handleAction('share')" on share button to handle the clicked action. The same is for the highlight action.

    在共享按鈕上添加了@mousedown.prevent="handleAction('share')"來處理單擊的操作。 高亮操作也是如此。

Note that we're using mousedown event instead of click to prevent the text from getting unselected — which would cause the menu to close.

請注意,我們使用mousedown事件而不是click事件來防止未選中文本-這將導致菜單關閉。

The last thing we have to do is add the handleAction method.

我們要做的最后一件事是添加handleAction方法。

handleAction (action) {  this.$emit(action, this.selectedText)}

This method emits the action event and passes the selected text along with it. (We used this event in App.vue, remember?)

此方法發出action事件,并將所選文本與之一起傳遞。 (我們在App.vue中使用了此事件,還記得嗎?)

With that, we're done! Now you have a reusable component that you can use to show a highlight menu for the selected text, just like Medium does.

這樣,我們就完成了! 現在,您有了一個可重用的組件,可以像Medium一樣使用它來顯示所選文本的突出顯示菜單。

Thanks for reading! By the way, I’m writing a book on how to build a complete single-page application from scratch using Vue. Check out the book’s landing page if you’re interested in learning more about what the book will cover:

謝謝閱讀! 順便說一句,我正在寫一本關于如何使用Vue從頭構建完整的單頁應用程序的書。 如果您有興趣了解有關該書涵蓋內容的更多信息,請查看該書的登錄頁面:

翻譯自: https://www.freecodecamp.org/news/how-to-create-a-medium-like-highlight-menu-in-vue-dc515f2dddef/

vue 遞歸創建菜單

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/392496.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/392496.shtml
英文地址,請注明出處:http://en.pswp.cn/news/392496.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

leetcode 376. 擺動序列(dp)

如果連續數字之間的差嚴格地在正數和負數之間交替&#xff0c;則數字序列稱為擺動序列。第一個差&#xff08;如果存在的話&#xff09;可能是正數或負數。少于兩個元素的序列也是擺動序列。 例如&#xff0c; [1,7,4,9,2,5] 是一個擺動序列&#xff0c;因為差值 (6,-3,5,-7,3…

在ASP.NET Atlas中調用Web Service——創建Mashup調用遠端Web Service(基礎知識以及簡單示例)...

作者&#xff1a;Dflying Chen &#xff08;http://dflying.cnblogs.com/&#xff09; 注&#xff1a;Atlas中的Mashup極其復雜&#xff0c;其中涉及眾多的對象與架構&#xff0c;為了寫這篇文章&#xff0c;我花了不少時間學習研究。同時&#xff0c;關于這方面資源的匱乏簡直…

java彈框形式輸入_java中點擊一個按鈕彈出兩個輸入文本框的源代碼

展開全部寫了一個很簡單的案例,可以參考和修改import java.awt.BorderLayout;import java.awt.GridLayout;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import javax.swing.JButton;import javax.swing.JDialog;import javax.swing.JFrame;import…

sap wm內向交貨步驟_內向型人在數據科學中成功的五個有效步驟

sap wm內向交貨步驟Just like most attributes of humans, including both the bright and dark sides, being an introvert is no exception. This article was not written to inspire you as most articles about data science or engineering do. What we want is that by …

C# 學習之路--百度網盤爬蟲設計與實現(一)

百度網盤爬蟲 現在市面上出現了很多網盤搜索引擎&#xff0c;寫這系列博文及爬蟲程序的初衷&#xff1a; 更方面的查找資源學習C#學習爬蟲的設計與實現記錄學習歷程自我監督 能力有限&#xff0c;如有不妥之處&#xff0c;還請各位看官點評。同在學習的網友~與君共勉。工具/庫選…

實習生對企業的認識_如何成為您認識的超級明星實習生

實習生對企業的認識by Maple Ong由Maple Ong 如何成為您認識的超級明星實習生 (How to be The Superstar Intern You Know You Are) 遏制冒名頂替綜合癥&#xff0c;為即將到來的軟件工程實習做準備 (Curb the Impostor Syndrome and get prepared for your upcoming Software…

7時過2小時是幾時_2017最北師大版二年級下冊數學第七單元《時、分、秒》過關檢測卷...

二年級數學下冊時分秒測試卷一、填一填。(每空1分&#xff0c;共36分)1.鐘面上有()大格&#xff0c;()個小格&#xff0c;時針走1個大格是()時&#xff0c;分針走一個大格是()分。2.1分()秒()分1時1分15秒()秒3.1小時20分()分90分()小時()分 70秒()分()秒4.用時、分、秒填空a)我…

在沒人相信的時候,你的堅持才真正可貴

2018 世界 VR 產業大會在南昌開幕&#xff0c;阿里巴巴創始人馬云在演講中說&#xff1a; “在人人都相信一個產業的時候&#xff0c;其實你已經沒有機會了。在沒有人相信的時候&#xff0c;你的堅持才是真正的珍貴。很多人是因為看見而相信&#xff0c;只有很少數的人是因為相…

leetcode 49. 字母異位詞分組(排序+hash)

給定一個字符串數組&#xff0c;將字母異位詞組合在一起。字母異位詞指字母相同&#xff0c;但排列不同的字符串。 示例: 輸入: [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 輸出: [ [“ate”,“eat”,“tea”], [“nat”,“tan”], [“bat”] ] 代碼 class S…

數據庫備份策略 分布式_管理優秀的分布式數據團隊的4種基本策略

數據庫備份策略 分布式COVID-19 has forced nearly every organization to adapt to a new workforce reality: distributed teams. We share four key tactics for turning your remote data team into a force multiplier for your entire company.COVID-19迫使幾乎每個組織都…

如何使用阿里云云解析API實現動態域名解析,搭建私有服務器

原文地址&#xff1a;http://www.yxxrui.cn/article/116.shtml 未經許可請勿轉載&#xff0c;如有疑問&#xff0c;請聯系作者&#xff1a;yxxrui163.com 公司的網絡沒有固定的公網IP地址&#xff0c;但是能夠保證的是&#xff0c;每次動態分配的IP地址均為獨立的公網IP&#x…

新手指南:dvwa_如何構建基本的Slackbot:新手指南

新手指南:dvwaBy Vishwa ShahVishwa Shah著 Update: code and tutorial updated on June 28 to reflect Slack API changes.更新&#xff1a;代碼和教程已于6月28日更新&#xff0c;以反映Slack API的更改 。 Slackbots&#xff1a;為什么要使用它們&#xff1f; (Slackbots:…

java 加載class文件路徑_動手實現MVC: 1. Java 掃描并加載包路徑下class文件

背景用過spring框架之后&#xff0c;有個指定掃描包路徑&#xff0c;然后自動實例化一些bean&#xff0c;這個過程還是比較有意思的&#xff0c;抽象一下&#xff0c;即下面三個點如何掃描包路徑下所有的class文件如何掃描jar包中對應包路徑下所有的class文件如何加載class文件…

leetcode 738. 單調遞增的數字(貪心算法)

給定一個非負整數 N&#xff0c;找出小于或等于 N 的最大的整數&#xff0c;同時這個整數需要滿足其各個位數上的數字是單調遞增。 &#xff08;當且僅當每個相鄰位數上的數字 x 和 y 滿足 x < y 時&#xff0c;我們稱這個整數是單調遞增的。&#xff09; 示例 1: 輸入: …

python+[:]+切片_我從C ++到Python的方式:概念上的改變

python[:]切片by asya f由asya f 我從C 到Python的方式&#xff1a;概念上的改變 (How I went from C to Python: a conceptual change) 介紹 (Introduction) People say that coding in Python is so easy that even a 6 year old can do it. This was the thought that I ha…

深度學習 免費課程_2020年排名前三的免費深度學習課程

深度學習 免費課程&#xff03;1 Fastai面向程序員的實用深度學習2020 (#1 Fastai Practical Deep Learning for Coders 2020) On 21 of August 2020, fastai released the new version of the fastai library and of their Deep Learning course!2020年8月21日&#xff0c;fas…

mysql復制主從集群搭建

近期搭了個主從復制。中間出了點小問題&#xff0c;排查搞定&#xff0c;記錄下來1環境&#xff1a;虛擬機&#xff1a;OS:centos6.5Linux host2 2.6.32-431.el6.x86_64 #1 SMP Fri Nov 22 03:15:09 UTC 2013 x86_64 x86_64 x86_64 GNU/LinuxserverIP192.168.18.66192.168.18.6…

java jolt tuxedo_java通過jolt調用tuxedo服務.xls

java通過jolt調用tuxedo服務.xls還剩20頁未讀&#xff0c;繼續閱讀下載文檔到電腦&#xff0c;馬上遠離加班熬夜&#xff01;親&#xff0c;喜歡就下載吧&#xff0c;價低環保&#xff01;內容要點&#xff1a;?private bea.jolt.pool.servlet.ServletSessionPoolManager bool…

你的周末時光是什么樣的?

周末是一個特殊的假日&#xff0c;隔三差五就會有&#xff0c;來的容易去得也容易&#xff0c;即便如此&#xff0c;我們還是應該好好珍惜&#xff0c;周末可以做的事太多了&#xff0c;既可以用來減壓&#xff0c;也可以為下一周的學習和工作充電&#xff0c;不管做什么&#…

leetcode 290. 單詞規律(hash)

給定一種規律 pattern 和一個字符串 str &#xff0c;判斷 str 是否遵循相同的規律。 這里的 遵循 指完全匹配&#xff0c;例如&#xff0c; pattern 里的每個字母和字符串 str 中的每個非空單詞之間存在著雙向連接的對應規律。 示例1: 輸入: pattern “abba”, str “dog…