如何在Vue中建立一個動態二維碼生成器

如何在Vue中建立一個動態二維碼生成器

或多或少,我們都遇到過一個有一些亂七八糟的迷宮式圖案的方塊,一旦我們掃描它們就會重定向或顯示一個新頁面的連結。我們說的是這樣的東西:

qr-code

這有什麼印象嗎?我打賭它是的。上面的圖片是一個靜態QR,我們知道這是因為它的經典黑色程式碼和白色背景。另一方面,動態QR碼是靈活的。它意味著我們可以改變影象的形狀、顏色和資訊,而無需生成新的程式碼。

品牌的身份包括顏色、形狀和標誌。因此,如果使用動態二維碼,靜態二維碼並不能代表一個品牌。

本教程將展示如何使用Vue JavaScript框架建立一個動態二維碼生成器。我們將涵蓋以下內容:

前提條件

本教程解釋了在Vue中建立一個動態二維碼生成器的過程。因此,它要求讀者具備以下條件:

  • 具有基本的JavaScript工作知識
  • 可使用Visual Studio Code或終端和程式碼編輯器
  • 用於安裝軟體包的NodeYarn
  • 一些咖啡

設定Vue專案

下面的章節將包括設定Vue專案,建立QR碼元件,以及定製QR碼。

我們將首先前往我們的終端,使用這個命令建立一個新的目錄:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
mkdir <directory name>
mkdir <directory name>
mkdir <directory name>

然後,我們將用這個命令改變到建立的目錄:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
cd <directory name>
cd <directory name>
cd <directory name>

接下來,我們需要安裝Vue CLI。要做到這一點,我們將使用Node.js的Node包管理器(npm)。到我們的終端,使用下面的命令在全域性新增Vue CLI:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm install -g @vue/cli
npm install -g @vue/cli
npm install -g @vue/cli

在本教程中,我們將使用一個預先建立的模板,並對該模板進行輕微的擴充套件。這些擴充套件將新增使用者輸入、自定義(顏色、比例、遮罩圖案)、標誌(影象),並使用所有元件顯示QR碼。

本教程將提供一個現成的UI模板,並演示如何建立一個動態QR生成器所需的一些特定功能。我們將下載包含程式碼的GitHub倉庫來使用這個模板。一旦完成,我們將在終端使用以下命令安裝QR碼包:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
npm i @chenfengyuan/vue-qrcode
npm i @chenfengyuan/vue-qrcode
npm i @chenfengyuan/vue-qrcode

該命令將在我們的Node模組中新增 @chenfengyuan/vue-qrcode 包。該包將派上用場,因為它將使用我們將在下面的章節中展示的所有元件來顯示一個動態QR碼。下面是我們執行 npm run serve 命令時模板的樣子:

QR程式碼生成器模板

新增使用者輸入

為了新增使用者輸入,我們將前往 ContentOne.vue 檔案,用 v-modelInputData 建立一個 required 輸入元素。v-model 在輸入和一個叫做 InputData 的資料屬性之間建立了一個雙向的繫結。我們還將新增 @input 屬性,即事件監聽器,當輸入值發生變化時呼叫 handleInput 方法。

我們將首先在指令碼部分定義該元件,匯出一個定義元件名稱的預設物件,我們將其設定為ContentOne。我們還將建立一個資料方法,返回一個具有單一屬性InputData的物件,該屬性被設定為一個空字串。

最後,我們將建立 methods 屬性,其中包含在輸入元素中建立的 handleInput 方法。這個 handleInput 方法需要兩個引數,emitEvent 和 value,併發射一個名稱為 emitEvent 的自定義事件,其值為 value

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<template>
<div>
<input type="text" name="" required v-model="InputData" @input="handleInput('input-value', InputData)">
<label>Enter Content</label>
</div>
</template>
<script>
export default {
name: "ContentOne",
data() {
return {
InputData: ''
}
},
methods: {
handleInput(emitEvent, value) {
this.$emit(emitEvent, value)
}
}
}
</script>
<template> <div> <input type="text" name="" required v-model="InputData" @input="handleInput('input-value', InputData)"> <label>Enter Content</label> </div> </template> <script> export default { name: "ContentOne", data() { return { InputData: '' } }, methods: { handleInput(emitEvent, value) { this.$emit(emitEvent, value) } } } </script>
<template>
<div>
<input type="text" name="" required v-model="InputData" @input="handleInput('input-value', InputData)">
<label>Enter Content</label>
</div>
</template>
<script>
export default {
name: "ContentOne",
data() {
return { 
InputData: ''
}
},
methods: {
handleInput(emitEvent, value) {
this.$emit(emitEvent, value)
}
}
}
</script>

因此,我們有一個允許我們輸入文字的元件,每當輸入發生變化時,就會發出一個帶有輸入值的自定義事件。

自定義二維碼

本節將建立一個使用者輸入,改變QR碼的顏色、比例(大小)和圖案。

我們將首先建立一個名為 ContentTwo.vue 的新檔案,並建立四個輸入元素;顏色(淺色和深色)、遮罩圖案和比例。我們還將建立它們與元件資料屬性的關聯v-model繫結,如 hexCodehexCode2MaskPattern, 和 Scale

與 ContentOne.vue 檔案中的程式碼類似,輸入也有事件監聽器,當它們的值發生變化時,會發出自定義事件,如 input-value2input-value3input-value4, 和 input-value5 。

指令碼部分包含一個定義元件的 export default 物件。該元件有一個emits屬性,列出了可以被髮射的自定義事件。它也有資料、方法和 handleInput 方法(用於顏色輸入),與之前的元件類似。 handleMPInput 和 handleScaleInput 方法是這個元件特有的,分別處理 MaskPattern 和 Scale 輸入的發射事件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<template>
<div class="gradient-input">
<div>
<input type="color" v-model="hexCode" @input="handleInput('input-value2', hexCode)">
<input type="text" v-model="hexCode" @input="handleInput('input-value2', hexCode)">
</div>
<div>
<input type="color" v-model="hexCode2" @input="handleInput('input-value3', hexCode2)">
<input type="text" v-model="hexCode2" @input="handleInput('input-value3', hexCode2)">
</div>
<div>
<label>MaskPattern:</label>
<input type="number" v-model.number="MaskPattern" min="0"
@input="handleMPInput('input-value4', MaskPattern)" /><span>px</span>
</div>
<div>
<label>Scale: </label>
<input type="number" v-model.number="Scale" min="0"
@input="handleScaleInput('input-value5', Scale)" /><span>px</span>
</div>
</div>
</template>
<script>
export default {
name: "ContentTwo",
emits: ['input-value2', 'input-value3', 'input-value4', 'input-value5'],
data() {
return {
hexCode: '#000000',
hexCode2: '#ffffff',
MaskPattern: 0,
Scale: 4,
}
},
methods: {
handleInput(emitEvent, value) {
this.$emit(emitEvent, value)
},
handleMPInput(emitEvent, value) {
this.$emit(emitEvent, value)
},
handleScaleInput(emitEvent, value) {
this.$emit(emitEvent, value)
}
}
}
</script>
<template> <div class="gradient-input"> <div> <input type="color" v-model="hexCode" @input="handleInput('input-value2', hexCode)"> <input type="text" v-model="hexCode" @input="handleInput('input-value2', hexCode)"> </div> <div> <input type="color" v-model="hexCode2" @input="handleInput('input-value3', hexCode2)"> <input type="text" v-model="hexCode2" @input="handleInput('input-value3', hexCode2)"> </div> <div> <label>MaskPattern:</label> <input type="number" v-model.number="MaskPattern" min="0" @input="handleMPInput('input-value4', MaskPattern)" /><span>px</span> </div> <div> <label>Scale: </label> <input type="number" v-model.number="Scale" min="0" @input="handleScaleInput('input-value5', Scale)" /><span>px</span> </div> </div> </template> <script> export default { name: "ContentTwo", emits: ['input-value2', 'input-value3', 'input-value4', 'input-value5'], data() { return { hexCode: '#000000', hexCode2: '#ffffff', MaskPattern: 0, Scale: 4, } }, methods: { handleInput(emitEvent, value) { this.$emit(emitEvent, value) }, handleMPInput(emitEvent, value) { this.$emit(emitEvent, value) }, handleScaleInput(emitEvent, value) { this.$emit(emitEvent, value) } } } </script>
<template>
<div class="gradient-input">
<div>
<input type="color" v-model="hexCode" @input="handleInput('input-value2', hexCode)">
<input type="text" v-model="hexCode" @input="handleInput('input-value2', hexCode)">
</div>
<div>
<input type="color" v-model="hexCode2" @input="handleInput('input-value3', hexCode2)">
<input type="text" v-model="hexCode2" @input="handleInput('input-value3', hexCode2)">
</div>
<div>
<label>MaskPattern:</label>
<input type="number" v-model.number="MaskPattern" min="0"
@input="handleMPInput('input-value4', MaskPattern)" /><span>px</span>
</div>
<div>
<label>Scale: </label>
<input type="number" v-model.number="Scale" min="0"
@input="handleScaleInput('input-value5', Scale)" /><span>px</span>
</div>
</div>
</template>
<script>
export default {
name: "ContentTwo",
emits: ['input-value2', 'input-value3', 'input-value4', 'input-value5'],
data() {
return {
hexCode: '#000000',
hexCode2: '#ffffff',
MaskPattern: 0,
Scale: 4,
}
},
methods: {
handleInput(emitEvent, value) {
this.$emit(emitEvent, value)
},
handleMPInput(emitEvent, value) {
this.$emit(emitEvent, value)
},
handleScaleInput(emitEvent, value) {
this.$emit(emitEvent, value)
}
}
}
</script>

新增logo元件

現在,我們將探討如何建立一個實現檔案上傳器和影象選擇功能的元件。我們允許使用者拖放或通過檔案選擇器選擇一個檔案。我們驗證檔案以確保它是一個具有以下副檔名的影象:.jpeg, .jpg, 和 .png。如果檔案是有效的,我們就讀取它並將其資料作為資料URL儲存在一個列表中。如果檔案是無效的,我們會顯示一個錯誤資訊,並在兩秒鐘後重置。

因此,我們將建立另一個名為ContentThree.vue的檔案。在該檔案中,我們將建立一個類為drag-area的div元素,作為拖放區域,並建立一個按鈕元素,在點選時觸發檔案選擇器。我們將在div和按鈕中新增一個ref屬性,以便在我們的JavaScript程式碼中訪問其DOM元素。我們還將建立一個帶有ref輸入的隱藏檔案輸入元素。

我們還將使用v-for屬性建立一個影象元素,以迴圈瀏覽儲存資料URL的列表。我們將建立一個@click屬性,連結到影象元素中的selectImage方法。最後,我們將建立一個class屬性,檢查資料屬性selectedIndex是否等於index:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<template>
<div class="drag-area" ref="dropArea">
<div class="icon"><i class="fas fa-cloud-upload-alt"></i></div>
<header ref="dragText">Drag & Drop to Upload File</header>
<span>OR</span>
<button @click="openFilePicker">Browse File</button>
<input type="file" hidden ref="input" multiple />
</div>
<div class="images-container">
<img v-for="(imgSrc, index) in imgSrcList" :src="imgSrc" width="120" height="120" :key="index"
@click="selectImage(imgSrc, index)" :class="{ thumbnail: selectedIndex === index }" />
</div>
</template>
<template> <div class="drag-area" ref="dropArea"> <div class="icon"><i class="fas fa-cloud-upload-alt"></i></div> <header ref="dragText">Drag & Drop to Upload File</header> <span>OR</span> <button @click="openFilePicker">Browse File</button> <input type="file" hidden ref="input" multiple /> </div> <div class="images-container"> <img v-for="(imgSrc, index) in imgSrcList" :src="imgSrc" width="120" height="120" :key="index" @click="selectImage(imgSrc, index)" :class="{ thumbnail: selectedIndex === index }" /> </div> </template>
<template>
<div class="drag-area" ref="dropArea">
<div class="icon"><i class="fas fa-cloud-upload-alt"></i></div>
<header ref="dragText">Drag & Drop to Upload File</header>
<span>OR</span>
<button @click="openFilePicker">Browse File</button>
<input type="file" hidden ref="input" multiple />
</div>
<div class="images-container">
<img v-for="(imgSrc, index) in imgSrcList" :src="imgSrc" width="120" height="120" :key="index"
@click="selectImage(imgSrc, index)" :class="{ thumbnail: selectedIndex === index }" />
</div>
</template>

在指令碼標籤中,我們將建立匯出預設物件並定義一個資料屬性,該屬性將返回儲存檔案資料URL的列表和一個值為-1的selectedIndex鍵。 接下來,我們將建立計算屬性selectedImage,該屬性返回當前選擇的影象。然後我們將在匯出預設物件的方法屬性中建立selectImage方法。

selectImage方法更新selectedIndex,併發出一個帶有選定影象的事件。我們還將建立另一個方法openFilePicker,它將觸發隱藏的檔案輸入,開啟檔案選取器:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<script>
export default {
data() {
return {
imgSrcList: [],
selectedIndex: -1
}
},
computed: {
selectedImage() {
return this.imgSrcList[this.selectedIndex];
}
},
methods: {
selectImage(selectedImage, index) {
this.selectedIndex = index;
this.$emit('Selected', selectedImage);
console.log(this.imgSrcList)
},
openFilePicker() {
this.$refs.input.click()
},
}
}
<script> export default { data() { return { imgSrcList: [], selectedIndex: -1 } }, computed: { selectedImage() { return this.imgSrcList[this.selectedIndex]; } }, methods: { selectImage(selectedImage, index) { this.selectedIndex = index; this.$emit('Selected', selectedImage); console.log(this.imgSrcList) }, openFilePicker() { this.$refs.input.click() }, } }
<script>
export default {
data() {
return {
imgSrcList: [],
selectedIndex: -1
}
},
computed: {
selectedImage() {
return this.imgSrcList[this.selectedIndex];
}
},
methods: {
selectImage(selectedImage, index) {
this.selectedIndex = index;
this.$emit('Selected', selectedImage);
console.log(this.imgSrcList)
},
openFilePicker() {
this.$refs.input.click()
},
}
}

然後,我們將建立一些事件處理程式,如:

  • handleFileChange:處理檔案輸入的 change 事件。
  • handleDragOver:處理拖放區的 dragover 事件。
  • handleDragLeave:處理拖放區的 dragleave 事件
  • handleDrop:處理拖放區的拖放事件

最後,我們建立一個已安裝的生命週期鉤子,併為拖放區、檔案輸入和其相應事件的控制代碼新增事件監聽器:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<script>
export default {
// data property
// computed property
methods: {
// do something
handleFileChange(event) {
let file = event.target.files[0]
let validExtensions = ["image/jpeg", "image/jpg", "image/png"
];
let fileType = file.type
if (validExtensions.includes(fileType)) {
let fileReader = new FileReader();
fileReader.onload = (e) => {
this.imgSrcList.push(e.target.result)
console.log(fileReader.result);
this.$refs.dropArea.classList.remove("active");
this.$refs.dragText.textContent = "The file is successfully uploaded."
setTimeout(() => {
this.$refs.dragText.textContent = "Drag & Drop to Upload File"
}, 2000)
}
fileReader.readAsDataURL(file);
this.openFilePicker();
} else {
this.$refs.dropArea.classList.remove("active");
this.$refs.dragText.textContent = "This is not an valid file!"
setTimeout(() => {
this.$refs.dragText.textContent = "Drag & Drop to Upload File"
}, 2000)
}
},
handleDragOver(event) {
event.preventDefault();
this.$refs.dropArea.classList.add("active");
this.$refs.dragText.textContent = "Release to Upload File";
},
handleDragLeave() {
this.$refs.dropArea.classList.remove("active");
this.$refs.dragText.textContent = "Drag & Drop to Upload File";
},
handleDrop(event) {
event.preventDefault();
let file = event.dataTransfer.files[0];
this.handleFileChange({ target: { files: [file] } });
},
},
mounted() {
this.$nextTick(() => {
this.$refs.dropArea.addEventListener("dragover", this.handleDragOver);
this.$refs.dropArea.addEventListener("dragleave", this.handleDragLeave);
this.$refs.dropArea.addEventListener("drop", this.handleDrop);
this.$refs.input.addEventListener("change", this.handleFileChange);
});
}
}
</script>
<script> export default { // data property // computed property methods: { // do something handleFileChange(event) { let file = event.target.files[0] let validExtensions = ["image/jpeg", "image/jpg", "image/png" ]; let fileType = file.type if (validExtensions.includes(fileType)) { let fileReader = new FileReader(); fileReader.onload = (e) => { this.imgSrcList.push(e.target.result) console.log(fileReader.result); this.$refs.dropArea.classList.remove("active"); this.$refs.dragText.textContent = "The file is successfully uploaded." setTimeout(() => { this.$refs.dragText.textContent = "Drag & Drop to Upload File" }, 2000) } fileReader.readAsDataURL(file); this.openFilePicker(); } else { this.$refs.dropArea.classList.remove("active"); this.$refs.dragText.textContent = "This is not an valid file!" setTimeout(() => { this.$refs.dragText.textContent = "Drag & Drop to Upload File" }, 2000) } }, handleDragOver(event) { event.preventDefault(); this.$refs.dropArea.classList.add("active"); this.$refs.dragText.textContent = "Release to Upload File"; }, handleDragLeave() { this.$refs.dropArea.classList.remove("active"); this.$refs.dragText.textContent = "Drag & Drop to Upload File"; }, handleDrop(event) { event.preventDefault(); let file = event.dataTransfer.files[0]; this.handleFileChange({ target: { files: [file] } }); }, }, mounted() { this.$nextTick(() => { this.$refs.dropArea.addEventListener("dragover", this.handleDragOver); this.$refs.dropArea.addEventListener("dragleave", this.handleDragLeave); this.$refs.dropArea.addEventListener("drop", this.handleDrop); this.$refs.input.addEventListener("change", this.handleFileChange); }); } } </script>
<script>
export default {
// data property
// computed property
methods: {
// do something
handleFileChange(event) {
let file = event.target.files[0]
let validExtensions = ["image/jpeg", "image/jpg", "image/png"
];
let fileType = file.type
if (validExtensions.includes(fileType)) {
let fileReader = new FileReader();
fileReader.onload = (e) => {
this.imgSrcList.push(e.target.result)
console.log(fileReader.result);
this.$refs.dropArea.classList.remove("active");
this.$refs.dragText.textContent = "The file is successfully uploaded."
setTimeout(() => {
this.$refs.dragText.textContent = "Drag & Drop to Upload File"
}, 2000)
}
fileReader.readAsDataURL(file);
this.openFilePicker();
} else {
this.$refs.dropArea.classList.remove("active");
this.$refs.dragText.textContent = "This is not an valid file!"
setTimeout(() => {
this.$refs.dragText.textContent = "Drag & Drop to Upload File"
}, 2000)
}
},
handleDragOver(event) {
event.preventDefault();
this.$refs.dropArea.classList.add("active");
this.$refs.dragText.textContent = "Release to Upload File";
},
handleDragLeave() {
this.$refs.dropArea.classList.remove("active");
this.$refs.dragText.textContent = "Drag & Drop to Upload File";
},
handleDrop(event) {
event.preventDefault();
let file = event.dataTransfer.files[0];
this.handleFileChange({ target: { files: [file] } });
},
},
mounted() {
this.$nextTick(() => {
this.$refs.dropArea.addEventListener("dragover", this.handleDragOver);
this.$refs.dropArea.addEventListener("dragleave", this.handleDragLeave);
this.$refs.dropArea.addEventListener("drop", this.handleDrop);
this.$refs.input.addEventListener("change", this.handleFileChange);
});
}
}
</script>

將資料傳遞給父級元件

在我們可以使用QR碼元件之前,我們需要能夠從我們先前建立的三個獨立的元件中訪問資料。它們都在發射事件;因此,我們將不得不在父元件中訪問它們,並將它們從父元件傳送到QR碼顯示元件。

因此,讓我們回到ParentComponent.vue檔案,將ContentOne、ContentTwo、ContentThree和DisplayArea元件新增到模板的第一、第二和第三div元素。

我們還將給ContentOne和ContentTwo元件附加一個v-on屬性。v-on屬性是一個Vue.js指令,用於監聽事件;在本例中,是到目前為止發出的所有事件。對於ContentThree元件發出的事件,我們將使用@selected屬性代替,因為它只發出一個選定的事件。然後,我們將把資料屬性物件傳遞給DisplayArea元件:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<template>
<div>
<ul>
<li v-for="item in items" @click="showContent(item)" :key="item.id" :class="{ active: item === selectedItem }">{{
item.title
}}</li>
</ul>
<div class="content" v-show="selectedItem === items[0]">
<ContentOne v-on:input-value="updateValue" />
</div>
<div class="content" v-show="selectedItem === items[1]">
<ContentTwo v-on:input-value2="updateValue2" v-on:input-value3="updateValue3" v-on:input-value4="updateValue4"
v-on:input-value5="updateValue5" />
</div>
<div class="content" v-show="selectedItem === items[2]">
<ContentThree @selected="setSelectedImage" />
</div>
<div class="content" v-show="selectedItem === items[3]">
<DisplayArea :InputData="InputData" :InputData2="InputData2" :InputData3="InputData3" :hexCode="hexCode"
:hexCode2="hexCode2" :selectedImage="selectedImage" />
</div>
</div>
</template>
<template> <div> <ul> <li v-for="item in items" @click="showContent(item)" :key="item.id" :class="{ active: item === selectedItem }">{{ item.title }}</li> </ul> <div class="content" v-show="selectedItem === items[0]"> <ContentOne v-on:input-value="updateValue" /> </div> <div class="content" v-show="selectedItem === items[1]"> <ContentTwo v-on:input-value2="updateValue2" v-on:input-value3="updateValue3" v-on:input-value4="updateValue4" v-on:input-value5="updateValue5" /> </div> <div class="content" v-show="selectedItem === items[2]"> <ContentThree @selected="setSelectedImage" /> </div> <div class="content" v-show="selectedItem === items[3]"> <DisplayArea :InputData="InputData" :InputData2="InputData2" :InputData3="InputData3" :hexCode="hexCode" :hexCode2="hexCode2" :selectedImage="selectedImage" /> </div> </div> </template>
<template>
<div>
<ul>
<li v-for="item in items" @click="showContent(item)" :key="item.id" :class="{ active: item === selectedItem }">{{
item.title
}}</li>
</ul>
<div class="content" v-show="selectedItem === items[0]">
<ContentOne v-on:input-value="updateValue" />
</div>
<div class="content" v-show="selectedItem === items[1]">
<ContentTwo v-on:input-value2="updateValue2" v-on:input-value3="updateValue3" v-on:input-value4="updateValue4"
v-on:input-value5="updateValue5" />
</div>
<div class="content" v-show="selectedItem === items[2]">
<ContentThree @selected="setSelectedImage" />
</div>
<div class="content" v-show="selectedItem === items[3]">
<DisplayArea :InputData="InputData" :InputData2="InputData2" :InputData3="InputData3" :hexCode="hexCode"
:hexCode2="hexCode2" :selectedImage="selectedImage" />
</div>
</div>
</template>

在指令碼元素中,我們將建立出口預設物件並傳遞以下資料屬性: InputData: ''hexCode: ''hexCode2: ''InputData2: ''InputData3: '' 和 selectedImage: ''。然後我們將呼叫附加在v-on和@selected屬性上的方法來更新相應的資料屬性:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<script>
import ContentOne from './Content/ContentOne.vue';
import ContentTwo from './Content/ContentTwo.vue';
import ContentThree from './Content/ContentThree.vue';
import DisplayArea from './Content/DisplayArea.vue';
export default {
name: 'HelloWorld',
components: {
ContentOne,
ContentTwo,
ContentThree,
DisplayArea
},
data() {
return {
InputData: '',
hexCode: '',
hexCode2: '',
InputData2: '',
InputData3: '',
selectedImage: '',
items: [
{ title: 'ENTER CONTENT' },
{ title: 'CUSTOMIZE' },
{ title: 'ADD LOGO' },
{ title: 'DISPLAY' },
],
selectedItem: null
}
},
methods: {
updateValue(value) {
this.InputData = value
},
updateValue2(value) {
this.hexCode = value
},
updateValue3(value) {
this.hexCode2 = value
},
updateValue4(value) {
this.InputData2 = value
},
updateValue5(value) {
this.InputData3 = value
},
setSelectedImage(selectedImage) {
this.selectedImage = selectedImage;
},
showContent(item) {
this.selectedItem = item
},
},
emits: ['Selected']
}
</script>
<script> import ContentOne from './Content/ContentOne.vue'; import ContentTwo from './Content/ContentTwo.vue'; import ContentThree from './Content/ContentThree.vue'; import DisplayArea from './Content/DisplayArea.vue'; export default { name: 'HelloWorld', components: { ContentOne, ContentTwo, ContentThree, DisplayArea }, data() { return { InputData: '', hexCode: '', hexCode2: '', InputData2: '', InputData3: '', selectedImage: '', items: [ { title: 'ENTER CONTENT' }, { title: 'CUSTOMIZE' }, { title: 'ADD LOGO' }, { title: 'DISPLAY' }, ], selectedItem: null } }, methods: { updateValue(value) { this.InputData = value }, updateValue2(value) { this.hexCode = value }, updateValue3(value) { this.hexCode2 = value }, updateValue4(value) { this.InputData2 = value }, updateValue5(value) { this.InputData3 = value }, setSelectedImage(selectedImage) { this.selectedImage = selectedImage; }, showContent(item) { this.selectedItem = item }, }, emits: ['Selected'] } </script>
<script>
import ContentOne from './Content/ContentOne.vue';
import ContentTwo from './Content/ContentTwo.vue';
import ContentThree from './Content/ContentThree.vue';
import DisplayArea from './Content/DisplayArea.vue';
export default {
name: 'HelloWorld',
components: {
ContentOne,
ContentTwo,
ContentThree,
DisplayArea
},
data() {
return {
InputData: '',
hexCode: '',
hexCode2: '',
InputData2: '',
InputData3: '',
selectedImage: '',
items: [
{ title: 'ENTER CONTENT' },
{ title: 'CUSTOMIZE' },
{ title: 'ADD LOGO' },
{ title: 'DISPLAY' },
],
selectedItem: null
}
},
methods: {
updateValue(value) {
this.InputData = value
},
updateValue2(value) {
this.hexCode = value
},
updateValue3(value) {
this.hexCode2 = value
},
updateValue4(value) {
this.InputData2 = value
},
updateValue5(value) {
this.InputData3 = value
},
setSelectedImage(selectedImage) {
this.selectedImage = selectedImage;
},
showContent(item) {
this.selectedItem = item
},
},
emits: ['Selected']
}
</script>

基本上,上面的程式碼將資料從三個子元件傳遞到父元件。然後,這些資料又從父元件移到另一個子元件,即 DisplayArea 元件。

建立二維碼顯示

現在,我們將建立另一個名為 DisplayArea.vue 的檔案(DisplayArea元件),並使用@陳方圓/vue-qrcode庫,我們將呼叫vue-qrcode元素並將ref、value和option屬性分別設定為qrcode、hello和options。我們還將從父元件中呼叫所有的props,將它們作為按鈕元素的引數。

按鈕元素包含一個方法,將當前的資料屬性與從每個元件傳遞過來的事件等同起來。這裡是下面的程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<template>
<vue-qrcode ref="qrcode" :value="hello" :options="options"></vue-qrcode>
<div class="container"> <button
v-on:click="getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, this.$refs.qrcode.$el)"><span>Generate
code</span></button>
</div>
</template>
<script>
import VueQrcode from '@chenfengyuan/vue-qrcode'
export default {
components: { VueQrcode },
props: ['InputData', 'hexCode', 'hexCode2', 'InputData2', 'InputData3', 'selectedImage'],
data() {
return {
hello: "hello",
options: {
maskPattern: 7,
scale: 4,
color: {
dark: '#000000',
light: '#ffffff',
},
margin: 0
}
}
},
methods: {
getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, canvas) {
try {
if (!InputData) throw new Error("InputData is not defined")
const context = canvas.getContext('2d');
const image = new Image();
image.src = selectedImage;
image.crossorigin = 'anonymous';
image.onload = () => {
const coverage = 0.15;
const width = Math.round(canvas.width * coverage);
const x = (canvas.width - width) / 2;
console.log(canvas.width)
this.drawImage(context, image, x, x, width, width);
};
this.hello = InputData
this.options.maskPattern = InputData2
this.options.scale = InputData3
this.options.color.dark = hexCode
this.options.color.light = hexCode2
} catch (error) {
console.log(error)
}
},
drawImage(context, image, x, y, width, height, radius = 4) {
context.shadowOffsetX = 0;
context.shadowOffsetY = 2;
context.shadowBlur = 4;
context.shadowColor = '#00000040';
context.lineWidth = 8;
context.beginPath();
context.moveTo(x + radius, y);
context.arcTo(x + width, y, x + width, y + height, radius);
context.arcTo(x + width, y + height, x, y + height, radius);
context.arcTo(x, y + height, x, y, radius);
context.arcTo(x, y, x + width, y, radius);
context.closePath();
context.strokeStyle = '#fff';
context.stroke();
context.clip();
context.fillStyle = '#fff';
context.fillRect(x, x, width, height);
context.drawImage(image, x, x, width, height);
},
}
}
</script>
<template> <vue-qrcode ref="qrcode" :value="hello" :options="options"></vue-qrcode> <div class="container"> <button v-on:click="getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, this.$refs.qrcode.$el)"><span>Generate code</span></button> </div> </template> <script> import VueQrcode from '@chenfengyuan/vue-qrcode' export default { components: { VueQrcode }, props: ['InputData', 'hexCode', 'hexCode2', 'InputData2', 'InputData3', 'selectedImage'], data() { return { hello: "hello", options: { maskPattern: 7, scale: 4, color: { dark: '#000000', light: '#ffffff', }, margin: 0 } } }, methods: { getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, canvas) { try { if (!InputData) throw new Error("InputData is not defined") const context = canvas.getContext('2d'); const image = new Image(); image.src = selectedImage; image.crossorigin = 'anonymous'; image.onload = () => { const coverage = 0.15; const width = Math.round(canvas.width * coverage); const x = (canvas.width - width) / 2; console.log(canvas.width) this.drawImage(context, image, x, x, width, width); }; this.hello = InputData this.options.maskPattern = InputData2 this.options.scale = InputData3 this.options.color.dark = hexCode this.options.color.light = hexCode2 } catch (error) { console.log(error) } }, drawImage(context, image, x, y, width, height, radius = 4) { context.shadowOffsetX = 0; context.shadowOffsetY = 2; context.shadowBlur = 4; context.shadowColor = '#00000040'; context.lineWidth = 8; context.beginPath(); context.moveTo(x + radius, y); context.arcTo(x + width, y, x + width, y + height, radius); context.arcTo(x + width, y + height, x, y + height, radius); context.arcTo(x, y + height, x, y, radius); context.arcTo(x, y, x + width, y, radius); context.closePath(); context.strokeStyle = '#fff'; context.stroke(); context.clip(); context.fillStyle = '#fff'; context.fillRect(x, x, width, height); context.drawImage(image, x, x, width, height); }, } } </script>
<template>
<vue-qrcode ref="qrcode" :value="hello" :options="options"></vue-qrcode>
<div class="container"> <button
v-on:click="getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, this.$refs.qrcode.$el)"><span>Generate
code</span></button>
</div>
</template>
<script>
import VueQrcode from '@chenfengyuan/vue-qrcode'
export default {
components: { VueQrcode },
props: ['InputData', 'hexCode', 'hexCode2', 'InputData2', 'InputData3', 'selectedImage'],
data() {
return {
hello: "hello",
options: {
maskPattern: 7,
scale: 4,
color: {
dark: '#000000',
light: '#ffffff',
},
margin: 0
}
}
},
methods: {
getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, canvas) {
try {
if (!InputData) throw new Error("InputData is not defined")
const context = canvas.getContext('2d');
const image = new Image();
image.src = selectedImage;
image.crossorigin = 'anonymous';
image.onload = () => {
const coverage = 0.15;
const width = Math.round(canvas.width * coverage);
const x = (canvas.width - width) / 2;
console.log(canvas.width)
this.drawImage(context, image, x, x, width, width);
};
this.hello = InputData
this.options.maskPattern = InputData2
this.options.scale = InputData3
this.options.color.dark = hexCode
this.options.color.light = hexCode2
} catch (error) {
console.log(error)
}
},
drawImage(context, image, x, y, width, height, radius = 4) {
context.shadowOffsetX = 0;
context.shadowOffsetY = 2;
context.shadowBlur = 4;
context.shadowColor = '#00000040';
context.lineWidth = 8;
context.beginPath();
context.moveTo(x + radius, y);
context.arcTo(x + width, y, x + width, y + height, radius);
context.arcTo(x + width, y + height, x, y + height, radius);
context.arcTo(x, y + height, x, y, radius);
context.arcTo(x, y, x + width, y, radius);
context.closePath();
context.strokeStyle = '#fff';
context.stroke();
context.clip();
context.fillStyle = '#fff';
context.fillRect(x, x, width, height);
context.drawImage(image, x, x, width, height);
},
}
}
</script>

最終確定專案

現在我們已經完成了,讓我們執行程式碼,看看結果:

QR程式碼生成器的最終結果

額外功能

早些時候,我們把其中一個輸入設定為必填。這意味著每次它的欄位為空時我們都會得到一個錯誤。為了解決這個問題,讓我們建立一個帶有 ref 屬性的 paragraph 元素,並設定一個條件,如果錯誤是 Input data is not defined,它應該顯示一個通知,而不是破壞程式碼:

Plain text
Copy to clipboard
Open code in new window
EnlighterJS 3 Syntax Highlighter
<template>
// Qr code component
<p ref="DisplayError"></p>
// button contianer
</template>
<script>
import VueQrcode from '@chenfengyuan/vue-qrcode'
export default {
methods: {
getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, canvas) {
try {
// do something
// onReady()
} catch (error) {
if (error.message === 'InputData is not defined') {
this.$refs.DisplayError.textContent = "Input is empty"
setTimeout(() => {
this.$refs.DisplayError.textContent = ""
}, 2000)
console.log("error: no input text")
} else {
console.log(error)
this.error = error.message
}
}
},
}
}
</script>
<template> // Qr code component <p ref="DisplayError"></p> // button contianer </template> <script> import VueQrcode from '@chenfengyuan/vue-qrcode' export default { methods: { getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, canvas) { try { // do something // onReady() } catch (error) { if (error.message === 'InputData is not defined') { this.$refs.DisplayError.textContent = "Input is empty" setTimeout(() => { this.$refs.DisplayError.textContent = "" }, 2000) console.log("error: no input text") } else { console.log(error) this.error = error.message } } }, } } </script>
<template>
// Qr code component
<p ref="DisplayError"></p>
// button contianer
</template>
<script>
import VueQrcode from '@chenfengyuan/vue-qrcode'
export default {
methods: {
getinput(InputData, hexCode, hexCode2, InputData2, InputData3, selectedImage, canvas) {
try {
// do something
// onReady()
} catch (error) {
if (error.message === 'InputData is not defined') {
this.$refs.DisplayError.textContent = "Input is empty"
setTimeout(() => {
this.$refs.DisplayError.textContent = ""
}, 2000)
console.log("error: no input text")
} else {
console.log(error)
this.error = error.message
}
}
},
}
}
</script>

小結

本文展示瞭如何將輸入和影象繫結到一個QR碼。一個動態的QR碼生成器有各種潛在的用途,如營銷和活動管理。生成器的未來發展可以包括增加更多的定製選項,與資料庫整合,並改善使用者體驗。

評論留言