my lesson note
老師範例的檔案路徑
\\10.0.1.2\share
帳:user
密:111
瀏覽器開發者工具先點擊Vue頁籤>Component>點擊console頁籤即可在主控台下指令$vm.data.msg(屬性)取得vm的資料
Options API在網頁中引用"vue.global.js"和"vue.esm-browser.js"這兩個有什麼差異?
https://grok.com/share/bGVnYWN5_98b56147-028c-4874-95f6-405af0215981
Options API與Composition API兩者有何差異?我該使用哪種?
https://grok.com/share/bGVnYWN5_1f16d4c4-f748-4d08-9102-b1f705f6c681
從jQuery事件中呼叫Vue的方法&取得Vue的資料屬性
https://grok.com/share/bGVnYWN5_6f0a37a9-8f17-4bce-b5a7-ad1f41cc703d
計算屬性的簡單範例
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="msgUpper" />
<p>{{ msg }}</p>
<p>{{ msgUpper }}</p>
</div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {
msg: "Hello World ! ",
};
},
computed: {
msgUpper: {
get () {
return this.msg.toUpperCase()
},
set (newvalue) {
this.msg = newvalue.toLowerCase()
}
},
},
}).mount("#app");
</script>
</body>
</html>
偵聽器(Watcher) 監看資料屬性是否變動,簡單範例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="msg"/> <br/>
<p v-text="msg"></p>
</div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
const vue_vm = createApp({
data() {
return {
msg: "",
};
},
watch: {
msg: function (msg) {
console.log("監看msg值:"+msg);
},
},
methods: {
},
}).mount("#app");
</script>
</body>
</html>
在HTML DOM使用$event傳遞觸發Vue JS事件的DOM物件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app">
<a href="https://vuejs.org/" @click="showMsg" target="_blank"> Go To Vue.js </a>
<br/>
<a href="https://vuejs.org/" @click="showMsg($event)" target="_blank"> Go To Vue.js </a>
</div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
createApp({
data() {
return {};
},
methods: {
showMsg: function (event) {
alert("No redirect !");
event.preventDefault();
console.log(event.target);
},
},
}).mount("#app");
</script>
</body>
</html>
Vue3 與 Bootstrap-select 整合示例
https://grok.com/share/bGVnYWN5_81cf68da-5e16-4c4c-9178-f6e386cdb747
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>Vue 3 with Bootstrap-select Example</title>
<!-- Bootstrap CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- Bootstrap-select CSS -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap-select@1.14.0-beta3/dist/css/bootstrap-select.min.css" rel="stylesheet">
</head>
<body>
<div id="app" class="container mt-5">
<h2>選擇項目</h2>
<!-- 搜尋框:data-live-search="true" -->
<select class="selectpicker"
v-model="selectedItemValue"
data-live-search="false"
title="請選擇一個項目"
@change="handleSelection">
<option v-for="item in items"
:key="item.id"
:value="item.id" v-text="item.name">
</option>
</select>
<div class="mt-3" v-if="selectedItemValue">
getSelectedItemName: {{ getSelectedItemName }} <br/>
selectedItemValue: {{selectedItemValue}}
</div>
</div>
<!-- jQuery (bootstrap-select 依賴) -->
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<!-- Vue 3 -->
<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>
<!-- Bootstrap JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/js/bootstrap.bundle.min.js"></script>
<!-- Bootstrap-select JS -->
<script src="https://cdn.jsdelivr.net/npm/bootstrap-select@1.14.0-beta3/dist/js/bootstrap-select.min.js"></script>
<script>
const { createApp } = Vue;
createApp({
data() {
return {
items: [],
selectedItemValue: null
}
},
computed: {
getSelectedItemName() {
const item = this.items.find(item => item.id === this.selectedItemValue);
return item ? item.name : '';
}
},
methods: {
fetchItems() {
// 使用 Promise 替代 async/await
fetch('https://jsonplaceholder.typicode.com/users')
.then(response => response.json())
.then(data => {
// 轉換資料格式
this.items = data.map(user => ({//集合轉型
id: user.id,
name: user.name
}));
// 更新 bootstrap-select
this.$nextTick(() => {
$('.selectpicker').selectpicker('refresh');
});
})
.catch(error => {
console.error('獲取資料失敗:', error);
});
},
handleSelection() {
console.log('選擇的項目ID:', this.selectedItemValue);
}
},
mounted() {
// Vue 掛載後 Ajax 獲取資料
this.fetchItems();
},
updated() {
console.log("Vue updated");
// 當 DOM 更新後重新刷新 selectpicker
//$('.selectpicker').selectpicker('refresh');
}
}).mount('#app');
</script>
</body>
</html>
子元件的props從父元件接收資料,基本用法
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app">
<!-- 預設沒v-bind給字串值 -->
<welcome-component message="Hello"></welcome-component>
<!-- 給JS值 -->
<welcome-component :message="'bind Hi'" :age="1+2"></welcome-component>
</div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
let welcome = {
/*VS Code的es6-string-html 擴充套件幫忙高亮html字串*/
template: /*html*/`<h1> {{ message }} : {{ age }}</h1>`,
props: ["message","age"]
};
var app = createApp({
components: {
"welcome-component" : welcome
},
});
app.mount("#app");
</script>
</body>
</html>
父元件透過子元件的props傳遞資料,子元件透過$emit傳遞事件給父元件
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="name">
<welcome-component v-bind:user-name="name" v-on:sayhello="onsayhello" v-on:inputchange="childinputchange" >
</welcome-component>
</div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
let welcome = {
/*子元件的input v-model不可直接修改唯讀的props userName*/
template: /*html*/`<div>子元件:
<label> {{labelText}} </label>
<input type="text" v-model="inputText" />
<button v-on:click="$emit('sayhello', inputText)">
sayhello
</button>
</div>`,
props: ["userName"],
data: function () {
return {
labelText: " Hello ",
inputText: this.userName,/*預設值,只執行一次,讀取父元件傳來的userName*/
};
},
watch: {
userName : function(newValue,oldValue) {
console.log(`userName newValue:${newValue},userName oldValue:${oldValue}`);
this.inputText = newValue;
},
inputText: function(newValue,oldValue){
console.log(`inputText newValue:${newValue},inputText oldValue:${oldValue}`);
this.$emit('inputchange',newValue);
}
},
};
var app = createApp({
data() {
return {
name: "mary",
};
},
components: {
"welcome-component": welcome,
},
methods: {
onsayhello: function ( msg ) {
alert(msg );
},
childinputchange:function(childInputText)
{
this.name = childInputText;
}
},
});
app.mount("#app");
</script>
</body>
</html>
父元件透過物件
傳遞參考給子元件,在子元件中編輯 傳遞過來的物件屬性會有嚮應式連動效果,子元件不必像上述一樣使用watch
來監聽
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Document</title>
</head>
<body>
<div id="app">
<input type="text" v-model="user.name">
<welcome-component v-bind:user="user" v-on:sayhello="onsayhello" >
</welcome-component>
</div>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js"
}
}
</script>
<script type="module">
import { createApp } from 'vue'
let welcome = {
/*子元件的input v-model不可直接修改唯讀的props參考*/
template: /*html*/`<div>子元件:
<input type="text" v-model="user.name" />
<button v-on:click="$emit('sayhello', user)">
sayhello
</button>
</div>`,
props: {
user : Object
},
data: function () {
return {
};
},
watch: {
},
};
var app = createApp({
data() {
return {
user:{ name:"myName" }
};
},
components: {
"welcome-component": welcome,
},
methods: {
onsayhello: function (user) {
alert(`this.user.name:${this.user.name},user.name:${user.name}`);
}
},
});
app.mount("#app");
</script>
</body>
</html>
父組件和子組件的輸入框連動嚮應式,組合式API(Composition API)的寫法
<!-- ChildComponent.vue -->
<template>
<div>
<h2>子組件</h2>
<input v-model="childValue" v-on:input="childTextInput" placeholder="在子組件中輸入" />
</div>
</template>
<script>
import { ref,watch} from "vue";
export default {
props: {
modelValue: String
},
setup(props,context) {
let childValue = ref(props.modelValue);
const childTextInput=()=>
{
//呼叫emit函式,把childValue往外傳出去
context.emit('update-model-value', childValue.value);
};
//當父組件的 modelValue 變化時,子組件的 childValue 會同步更新。
watch(() => props.modelValue,(newVal)=>{
childValue.value=newVal;
});
// 回傳要暴露給模板的變數和函數
return {
childValue ,childTextInput
};
},
};
</script>
<!-- ParentComponent.vue -->
<template>
<div>
<h1>父組件</h1>
<input v-model="parentValue" placeholder="在父組件中輸入" />
</div>
<div>
<h1>子組件</h1>
<child-component :model-value="parentValue" v-on:update-model-value="updateParentValue" ></child-component>
</div>
</template>
<script setup>
import { ref } from 'vue';
import ChildComponent from './ChildComponent.vue';
let parentValue = ref("parentValue");
const updateParentValue = (childValue)=>{
parentValue.value = childValue;
};
</script>
Bootstrap 5 Alert 整合 Vue 3 (使用子元件)
https://grok.com/share/bGVnYWN5_b256d2bf-6d2e-474d-8000-5cdd5d82fe1e
ASP.NET MVC 整合 Vite建立的Vue專案
https://grok.com/share/bGVnYWN5_4e62978a-cbdc-47fe-8c93-621f328a022d
Vue3 Composition API 介紹
https://grok.com/share/bGVnYWN5_90603467-94cf-44a1-88a0-7c7e4071c1d1
<scrip setup>改成setup()的寫法:setup()函式多了 export default 且須回傳資料給setup()函式,可以在ASP.net MVC的視圖中使用setup()函式寫法,<script setup>標籤則是Vue專案專用
Vue3 組合式Composition API: setup vs <script setup>用法差異
https://grok.com/share/bGVnYWN5_f3d70e9c-7bc3-4148-b784-233ad7ab0a40
使用ref創建基本型別、null、undefined的嚮應式對象;陣列、物件用reactive創建嚮應式對象
<template>
<h1> Home </h1>
<div>
<p> Employee Name :{{ empName }} </p>
<p> Age : {{ age }} </p>
<p> Is Married : {{ isMarried }} </p>
<p> Array Value: {{ arry[0] }} </p> <!-- 顯示陣列的第一個值 -->
</div>
<div>
<button @click="buttonClick" >Click me</button>
</div>
</template>
<script>
import { ref, reactive } from "vue";
export default {
setup() {
let empName = "shadow";
let age = ref(39);//基本型別
let isMarried = false;
let arry = reactive([0,1]);//陣列、物件用reactive創建嚮應式對象
const buttonClick = () => {
arry[0]++;//這裡累加1效果
age.value++;
};
// 回傳要暴露給模板的變數和函數
return {
empName,
age,
isMarried,
arry,
buttonClick
};
}
};
</script>
Vue3: watch vs watchEffect
https://grok.com/share/bGVnYWN5_88ab721c-18f8-455d-ba9d-da1490843034
Vue3 defineProps函式,定義物件傳遞範例
https://grok.com/share/bGVnYWN5_511e97e3-cfe7-4405-ae2a-95d308943880
在 ASP.NET MVC 中使用 Vue 3 Router、<script type="importmap">引用vue.js、兩個子組件封裝成ES模組的寫法
https://grok.com/share/bGVnYWN5_e3c3e5c9-99c8-47d7-9164-be38155369bb
我的ASP.net MVC專案整合Vue3的起手式範本
Index.cshtml
<!DOCTYPE html>
<html lang="zh-TW">
<head>
<meta charset="UTF-8">
<title>Vue 應用</title>
</head>
<body>
<div id="vue-app">
<div>
<nav>
<router-link to="/">首頁</router-link> |
<router-link to="/about">關於</router-link>
</nav>
<router-view></router-view>
</div>
</div>
<script type="text/x-template" id="home-template">
<div>
<h1>Home</h1>
<p>{{ message }}</p>
</div>
</script>
<script type="text/x-template" id="about-template">
<div>
<h1>About</h1>
<p>{{ message }}</p>
</div>
</script>
<script type="importmap">
{
"imports": {
"vue": "https://unpkg.com/vue@3/dist/vue.esm-browser.js",
"vue-router": "https://unpkg.com/vue-router@4/dist/vue-router.esm-browser.js",
"@@vue/devtools-api": "https://unpkg.com/@@vue/devtools-api@6.5.0/lib/esm/index.js"
}
}
</script>
<script>
const serverRoot = "@Url.Content("~/")";
</script>
<script type="module" src="~/Vue-js/app.js"></script>
</body>
</html>
app.js
import { createApp } from 'vue';
import { createRouter, createWebHashHistory } from 'vue-router';
import Home from "./components/Home.js"; // 引入 Home 組件
import About from "./components/About.js"; // 引入 About 組件
// 定義路由
const routes = [
{ path: '/', component: Home },
{ path: '/about', component: About }
];
// 創建路由器實例
const router = createRouter({
history: createWebHashHistory(),
routes
});
// 創建 Vue 應用實例並使用路由器
const app = createApp({
setup() {
}
});
app.use(router);
// 掛載應用到 #vue-app
app.mount('#vue-app');
Home.js
import { ref } from 'vue';
export default {
setup() {
return { message: '歡迎來到首頁' };
},
template: '#home-template'
};
About.js
import { ref } from 'vue';
export default {
setup() {
return { message: '關於的頁面' };
},
template: '#about-template'
};