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

这里主要演示一些简单实际案例

1. 图片轮播案例

    <div id="app">
        <h1>当前页数:{{number}}</h1>

        <!-- 实现轮播图,所以要使用v-bind 动态绑定src属性,并且number变量控制图片的切换 使用 ``包裹路径 ${}包裹变量 -->
        <img :src=`./img/${number}.jpg` />
        <hr>
        <button @click="prev">上一页</button>

        <button @click="next">下一页</button>

        <ul>
            <li v-for="value in 4"><a href="#" @click="jump(value)">{{value}}</a></li>
        </ul>
        
    </div>

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

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

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const number = ref(3)
                const prev = ()=>{
                    number.value--
                    if(number.value == 0)number.value = 4
                }

                const next = ()=>{
                    number.value++
                    if(number.value == 5)number.value = 1
                }

                const jump = (value) =>{
                    number.value = value
                }
                // 返回数据和方法
                return {
                    number,
                    prev,
                    next,
                    jump
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

2. 记事本案例

实现一个简单的记事本案例,主要熟悉数组的操作

    <div id="app">
        <h1>数组长度:{{data.list.length}}</h1>
        <hr>
        <input type="text" v-model="data.text">
        <!-- 添加元素到数组末尾 使用push方法 -->
        <button @click="add">添加</button>
        <button @click="clear">清空</button>

        <hr>
        <!-- 遍历输出数组元素 -->
        <ul>
            <li v-for="(value,index) in data.list">
                {{value}}
                <!-- 删除元素 使用splice方法 -->
                <button @click="del(index)">删除</button>
            </li>
        </ul>
    </div>

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

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

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data = reactive({
                    text:"十一月的早晨",
                    list:["吹进卧室的风","春日玫瑰"]
                })

                const add = ()=>{
                    // push 添加元素到数组末尾
                    data.list.push(data.text)
                }

                const del = (index)=>{
                    // 删除数组元素 从索引index处开始 删除1个元素 也就是删除自己
                    data.list.splice(index,1)
                }

                const clear = ()=>{
                    //清空数组 直接置空数组
                    data.list = []
                }
                // 返回数据和方法
                return {
                    data,
                    add,
                    del,
                    clear
                }
            }
        }).mount('#app') //mount 挂载在id为app的元素上
    </script>

3. 购物车案例

实现一个简单的购物车案例,这里将会学到@change事件的使用

    <div id="app">
        <table>
            <thead>
                <tr>
                    <td><input type="checkbox" v-model="data.selected" @change="selectAll"></td>
                    <td>商品名称</td>
                    <td>单价</td>
                    <td>库存</td>
                    <td>数量</td>
                    <td>操作</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(value,index) in data.list">
                    <td><input type="checkbox" :value="value" v-model="data.checkList" @change="selectChange"></td>
                    <td>{{value.name}}</td>
                    <td>{{value.price}}</td>
                    <td>{{value.stock}}</td>
                    <td>
                        <button @click="addNum(value)">+</button>
                        {{ value.num }}
                        <button @click="subNum(value)">-</button>
                    </td>
                    <td>
                        <button @click="deleteItem(index,value.id)">删除</button>
                    </td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td>合计{{ totalPrice() }}</td>
                </tr>
            </tfoot>
        </table>
    </div>

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

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

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data = reactive({
                    selected: false,
                    checkList: [],
                    list: [
                        {
                            id: 1,
                            name: "铅笔",
                            price: 3,
                            stock: 5,
                            num: 2
                        },
                        {
                            id: 2,
                            name: "橡皮",
                            price: 2,
                            stock: 4,
                            num: 1
                        },
                        {
                            id: 3,
                            name: "作业本",
                            price: 8,
                            stock: 7,
                            num: 1
                        }
                    ]
                })

                // 实现全选
                const selectAll = () => {
                    if (data.selected) {
                        data.checkList = data.list
                    } else {
                        data.checkList = []
                    }
                }

                // 单个选择变化
                const selectChange = () => {
                    if (data.checkList.length == data.list.length && data.list.length != 0) {
                        data.selected = true
                    } else {
                        data.selected = false
                    }
                }

                // 实现加减数量
                const addNum = (value) => {
                    if (value.stock > 0) {
                        value.num++
                        value.stock--
                    }
                }

                // 实现减数量
                const subNum = (value) => {
                    if (value.num > 0) {
                        value.num--
                        value.stock++
                    }
                }

                // 实现删除商品
                const deleteItem = (index, id) => {
                    data.list.splice(index, 1) // 从data.list中删除指定索引的商品

                    // 删除list中商品的同时,过滤掉checkList中对应的商品
                    let newArr = data.checkList.filter((value, index) => {
                        // value 和 index 分别代表 data.checkList 数组中的每一个元素及其对应的索引。
                        // value 是 data.checkList 数组中的每一个商品对象。
                        // index 是这个商品对象在 data.checkList 数组中的索引位置。

                        // 遍历checkList,保留所有id不等于传入id的商品
                        return value.id !== id
                    })
                    data.checkList = newArr // 更新data.checkList为过滤后的新数组
                    selectChange() // 调用selectChange函数,可能用于更新界面或其他逻辑处理
                }


                // 统计合计价格
                const totalPrice = () => {
                    let sum = 0;
                    console.log(data.checkList.length)
                    for (let i = 0; i < data.checkList.length; i++) {
                        sum += data.checkList[i].price * data.checkList[i].num
                    }
                    return sum;
                }

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

4. 购物车优化案例

使用watch监听来替代@change事件,computed计算属性替代计算方法

    <div id="app">
        <table>
            <thead>
                <tr>
                    <td><input type="checkbox" v-model="data.selected"></td>
                    <td>商品名称</td>
                    <td>单价</td>
                    <td>库存</td>
                    <td>数量</td>
                    <td>操作</td>
                </tr>
            </thead>
            <tbody>
                <tr v-for="(value,index) in data.list">
                    <td><input type="checkbox" :value="value" v-model="data.checkList"></td>
                    <td>{{value.name}}</td>
                    <td>{{value.price}}</td>
                    <td>{{value.stock}}</td>
                    <td>
                        <button @click="addNum(value)">+</button>
                        {{ value.num }}
                        <button @click="subNum(value)">-</button>
                    </td>
                    <td>
                        <button @click="deleteItem(index,value.id)">删除</button>
                    </td>
                </tr>
            </tbody>
            <tfoot>
                <tr>
                    <td>合计{{ totalPrice }}</td>
                </tr>
            </tfoot>
        </table>
    </div>

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

        // 模块化开发Vue
        // 使用watch监听复选框   使用computed计算totalPrice
        import { createApp, reactive, watch, computed } from './vue.esm-browser.js'

        createApp({
            //setup选项 用于设置响应式数据和方法
            setup() {
                const data = reactive({
                    selected: false,
                    checkList: [],
                    list: [
                        {
                            id: 1,
                            name: "铅笔",
                            price: 3,
                            stock: 5,
                            num: 2
                        },
                        {
                            id: 2,
                            name: "橡皮",
                            price: 2,
                            stock: 4,
                            num: 1
                        },
                        {
                            id: 3,
                            name: "作业本",
                            price: 8,
                            stock: 7,
                            num: 1
                        }
                    ]
                })

                let flag = true
                // 监听复选框
                watch(() => data.selected, (newValue, oldValue) => {
                    if (newValue) {
                        data.checkList = data.list
                    } else {
                        if (flag) data.checkList = []
                    }
                })

                watch(() => data.checkList, (newValue, oldValue) => {
                    if (newValue.length == data.list.length && data.list.length != 0) {
                        data.selected = true
                        flag = true
                    } else {
                        data.selected = false
                        flag = false
                    }
                })

                // 实现加减数量
                const addNum = (value) => {
                    if (value.stock > 0) {
                        value.num++
                        value.stock--
                    }
                }

                // 实现减数量
                const subNum = (value) => {
                    if (value.num > 0) {
                        value.num--
                        value.stock++
                    }
                }

                // 实现删除商品
                const deleteItem = (index, id) => {
                    data.list.splice(index, 1) // 从data.list中删除指定索引的商品

                    // 删除list中商品的同时,过滤掉checkList中对应的商品
                    let newArr = data.checkList.filter((value, index) => {
                        // value 和 index 分别代表 data.checkList 数组中的每一个元素及其对应的索引。
                        // value 是 data.checkList 数组中的每一个商品对象。
                        // index 是这个商品对象在 data.checkList 数组中的索引位置。

                        // 遍历checkList,保留所有id不等于传入id的商品
                        return value.id !== id
                    })
                    data.checkList = newArr // 更新data.checkList为过滤后的新数组
                }


                // 统计合计价格
                const totalPrice = computed(() => {
                    /*
                        reduce定义: 用于对数组中的所有元素进行迭代操作, 并将每次操作的结果累加到一个初始值上
                        reduce接收两个参数: 一个是累加器函数, 另一个是初始值
                        reduce: 将 data.checkList 数组中的每个 checkbox 对象的 price 和 num 属性进行相乘, 
                        并将结果累加到初始值 0 上, 最后返回累加的结果

                        total(累加器) 用于存储每次计算的结果, 初始值为 0
                        item(当前元素) 在每次迭代过程中, 当前元素的值会被传递给回调函数
                    */
                    return data.checkList.reduce((total, item) => total + item.num * item.price, 0)
                })


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

5. 使用Axios实现文章搜索案例

    <div id="app">
        搜索类型
        <select v-model="data.type">
            <option value="">请选择搜索类型</option>
            <option value="1">ID</option>
            <option value="2">内容</option>
        </select>
        搜索内容
        <input type="text" v-model="data.content" />
        <button @click="search">搜索</button>

        <ul>
            <li v-for="value in data.list">{{ value }}</li>
        </ul>

    </div>

    <script type="module">
        import { createApp, reactive } from './vue.esm-browser.js'

        createApp({
            setup() {
                const data = reactive({
                    //搜索类型
                    type:"1",
                    //搜索输入内容
                    content:"",
                    //存储返回结果
                    list:[]
                })

                //搜索方法
                const search = ()=>{

                    //每次搜索前清空列表
                    data.list = []

                    // 根据id搜索
                    if(data.type=="1"){
                        axios.get(`http://127.0.0.1/article/get/id/${data.content}`).then(res=>{
                            data.list.push(res.data.data)
                        }).catch(err=>{
                            console.log(err)
                        })
                    // 根据内容搜索
                    }else if(data.type=="2"){
                        let params = {
                            title:data.content
                        }
                        axios.post("http://127.0.0.1/article/postJson/search",params).then(res=>{
                            for(let i =0;i<res.data.data.length;i++){
                                data.list.push(res.data.data[i])
                            }
                        }).catch(err=>{
                            console.log(err)
                        })
                    }
                }

                return {
                    data,
                    search
                }
            }
        }).mount("#app")
    </script>