【Vue3】一文全览基础语法-案例程序及配图版
文章目录
- Vue应用基本结构
- 模块化开发
- ref和reactive
- 绑定事件 v-on 简写@
- 显示和隐藏 v-show
- 条件渲染 v-if
- 动态属性绑定 v-bind 简写:
- 遍历数组或对象 v-for
- 双向数据绑定 v-model
- 渲染数据 v-text 和 v-html
- 计算属性 computed
- 侦听器 watch
- 自动侦听器 watchEffect
本文示例代码下载链接Vue3基本语法示例代码
Vue.js是渐进式JavaScript框架,渐进式是指可以按需引入Vue.js的部分功能, 而不必全量引入整个框架。
下面引入vue采用本地文件的方式:
vue.global.js
vue.esm-browser.js
vue.esm-browser.js和vue.global.js是Vue.js的两个不同构建版本,主要区别在于模块系统和使用场景。前者更适合模块化开发,如webpack打包。后者是一个全局构建,适合在浏览器中直接使用,不依赖模块系统。在全局作用域中注册Vue,使得在浏览器中可以直接通过Vue访问Vue的API。更适合快速原型开发或者在没有构建工具的情况下直接在 HTML 中使用。
加载后可在浏览器页面中右键另存为js文件,放到测试文件中,类似如下:
如果采用的是VS Code,可安装插件Live Server,右键查看页面效果:
Vue应用基本结构
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><!--<div id="app"></div> 指定一个id为app的div元素;{{ }} 插值表达式, 可以将 Vue 实例中定义的数据在视图中进行渲染,如: Vue实例中定义一个 msg变量, 值为"Hello world", 在模板中若使用插值表达式{{ msg }}则会被渲染成"Hello world";响应式数据是指当数据发生变化时, 模板中依赖于该数据的部分会自动更新--><div id="app">{{ msg }}<h2>{{ web.title }}</h2><h3>{{ web.url }}</h3></div><script>//创建一个 Vue 应用程序Vue.createApp({//Composition API(组合式API) 的setup选项 用于设置响应式数据和方法等setup() {//Composition API的reactive()函数 用于创建响应式数据//Vue.reactive创建一个响应式数据对象web, 其中包含title和url属性const web = Vue.reactive({ title: "百度搜索",url: "baidu.com"})//返回数据return {msg: "success",web}}}).mount("#app") //将Vue应用程序挂载(mount)到app元素上</script>
</body>
</html>
上述程序运行结果页面如下:
或者将创建app部分更换成如下写法,效果相同:
//将 Vue 对象中的 createApp、reactive 属性赋值给 createApp、reactive 变量
const { createApp, reactive } = Vue //解构赋值语法createApp({setup() {const web = reactive({title: "百度搜索",url: "baidu.com"})return {msg: "success",web}}
}).mount("#app")
模块化开发
或者像如下方式引入esm-browser.js中的模块也是相同的效果。
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({title: "百度搜索",url: "baidu.com"})return {msg:"success",web}}}).mount("#app")
</script>
ref和reactive
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><div id="app">msg: {{ msg }}<h3>web.title: {{ web.title }}</h3><h3>web.url: {{ web.url }}</h3><h3>web.number: {{ number }}</h3></div><script type="module">import { createApp, ref, reactive } from './vue.esm-browser.js'createApp({setup() {//ref用于存储单个基本类型的数据, 如:数字、字符串等const number = ref(10) //使用ref创建的响应式对象, 需要通过.value属性来访问和修改其值number.value = 20 //用于存储复杂数据类型, 如:对象或数组等const web = reactive({ title: "百度搜索",url: "baidu.com"})//使用reactive创建的响应式对象, 可以直接通过属性名来访问和修改值web.url = "www.baidu.com" return {msg: "success",number,web}}}).mount("#app")</script>
</body>
</html>
上述程序运行结果如下:
绑定事件 v-on 简写@
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><div id="app"><h3>{{ msg }}</h3><h3>{{ web.url }}</h3><h3>{{ web.user }}</h3><h3>{{ sub(100, 20) }}</h3><!-- v-on:click 表示在 button 元素上监听 click 事件 --><button v-on:click="edit">修改</button> <br><!-- @click 简写形式 --><button @click="add(20, 30)">加法</button> <br><!-- enter space tab 按键修饰符keyup是在用户松开按键时才触发keydown是在用户按下按键时立即触发-->回车 <input type="text" @keyup.enter="add(40, 60)"> <br>空格 <input type="text" @keyup.space="add(20, 30)"> <br>Tab <input type="text" @keydown.tab="add(10, 20)"> <br>w <input type="text" @keyup.w="add(5, 10)"> <br><!-- 组合快捷键 -->Ctrl + Enter <input type="text" @keyup.ctrl.enter="add(40, 60)"> <br>Ctrl + A <input type="text" @keyup.ctrl.a="add(20, 30)"></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({title: "百度搜索",url: "baidu.com",user: 0})const edit = () => {web.url = "www.baidu.com"//错误示例 不能直接改变msg的值,因为msg是一个普通变量, 不是响应式数据//msg = "百度搜索" }const add = (a, b) => {web.user += a + b}const sub = (a, b) => {return a - b}return {//普通变量, 非响应式数据, 在模板中普通变量不会自动更新msg: "success", //响应式数据web, //方法edit, add,sub,}}}).mount("#app")</script></body>
</html>
上述程序运行初始界面如下:
上述页面中点击相应按钮会将光标定位到输入框内再使用快捷键即可完成相应的调用加法功能函数,页面中数据渲染及时更新。
显示和隐藏 v-show
<div id="app"><h3>{{ web.show }}</h3><p v-show="web.show">百度搜索 baidu.com</p><button @click="toggle">点击切换显示状态</button>
</div>
<script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({show: true})const toggle = () => {web.show = !web.show}return {web,toggle}}}).mount("#app")
</script>
上述程序运行后初始页面如下:
点击按钮可切换页面中元素如下:
条件渲染 v-if
<div id="app"><h3>{{ web.show }}</h3><p v-show="web.show">百度搜索</p><p v-if="web.show">baidu.com</p><button @click="toggle">点击切换显示状态</button><p v-if="web.user < 1000">Class1网站</p><p v-else-if="web.user >= 1000 && web.user < 10000">Class2网站</p><p v-else-if="web.user >= 10000 && web.user < 100000">Class3网站</p><p v-else>SuperClass网站</p>
</div>
<script type="module">/*v-show通过 css display属性来控制元素的显示或隐藏;v-if用于对元素进行条件渲染. 当条件为true时, 渲染该元素; 为false时, 则不渲染。v-show适用于频繁切换元素的显示状态, 因为只改变display属性, 不需要重新渲染整个组件。v-if适用于较少改变的场景, 因为频繁从dom中删除或添加元素, 会导致性能下降。*/import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({show: true,user: 500})const toggle = () => {web.show = !web.show}return {web,toggle}}}).mount("#app")
</script>
动态属性绑定 v-bind 简写:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script><style>.textColor{color:aqua;}</style>
</head>
<body><div id="app"><h3>常规方法传值</h3><h3>{{value}}</h3><input type="text" value="baidu.com"><h3>使用v-bind动态传值</h3><h3>{{web.url}}</h3><input type="text" v-bind:value="web.url"><h3>使用v-bind简写形式传值,即只有一个冒号</h3><input type="text" :value="web.url"><!-- :src --><h3>本地路径传图片资源</h3><img src="./images/test.jpg" style="max-width: 20%; height: auto;"><h3>动态绑定图片源</h3><img :src="web.img" style="max-width: 10%; height: auto;"><h3>动态绑定类名</h3>百度搜索<!-- b标签用于加粗文本 --><b class="textColor">百度搜索</b><!-- :class用于动态绑定类名。如果web.fontStatus为true,则会将textColor类应用于<b>标签;如果为false,则不会应用这个类。 --><h3>动态绑定类名并决定是否启用</h3><b :class="{textColor:web.fontStatus}">baidu.com</b></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({url: "www.baidu.com",img: "./images/test.jpg",fontStatus: true})return {web}}}).mount("#app")</script>
</body>
</html>
上述程序运行后效果如下:
遍历数组或对象 v-for
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script><style>.textColor{color:aqua;}</style>
</head>
<body><div id="app"><ul><li v-for="(value, index) in data.number">index值为{{ index }} : value值为{{ value }}</li></ul><ul><li v-for="value in data.user">value值为{{ value }}</li></ul><ul><li v-for="(value, key) in data.user">key值为{{ key }} : value值为{{ value }}</li></ul><ul><li v-for="(value, key, index) in data.user">index值为{{ index }} : key值为{{ key }} : value值为{{ value }}</li></ul><ul><!-- <template> 标签可以用来包装多个元素或者多行代码, 不会在页面中渲染 --><template v-for="(value, key, index) in data.user"><li v-if="index == 1">index值为{{ index }} : key值为{{ key }} : value值为{{ value }}</li></template></ul><ul><!-- :key="value.id" 为 每个 li 元素设置一个唯一的 key 值 --><li v-for="(value, index) in data.teacher" :title="value.name" :key="value.id">index值为 {{ index }} : value.id值为{{ value.id }} value.name值为{{ value.name }} value.web值为{{ value.web }}</li></ul></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({number: ["足球", "篮球", "排球"], //数组user: { //对象name: "tina",gender: "女"},//包含两个对象的数组teacher: [ { id: 100, name: "小明", web: "baidu.com" },{ id: 101, name: "Mario", web: "www.baidu.com" }]})return {data}}}).mount("#app")</script>
</body>
</html>
上述程序运行后效果如下:
双向数据绑定 v-model
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script><style>.textColor{color:aqua;}</style>
</head>
<body><div id="app"><h3>文本框 {{ data.text }}</h3><h3>单选框 {{ data.radio }}</h3><h3>复选框 {{ data.checkbox }}</h3><h3>记住密码 {{ data.remember }}</h3><h3>下拉框 {{ data.select }}</h3><!-- 单向数据绑定 当数据发生改变时, 视图会自动更新. 但用户手动更改 input 的值, 数据不会自动更新 -->单向数据绑定 <input type="text" :value="data.text"><hr><!-- 双向数据绑定 当数据发生改变时, 视图会自动更新. 当用户手动更改 input 的值, 数据也会自动更新对于 <input type="text">, v-model 绑定的是 input 元素的 value 属性-->双向数据绑定 <input type="text" v-model="data.text"><hr><!-- 单选框 对于 <input type="radio">, v-model 绑定的是 input 元素的选中状态--><input type="radio" v-model="data.radio" value="1">男<input type="radio" v-model="data.radio" value="2">女<hr><!-- 复选框对于 <input type="checkbox">, v-model 绑定的是 input 元素的选中状态--><input type="checkbox" v-model="data.checkbox" value="a">红色<input type="checkbox" v-model="data.checkbox" value="b">绿色<input type="checkbox" v-model="data.checkbox" value="c">蓝色<hr><!-- 记住密码 --><input type="checkbox" v-model="data.remember">记住密码<hr><!-- 下拉框对于 <select>, v-model 绑定的是 select 元素的选中状态--><select v-model="data.select"><option value="">请选择</option><option value="A">红色</option><option value="B">绿色</option><option value="C">蓝色</option></select></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const data = reactive({text: "baidu.com", //文本框radio: "", //单选框checkbox: [], //复选框remember: false, //单个复选框-记住密码select: "" //下拉框})return {data}}}).mount("#app")</script>
</body>
</html>
上述程序运行结果如下图所示:
当操作双向绑定文本框或其他可选控件时数据可双向绑定实时更新:
另外还有v-model常见修饰符属性案例,如下:
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><div id="app"><h3>url: {{ web.url }}</h3><h3>user: {{ web.user }}</h3>实时渲染 <input type="text" v-model="web.url"> <br>在失去焦点或按下回车键之后渲染 <input type="text" v-model.lazy="web.url"> <br><!-- 输入 100人, web.user 的值仍为 100 -->输入框的值转换为数字类型 <input type="text" v-model.number="web.user"> <br><!-- 此处的输入框输入完之后去除首尾空格,但管不到其他部分更新的数据 -->去除首尾空格 <input type="text" v-model.trim="web.url"></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({url: "baidu.com",user: 10})return {web}}}).mount("#app")</script>
</body>
</html>
上述程序运行结果如下图所示:
相应动态效果如描述所示。
渲染数据 v-text 和 v-html
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><div id="app"><h3>{{ web.title }}</h3><!-- v-text 将数据解析为纯文本格式 --><h3 v-text="web.title"></h3><!-- v-html 将数据解析为 html 格式 --><h3 v-html="web.url"></h3></div><script type="module">import { createApp, reactive } from './vue.esm-browser.js'createApp({setup() {const web = reactive({title: "百度搜索",url:"<i style='color:blue;'>www.baidu.com</i>"})return {web}}}).mount("#app")</script>
</body>
</html>
上述程序运行结果如下图所示:
计算属性 computed
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><div id="app"><h3>add: {{ add() }}</h3><h3>add: {{ add() }}</h3><h3>sum: {{ sum }}</h3><h3>sum: {{ sum }}</h3>x <input type="text" v-model.number="data.x"> <br>y <input type="text" v-model.number="data.y"></div><script type="module">import { createApp, reactive, computed } from './vue.esm-browser.js'createApp({setup() {const data = reactive({x: 10,y: 20})//方法-无缓存,只要被调用就会执行方法里面的代码let add = () => {console.log("add") //打印两次return data.x + data.y}//计算属性-有缓存 [计算属性根据其依赖的响应式数据变化而重新计算]//只有当依赖的数据发生变化才会执行里面的内容,否则使用缓存const sum = computed(() => {console.log("sum") //打印一次return data.x + data.y})return {data,sum,add}}}).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"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><div id="app">颜色<select v-model="color"><option value="">请选择</option><option value="1">红色</option><option value="2">绿色</option><option value="3">蓝色</option></select><hr>年<select v-model="date.year"><option value="">请选择</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option></select>月<select v-model="date.month"><option value="">请选择</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select></div><script type="module">import { createApp, ref, reactive, watch } from './vue.esm-browser.js'createApp({setup() {const color = ref("") //颜色const date = reactive({ //日期year: "2024",month: "11"})//监听 colorwatch(color, (newValue, oldValue) => {console.log("oldValue", oldValue, "newValue", newValue)if (newValue == "2") {console.log("绿色")}})//监听 datewatch(date, (newValue, oldValue) => {/*JS中对象和数组是通过引用传递的, 而不是通过值传递当修改对象或数组的值时, 实际上修改的是对象或数组的引用, 而不是创建一个新的对象或数组所以,如果修改了对象或数组的值,那么打印出来的结果则是修改后的值*/console.log("oldValue", oldValue, "newValue", newValue)if (newValue.year == "2025") {console.log("2025")}if (newValue.month == "11") {console.log("11")}})//监听 date 中的某个属性 year//使用() = >创建了一个getter函数,这样只监听特定的属性变化watch(() => date.year, (newValue, oldValue) => {console.log("oldValue", oldValue, "newValue", newValue)if (date.year == "2024") {console.log("2024")}})return {color,date}}}).mount("#app")</script>
</body>
</html>
上述程序运行结果如下图所示:
点改变相应控件的值时,相应的监听函数会被调用。
补充引用传递相关知识:
引用传递是指在 JavaScript 中,当对象或数组作为参数传递时,传递的是对该对象或数组的引用,而不是其副本。这意味着在函数内部对该对象或数组的修改将影响到外部的原始对象或数组。
//假设我们有一个对象 person,我们将其作为参数传递给一个函数
let person = {name: "Alice",age: 25
};function updateAge(obj) {obj.age += 1; // 修改对象的 age 属性console.log("内部:", obj);
}//在updateAge函数中,obj实际上是对person对象的引用。对obj.age的修改直接影响了person.age的值。
//因此当在updateAge函数中增加age时,person对象的age属性也发生了变化。
console.log("修改前:", person); // 输出: { name: 'Alice', age: 25 }
updateAge(person); // 传递引用
console.log("修改后:", person); // 输出: { name: 'Alice', age: 26 }
自动侦听器 watchEffect
当在watchEffect内部引用响应式数据(如ref或reactive的属性)时,Vue会自动追踪这些依赖。这意味着只要这些数据发生变化,watchEffect内的函数就会被重新执行。包括:
- 用户在界面上进行交互导致数据变化。
- 程序代码直接修改数据的情况。
- 刷新页面并重新挂载组件时,watchEffect也会在组件首次加载时执行一次。
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Demo</title><script src="vue.global.js"></script>
</head>
<body><div id="app">颜色<select v-model="color"><option value="">请选择</option><option value="1">红色</option><option value="2">绿色</option><option value="3">蓝色</option></select><hr>年<select v-model="date.year"><option value="">请选择</option><option value="2023">2023</option><option value="2024">2024</option><option value="2025">2025</option></select>月<select v-model="date.month"><option value="">请选择</option><option value="10">10</option><option value="11">11</option><option value="12">12</option></select></div><script type="module">/*watch需要显式指定要监听的属性, 并且只有当监听的属性发生变化时才会执行若需要更精细地控制或需要获取到原值, 需要使用watch*/import { createApp, ref, reactive, watchEffect } from './vue.esm-browser.js'createApp({setup() {const color = ref("") //颜色const date = reactive({ //日期year: "2024",month: "11"})//自动监听watchEffect(() => {console.log("------ 监听开始")if (color.value == "2") {console.log("绿色")}if (date.year == "2025") {console.log("2025")}if (date.month == "11") {console.log("11")}console.log("------ 监听结束")})return {color,date}}}).mount("#app")</script>
</body>
</html>
上述程序运行结果如下图所示: