Vue3简单快速基础入门 (一)

Vue (发音为 /vjuː/,类似 view) 是一款用于构建用户界面的 JavaScript 框架。它基于标准 HTML、CSS 和 JavaScript 构建,并提供了一套声明式的、组件化的编程模型,帮助你高效地开发用户界面。无论是简单还是复杂的界面,Vue 都可以胜任。

Vue3官方文档中文版
响应式数据是指当数据发生变化时, 模板中依赖于该数据的部分会自动更新
本系列所有代码都在VSCode中编写

1. 创建第一个Vue应用

初期学习,这里通过CDN使用Vue

1.1 全局构建版本引入

全局构建版本,也就是说所有顶层 API 都以属性的形式暴露在了全局的 Vue 对象上。

<script src="https://unpkg.com/vue@3/dist/vue.global.js"></script>

如例:

    <script src="./vue.global.js"></script>
    <div id = "app">
        <h1>{{ msg }}</h1>
        <h1>{{ syy.name }} |{{ syy.age }}</h1>
    </div>

    <script>
        // 原语法 Vue.createApp     Vue.reactive  
        // 现在使用解构赋值语法,省去Vue    
        // 将 Vue 对象中的 createApp、reactive 属性赋值给 createApp、reactive 变量
        const {createApp,reactive} = Vue  
        

        // Vue.createApp
        createApp({
            //setup选项 用于设置响应式数据和方法
            setup(){
                const syy = reactive({
                    name:"syy",
                    age:22
                })
                return{
                    msg:"hello world",
                    syy
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

1.2 ES 模块构建版本

ES 模块构建版本,主要通过模块系统导入 API。需要注意的是模块构建只能工作在http://协议中,不支持file://协议。

要启动一个本地的 HTTP 服务器,请先安装 Node.js,然后通过命令行在 HTML 文件所在文件夹下运行 npx serve

或者使用VSCode安装插件Live Server,然后在VSCode中打开 HTML 文件,点击右下角的Go Live按钮,即可启动本地服务器。

    <div id = "app">
        <h1>{{ msg }}</h1>
        <h1>{{ syy.name }} |{{ syy.age }}</h1>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">
        // 模块化开发Vue
        import {createApp,reactive} from './vue.esm-browser.js'
        // 可以直接导入cdn的vue.esm-browser.js文件
        // import { createApp, reactive } from 'https://unpkg.com/vue@3/dist/vue.esm-browser.js'
        

        createApp({
            setup(){
                const syy = reactive({
                    name:"syy",
                    age:22
                })

                return{
                    msg:"hello world",
                    syy
                }
            }
            
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

2. ref 和 reactive 的区别

ref 用于存储单个基本类型的数据,比如数值、字符串等,也可以存数组。
reactive 用于存储复杂数据类型,比如对象或数组等。

2.1 ref

使用前需要先导入ref,使用ref声明的属性,通过.value来获取和修改其值。但是在模板中使用 ref 时,我们不需要附加 .value

    <div id = "app">
        <h1>{{ number }}</h1>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import {createApp,ref,reactive} from './vue.esm-browser.js'
        

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup(){
                // 使用ref为number声明一个响应式变量,初始值为0
                const number = ref(0);
                // 修改number的值为 10
                number.value = 10;
                return{
                    //返回 number 数据
                    number
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

2.2 reactive

使用前需要先导入reactive,使用reactive声明的属性,可以通过.[属性名]来获取和修改其值。

    <div id = "app">
        <h1>{{ web.title }}</h1>
        <h1>{{ web.author }}</h1>
        <h1>{{ web.content }}</h1>
        <h1>{{ web.url }}</h1>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import {createApp,ref,reactive} from './vue.esm-browser.js'
        

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup(){
                // 使用reactive声明一个响应式对象,并为对象属性赋值
                const web = reactive({
                    title: "Vue3 基础入门",
                    author: "syy",
                    content: "Vue3 是一个用于构建用户界面的 JavaScript 框架。",
                    url: "https://cn.vuejs.org/guide/introduction.html"
                })
                //直接通过对象.属性修改值
                web.url = "https://blog.xy21lin.cn";
                return {
                    //返回 web 数据
                    web
                }
            }
            
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

3. 绑定事件v-on:click

v-on:click 用于绑定事件,可以绑定原生事件和自定义事件。

    <div id="app">
          <!-- v-on:click 绑定事件  -->
        <button v-on:click="editUrl">修改URL地址</button>
        <!-- 简写形式 @click -->
        <button @click="editUrl">修改URL地址-简写</button>
        <!-- keyup 按键松开后触发 -->
        keydown 按键按下时就触发 一直按着不放一直触发
        按下回车触发<input type="text" @keydown.enter="add(40,30)">
        松开空格触发<input type="text" @keyup.space="sub(10,20)">
        按下w触发<input type="text" @keydown.w="add(40,30)">

        <!--组合快捷键 -->
        ctrl + a 触发<input type="text" @keyup.ctrl.a="add(40,30)">
        ctrl + alt + c 触发<input type="text" @keydown.ctrl.alt.c="add(40,30)">
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, ref, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                // 使用reactive声明一个响应式对象,并为对象属性赋值
                const web = reactive({
                    title: "Vue3 基础入门",
                    author: "syy",
                    content: "Vue3 是一个用于构建用户界面的 JavaScript 框架。",
                    url: "https://cn.vuejs.org/guide/introduction.html",
                    user: 500000,
                })
                
                // // 定义一个函数方法,用于修改web对象中的url属性,使用变量 editUrl 接收
                const editUrl = () => {
                    //直接通过对象.属性修改值
                    web.url = "https://blog.xy21lin.cn";
                }

                const add = (a,b) => {
                    web.user +=   a + b
                }
                const sub = (a,b) =>{
                    web.user -=   a + b
                }



                // 返回数据和方法
                return {
                    web,
                    editUrl,
                    add,
                    sub
                }
            }

        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

4. 显示和隐藏 v-show

    <div id="app">
        <!-- v-show 显示或隐藏元素 -->
        <h1 v-show="web.show">{{ web.title }}</h1>
        <button @click="updateShow">显示/隐藏</button>

    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, ref, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                // 使用reactive声明一个响应式对象,并为对象属性赋值
                const web = reactive({
                    show:true
                })

                const updateShow = () =>{
                    web.show = !web.show
                }


                // 返回数据和方法
                return {
                    web,
                    updateShow
                }
            }

        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

5. 条件渲染 v-if 和 v-else

    <div id="app">
        <!-- v-if 条件判断,如果条件为真,则渲染该元素,否则不渲染 会频繁删除添加元素,性能有影响-->
        <h1 v-if="web.show">{{ web.author }}</h1>
        <!-- 如果web.user小于1000,显示“新网站”;如果web.user大于等于1000小于10000,显示“优秀网站”;否则显示“资深网站” -->
        <p v-if="web.user < 1000">新网站</p>
        <p v-else-if="web.user >=1000 && web.user < 10000">优秀网站</p>
        <p v-else>资深网站</p>
        <button @click="updateShow">显示/隐藏</button>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, ref, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                // 使用reactive声明一个响应式对象,并为对象属性赋值
                const web = reactive({
                    title: "Vue3 基础入门",
                    author: "syy",
                    content: "Vue3 是一个用于构建用户界面的 JavaScript 框架。",
                    url: "https://cn.vuejs.org/guide/introduction.html",
                    user: 500000,
                    show:true
                })
                

                const updateShow = () =>{
                    web.show = !web.show
                }


                // 返回数据和方法
                return {
                    web,
                    updateShow
                }
            }

        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

6. 动态绑定v-bind:

    <style>
        .textStyle {
            font-size: 24px;
            color: green;
        }
    </style>

    <div id="app">
        正常v-bind: 动态绑定属性
        <input type="text" v-bind:value="web.title"/>
        <br>
        简写v-bind:     只用 :value 即可
        <input type="text" :value="web.title"/>
        <img :src="web.img">
        <p style="color:blue">
            原style样式: 十一月的早晨
        </p>
        <p :style="web.style">
            动态绑定后:十一月的早晨
        </p>
        <p class="textStyle">
            渲染样式:十一月的早晨
        </p>
        <!-- web.fontStatus 为false   不渲染样式 -->
        <p :class="{textStyle:web.fontStatus}">
            动态决定是否渲染样式:十一月的早晨
        </p>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, ref, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                // 使用reactive声明一个响应式对象,并为对象属性赋值
                const web = reactive({
                    title: "Vue3 基础入门",
                    img:"https://api.r10086.com/%E5%9B%BE%E5%8C%85webp/%E9%A3%8E%E6%99%AF%E7%B3%BB%E5%88%971/107295.webp",
                    style:"color:red",
                    fontStatus:false
                })
                
                // 返回数据和方法
                return {
                    web
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

7. 遍历数组或对象 v-for

    <div id="app">
        <ul>
            <!-- 直接遍历number数组 -->
            <li v-for="value in data.number">
                {{value}}
            </li>
        </ul>
        <hr>
        <ul>
            <!-- 遍历number数组值,并输出索引 -->
            <li v-for="(value,index) in data.number">
                index = > {{index}}  | value = > {{value}}
            </li>
        </ul>
        <hr>
        <ul>
            <!-- 直接遍历对象 -->
            <li v-for="value in data.person">
                {{value}}
            </li>
        </ul>
        <hr>
        <ul>
            <!-- 输出对应的键值对 -->
            <li v-for="(value,key) in data.person">
                key = > {{key}}  | value = > {{value}}
            </li>
        </ul>
        <hr>
        <ul>
            <!-- 输出对应的键值对以及索引 -->
            <li v-for="(value,key,index) in data.person">
                index = > {{index}}  |  key = > {{key}}  | value = > {{value}}
            </li>
        </ul>
        <hr>
        <ul>
            <!-- 限制条件遍历 -->
            <template v-for="(value,key,index) in data.person">
                <li v-if="index == 1">
                    index = > {{index}}  |  key = > {{key}}  | value = > {{value}}
                </li>
            </template>
        </ul>
        <hr>
        <ul>
            <!-- 遍历数组并通过 .属性的方式访问对象属性 -->
            <!-- 这里使用动态绑定 也就是v-bind 绑定了title和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.subject = > {{value.subject}} 
            </li>
        </ul>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data  = reactive({
                    // 数组
                    number:[1,3,5,7,9],
                    // 对象
                    person:{
                        name:"张三",
                        age:20,
                        sex:"男"
                    },
                    // 包含数组的对象
                    teacher:[{id:99,name:"李四",subject:"数学"},{id:120,name:"王五",subject:"语文"}]

                })
                // 返回数据和方法
                return {
                    data
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

8. 双向数据绑定v-model

    <div id="app">
        <!-- 单向数据绑定,当数据发生改变的时候,视图也会更新,但是手动更改input值,数据不会自动更新 -->
        <!-- 双向数据绑定,当数据发生改变的时候,视图也会更新,并且手动更改input值,数据也会自动更新 -->
        <h1>文本框{{data.text}}</h1>
        <!-- 对于 type="text" v-model绑定的是value属性 -->
        单向数据绑定<input type="text" :value="data.text">
        <hr>
        双向数据绑定<input type="text" v-model="data.text">


        <!-- 单选框 绑定的是radio的选中状态  所以需要自己定义value的值 -->
        <h1>单选框{{data.radio}}</h1>
        <input type="radio" v-model="data.radio" value="1">
        <input type="radio" v-model="data.radio" value="大海">
        <input type="radio" v-model="data.radio" value="花儿">
        

        <!-- 多个复选框 绑定的也是选中状态  所以需要自己定义value的值  复选框可以选中多个值,所以使用数组接收 -->
        <h1>复选框{{data.checkbox}}</h1>
        <input type="checkbox" v-model="data.checkbox" value="music">听歌
        <input type="checkbox" v-model="data.checkbox" value="book">看书
        <input type="checkbox" v-model="data.checkbox" value="game">游戏

        <!-- 单个复选框   绑定的是单个的选中状态 值就是为false或true   所以不需要自己定义value的值-->
        <h1>单个复选框{{data.remember}}</h1>
        <input type="checkbox" v-model="data.remember">记住密码


        <!-- 下拉框 绑定的也是选中状态  所以需要自己定义value的值 -->
        <h1>下拉框{{data.select}}</h1>
        <select v-model="data.select">
            <option value="">请选择</option>
            <option value="1"></option>
            <option value="2"></option>
        </select>
        
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data  = reactive({
                    text: "hello world",
                    radio:"",
                    checkbox:[],
                    remember:false,
                    select:""

                })
                // 返回数据和方法
                return {
                    data
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

9. v-model 修饰符

v-model 修饰符能够对 v-model 绑定的数据进行一些特定处理。
这里只介绍常用的三种修饰符(lazy,number, trim)。

    <div id="app">
        <h1>Text值:{{data.text}}</h1>
        <!-- 更改input值,数据实时渲染 -->
        实时渲染<input type="text" v-model="data.text">
        <hr>
        <!-- 更改input值,数据不会立即渲染,而是在失去焦点或按下回车后才进行渲染 -->
        lazy修饰符<input type="text" v-model.lazy="data.text">
        <hr>
        <!-- 将input内的值转为number类型,如果转换不了,则显示原始字符串 -->
        <!-- 比如 100001人   会转换成 100001 -->
        <!-- 1001人10001 则会转换成1001 因为无法转换人 所以后面的10001会被舍弃 -->
        <!-- 人10001  则无法转换,显示原始字符串 -->
        
        <h1>number值:{{data.number}}</h1>
        number修饰符<input type="text" v-model.number="data.number">
        <hr>
        <!-- trim修饰符 去除首尾空格,但是字符串中的空格无法去除 -->
        <h1>trim值:{{data.trim}}</h1>
        trim修饰符<input type="text" v-model.trim="data.trim">
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data  = reactive({
                    text: "hello world",
                    number:100,
                    trim:"hi JimBaby"
                })
                // 返回数据和方法
                return {
                    data
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

10. 渲染数据 v-text 和 v-html

    <div id="app">
        <!-- v-text 将数据解析为文本格式 也就相当于之前的插值表达式 {{data.text}}-->
        <h1 v-text="data.text"></h1>
        <h1 v-text="data.html"></h1>
        <!-- v-html 将数据解析为html格式 -->
        <h1 v-html="data.html"></h1>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, reactive } from './vue.esm-browser.js'


        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data  = reactive({
                    text: "hello world",
                    html:"<a style='color:red' href='https://blog.xy21lin.cn'>blog.xy21lin.cn</a>"
                })
                // 返回数据和方法
                return {
                    data
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

11. 计算属性 computed

computed 选项用于声明计算属性,它返回一个计算结果,并且可以缓存计算结果,只有当计算结果变化时,才会重新求值。

    <div id="app">
        

        <h1> add:{{add()}}</h1>
        <h1> add:{{add()}}</h1>

        <!-- 注意这里 sub是属性 不是方法 所以不需要`()` -->
        <h1> sub:{{sub}}</h1>
        <h1> sub:{{sub}}</h1>

    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp, reactive,computed } from './vue.esm-browser.js'

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data  = reactive({
                    x:10,
                    y:20
                })

                // 普通计算方法 无缓存 调用几次执行几次
                const add = () =>{
                    console.log('add')
                    return data.x + data.y
                }

                
                // computed计算属性 有缓存 依赖的计算属性发生变化后,才会重新计算
                const sub = computed(()=>{
                    console.log('sub')
                    return data.x - data.y
                })

                // 返回数据和方法
                return {
                    data,
                    add,
                    sub
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

可以从控制台console.log中看到,add和sub都调用了两次,add方法执行了两次,sub计算属性只执行一次。

12. 侦听器 watch

watch 选项用于观察数据的变化,一旦数据变化,就自动运行相应的函数。

    <div id="app">
        请选择爱好
        <select v-model="hobby">
            <option value="1">听歌</option>
            <option value="2">看书</option>
            <option value="3">画画</option>
        </select>
        <hr>
        请选择年份
        <select v-model="date.year">
            <option value="2021">2021</option>
            <option value="2022">2022</option>
            <option value="2023">2023</option>
        </select>

        请选择月份
        <select v-model="date.month">
            <option value="6">6</option>
            <option value="7">7</option>
            <option value="8">8</option>
        </select>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp,ref, reactive,watch } from './vue.esm-browser.js'

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const hobby = ref("")
                const date = reactive({
                    year:"2022",
                    month:"6"
                })

                // 监听hobby变化
                watch(hobby,(newValue,OldValue) =>{
                    console.log("hobby的值发生了变化","newValue: ", newValue,"OldValue: ",OldValue)
                })

                //监视date变化
                // newValue oldValue 都是对象,所以打印出来的都是修改后的值
                // js中对象和数组都是引用传递,当修改对象或数组的值时,改变的是值的引用,而不是新建了对象或数组,所以打印出来的是修改后的值
                watch(date,(newValue,oldValue)=>{
                    console.log("newValue: ",newValue,"oldValue: " , oldValue)

                    if(date.year == "2023")console.log("选择了2023年")
                    if(date.month == "7")console.log("选择了7月")
                })


                // 监视date中属性的变化
                watch(()=>date.year,(newValue,oldValue)=>{
                    console.log("年份发生了变化","newValue: ",newValue,"oldValue: ",oldValue)
                })

                // 返回数据和方法
                return {
                    date,
                    hobby
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

13. 自动侦听器watchEffect

watchEffect 选项用于观察数据的变化,一旦数据变化,就自动运行相应的函数。

    <div id="app">
        请选择爱好
        <select v-model="hobby">
            <option value="1">听歌</option>
            <option value="2">看书</option>
            <option value="3">画画</option>
        </select>
        <hr>
        请选择年份
        <select v-model="date.year">
            <option value="2021">2021</option>
            <option value="2022">2022</option>
            <option value="2023">2023</option>
        </select>

        请选择月份
        <select v-model="date.month">
            <option value="6">6</option>
            <option value="7">7</option>
            <option value="8">8</option>
        </select>
    </div>

    <!-- 更改模块化  type='module' -->
    <script type="module">

        // 模块化开发Vue
        import { createApp,ref, reactive,watchEffect } from './vue.esm-browser.js'

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const hobby = ref("")
                const date = reactive({
                    year:"2022",
                    month:"6"
                })

                watchEffect(()=>{
                    console.log("==========>监听开始")
                    if(date.year == "2023")console.log("选择了2023年")
                    if(date.month == "7")console.log("选择了7月")
                    if(hobby.value == "3")console.log("选择了画画")
                    console.log("==========>监听结束")
                })

                // 返回数据和方法
                return {
                    date,
                    hobby
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

如果需要更精细的监听,还是更推荐使用watch进行手动监听