Vue.js学习笔记 06、Vue3新特性

举报
长路 发表于 2022/11/28 21:52:18 2022/11/28
【摘要】 文章目录前言Composition API(基于函数组合)一、setup()函数(Composition API的入口)二、ref与reactive函数使用2.1、ref与reactive引用方式与原理2.2、toRefs与toRef使用(让reactive包装的引用类型解构后响应依然生效)2.3、context属性介绍与使用(attrs、emit、slots)三、computed函数(Conte

@[toc]

前言

本篇博客是在学习技术胖-Vue3.x从零开始学-第一季 基础语法篇过程中记录整理的笔记,若文章中出现相关问题,请指出!

  • 当前该链接失效了,有需要的小伙伴可以去b站或者技术胖官网去找相应的视频与笔记。

所有博客文件目录索引:博客目录索引(持续更新)

Composition API(基于函数组合)

在VUE2中,对于data数据、methods、生命周期都写在一个对象中这就显得十分臃肿。因为每个功能模块的代码会散落分布在各个位置,让整个项目的内容难以阅读和维护。这也导致我们需要考虑用其他方式来维护代码,比如Vuex。

Vue3,它会根据逻辑功能来进行组织,把同一个功能的不同代码都放在一起,或者把它们单独拿出来放在一个函数中,所以Composition API又被称为基于函数组合的API。



一、setup()函数(Composition API的入口)

setup():是vue3中新增的一个生命周期函数,在beforeCreate之前调用,此时组件的data和methods还没有初始化,因此在setup中是不能使用this的,并且对于setup使用只能是同步的。

注意点:在setup()内部是不能够使用this的,外部的话可以使用this来调用setup中返回的属性。

效果:能够将对象中的属性与方法等添加到Vue的实例中。

示例:

<body>
    <div id="app"></div>

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

        const app = Vue.createApp({
            // 1、setup()函数使用
            // props:外部组件传递过来的一些内容;context:上下文。
            setup(props, context) {
                console.log("setup的props=>", props);
                console.log("setup的context=>", context);
                console.log(this);//由于在beforeCreate之前调用,所有this执行Window对象
                return {
                    name: 'changlu',
                    handleClick: () => {
                        alert(123);
                    }
                }
            },
            beforeCreate() {
                console.log("beforeCreate的this=>", this);
                console.log("beforeCreate的this.$options=>", this.$options);//可以看到在$options对象中包含setup属性
            },
            template: `
                <div @click="handleClick">{{name}}</div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

image-20210725105433720

image-20210725105525203



二、ref与reactive函数使用

2.1、ref与reactive引用方式与原理

refreactive指的是什么?

  • 是在Vue3中提供给我们的函数,可通过Vue类来获取到函数。

目的:在setup()生命周期中使用refreactive函数包装的基本类型或引用类型能够变为一个响应式的引用,从而实现双向绑定!

核心点

  1. 外界不能直接修改内部值,只能够通过调用setup暴露出来的方法来进行修改。
  2. 外界拿到setup()返回的值或对象:this.xxx即可拿取。
  3. 外界调用setup()中的方法:this.xxx()即可。
  4. 外界想要绑定值到dom元素上:与绑定基本的data对象属性相同
    • ref引用:{{xxx}}即可,可直接省略掉xxx.value
    • reactive引用:{{obj.xxx}}即可。

示例:包含ref、reactive定义与使用

<body>
    <div id="app"></div>

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

        // console.log(Vue);  //Vue类中包含了ref、reactive函数

        const app = Vue.createApp({
            setup() {
                const { ref, reactive } = Vue;//从Vue中拿到ref、reactive函数
                // 1.1、ref=>处理基本类型,底层封装为proxy({value: 'changlu'})
                let name = ref("changlu");
                function modName(newName) {
                    name.value = newName;
                }
                // 1.2、reactive=>处理引用类型,底层封装为proxy({age: 18})
                let obj = reactive({ age: 18 });
                function modObjAge(newAge) {
                    obj.age = newAge
                }
                // 定义函数
                const change = () => console.log("change()....");
                console.log(name, obj);
                return { name, obj, change, modName, modObjAge }
            },
            methods: {
                // 外界使用setup()中定义的属性与方法
                handleClick() {
                    this.change();//调用setup()中方法
                    console.log(this.name);//调用ref引用的基本类型
                    console.log(this.obj.age);//调用reactive包装的引用类型
                }
            },
            // 对于ref包装后的值:想要拿到应该name.value才拿到,不过这里可以省略.value,对于ref类型可以直接name拿取
            // 对于reactive包装的以及函数方法:可以直接使用
            template: `
                <div>{{name}}</div>
                <div>{{obj.age}}</div>
                <button @click="handleClick">点我触发方法</button>
                <button @click="modName('liner')">点我修改name</button>
                <button @click="modObjAge(20)">点我触发方法</button>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>



2.2、toRefs与toRef使用(让reactive包装的引用类型解构后响应依然生效)

toRefs函数

当我们在setup()生命周期中使用reactive()来创建引用对象类型时,我们只想将其中的某个属性暴露出去,首先的思路就是通过解构赋值的方式拿到其中的属性暴露出去。

问题描述:若是仅仅使用解构赋值拿到的属性返回出去,此时若是引用对象的属性发生改变就不会有响应的效果!

原理:关注下面的正确方式

const { ref, reactive, toRefs } = Vue;
//对于obj直接进行解构赋值:没有响应的效果!
const obj = reactive({name:"changlu"});//obj: Proxy({name:"chaglu"})
let {name} = obj;//若是直接进行解构赋值 此时name="changlu",仅仅就只是拿到值,之后若是对obj.name进行修改,外界就不会响应,因为该name仅仅就只是一个字符串而已
return name;

//正确方式:使用toRefs()来完成引用类型解构
const obj = reactive({name:"changlu"});
let {name} = toRefs(obj);//核心:使用toRefs来进行包装=>  name:proxy({value: 'changlu'}),此时底层就会默认将该单个值转为ref包装的对象,此时返回出现就能够响应了
return name;

示例

<body>
    <div id="app"></div>

    <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script>
    <script>
        const app = Vue.createApp({
            setup() {
                const { ref, reactive, toRefs } = Vue;
                let obj = reactive({ name: "changlu", age: 18 });
                //let { name, age } = obj;  //这种形式解构赋值仅仅是将值的绑定到了对应的name与age上,不会有响应效果
                let { name, age } = toRefs(obj);
                // 定时2秒动态修改
                setTimeout(() => {
                    obj.name = "liner";
                    obj.age = 10;
                }, 2000);
                return { name, age };
            },
            template: `
                <div>{{name}}</div>
                <div>{{age}}</div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

toRef()

方式let age = toRef(obj, 'age');,注意这里需要写两个参数,意思是从obj对象中拿到名为age的属性,若是拿不到就赋值一个空,之后若是age值改变依旧会生效!

<body>
    <div id="app"></div>

    <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script>
    <script>
        const app = Vue.createApp({
            setup() {
                const { ref, reactive, toRefs, toRef } = Vue;
                let obj = reactive({ name: "changlu" });
                //toRef()形式
                let age = toRef(obj, 'age');//从obj对象中取age这个属性,若是不能取到则给它一个空依旧能够响应数据
                // 定时2秒动态修改
                setTimeout(() => {
                    age.value = 10;//需要对age对象来进行数据操作
                }, 2000);
                return { age };
            },
            template: `
                <div>{{age}}</div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

GIF

两者区别:使用方式不同,toRef()需要去指定拿属性,并且若是没有取到属性会默认赋值给一个null值,之后若是赋值依旧会响应更新到dom元素上;而对于toRefs()则会报错并且不会生效。



2.3、context属性介绍与使用(attrs、emit、slots)

介绍

这里介绍的是setup()生命周期函数中的参数context。在Context对象中包含三个比较常用属性分别是attrsemitslots,分别作用是拿到父组件传递的属性、内部组件向外调用执行父组件方法以及插槽。

image-20210725152434790


使用

通过从context拿到对应的三个对象实际上与之前使用$attrs$emit$slots都大差不差,效果都是相同,通过在Context对象中拿到并使用:

示例

<body>
    <div id="app"></div>

    <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script>
    <script>
        const app = Vue.createApp({
            setup(props, context) {
                console.log(context);
                //父组件方法
                const handleChange = () => console.log("执行父组件方法");
                return { handleChange };
            },
            template: `
                <cl-item name="changlu" @change="handleChange">
                    I am ChangLu.
                </cl-item>
            `
        });

        app.component('cl-item', {
            setup(props, context) {
                const { attrs, emit, slots } = context;
                // 1、attrs使用:获取父组件传递属性
                console.log("attrs=>", attrs.name);
                // 2、emit使用:向父组件发出执行指令
                function handleClickInCL() {
                    emit("change");//向外传递,配合@change="handleClick"
                }
                // 3、slots使用:获取父组件中使用子组件里的内容
                const myslots = slots.default()[0].children;
                console.log("slots.default()[0].children=>", myslots);
                return { myslots, handleClickInCL };
            },
            // 测试单击事件是否向外传递以及获取父组件传递的插槽内容
            template: `
                <div>
                    <button @click="handleClickInCL">点我一下</button>
                    <div>{{myslots}}</div>
                </div>
            `
        })

        const vm = app.mount("#app");
    </script>
</body>

GIF



三、computed函数(Context实例中获取,计算属性)

3.1、computed参数为箭头函数

语法

const {computed} = Vue;
let computedNum = computed(()=>{
    return xxx;   //只要其中的值与属性相关联,该属性一旦改变就会调用计算函数重新执行
});

示例

<body>
    <div id="app"></div>

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

        const app = Vue.createApp({
            setup() {
                // 1、获取计算函数
                const { ref, computed } = Vue;
                const num = ref(0);
                // 2、编写计算函数(只要num.value发生改变,该计算函数就会重新计算返回)
                let addFive = computed(() => {
                    return num.value + 5;
                });

                setTimeout(() => {
                    num.value = 10; //设置一个延时器来更新num的值,来看2秒后,计算属性是否重新计算
                }, 2000);

                return { num, addFive };
            },
            // 3、对于计算函数,我们可以直接看做一个属性(其返回值为一个值)
            template: `
                <div>
                    <span>{{num}}--{{addFive}}</span>
                    <span>{{name}}</span>
                </div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

GIF



3.2、computed函数设置set、get方法

在computed函数可以设置set、get方法,在对computed函数重新赋值或者取值时都会触发!

  • set触发:对computed函数变量赋值即可触发set以及get方法。
  • get触发:将computed函数作为值在标签里响应时就会执行get()拿取,同时只要与其相关联的值更新也会触发。

示例

<body>
    <div id="app"></div>


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

        const app = Vue.createApp({
            setup() {
                // 1、获取计算函数
                const { reactive, computed } = Vue;
                const obj = reactive({ num: 5 });
                // 计算函数:添加get、set方法
                // addFive=>底层是ref包装
                let addFive = computed({
                    get: () => {
                        return obj.num + 5;
                    },
                    set: (param) => {
                        obj.num = param;
                    }
                });

                setTimeout(() => {
                    // 由于底层是ref包装,所以调用xxx.value才能修改值
                    addFive.value = 100;//即可触发set(),并传入参数。(触发set之后,由于对obj.num重新赋值就会触发get)
                }, 2000);

                return { obj, addFive };
            },
            template: `
                <div>
                    <span>{{obj.num}}--{{addFive}}</span>
                </div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

GIF



四、watch和watchEffect函数(监听函数)

4.1、watch函数使用(指定ref、reactive属性监控及多个同时监控)

介绍

watch函数:通过从context对象中拿取,可以对单个值或者多个值(数组)形式来进行监听,是惰性的(当监听的值发生修改时才会触发)。

语法watch(监控属性,(currentval,preval)=>{}),回调函数第一个是现有值,第二个是之前值。

注意点

  1. 对于ref包装的基本类型,第一个参数直接设置其值即可
  2. 对于reactive包装的引用类型想对其某个属性监控,第一个参数需要设置为一个函数返回才可生效,如watch(()=>obje.name,()=>{})
  3. 若是想要监控多个值,第一个参数写为数组形式如[()=>属性1,()=>属性2],第二个参数函数回调函数的参数要写成数组形式如([属性1现有值,属性2现有值],[属性1改变前值,属性2改变前值])=>{}

示例

1、针对于ref类型

注意点:对于ref基本类型,监控的值可以直接添加一个变量。

const app = Vue.createApp({
    setup() {
        const { watch, ref } = Vue;
        const num = ref('');
        // 1、针对于ref基本类型:具有惰性,对num值进行监控
        watch(num, (curval, preval) => {  
            console.log(curval, preval);
        });
        return { num };
    },
    template: `
        <div>
            <input v-model="num" />
        </div>
    `
});

GIF

2、监控reactive包装对象的某个属性

说明:这里监控对象中的两个属性

示例:对reactive包装对象的两个属性进行监控,并且实时打印值

<body>
    <div id="app"></div>


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

        const app = Vue.createApp({
            setup() {
                const { watch, reactive, toRefs } = Vue;
                const obj = reactive({ name: "changlu", age: 18 });

                // 监控reactive包装对象的属性,需要使用函数形式返回
                // 若是监控多个属性,需要写成数组形式,并且回调函数也写成数组形式
                watch([() => obj.name, () => obj.age], ([curval1, curlval2], [preval1, preval2]) => {
                    console.log("name当前与之前值=>", curval1, preval1);
                    console.log("age当前与之前值=>", curlval2, preval2);
                });

                // 解构导出指定的属性(使用toRefs保证具有相应效果)
                let { name, age } = toRefs(obj);
                return { name, age };
            },
            template: `
                <div>
                    name:<input v-model="name" />
                    age: <input v-model="age" />
                </div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

GIF



4.2、watchEffect函数(无指定监控属性,自动感知内部)

watchEffect函数:不需要指定监控属性,其会自动感知内部的属性值是否有更新,一旦有更新就会执行。

语法watchEffect(()=>{}),会对回调函数内部的内容进行监控。

注意

  1. 立即执行,无惰性初始化会直接执行。
  2. 没有当前值与现有值在回调函数参数中获取。

示例

const { reactive, watchEffect } = Vue;
const obj = reactive({ name: "changlu", age: 18 });
//仅仅只需要写回调函数内部的代码体即可,监控内部参数
watchEffect(() => {
    console.log(obj.name);
    console.log(obj.age);
});

GIF

说明:可以看到页面加载初始化时默认就会执行该函数体,之后也会有监控效果!



4.3、停止监听(函数.stop()即可)

watch()函数停止:

//1、声明监听函数
const watch1 = watch(name,()=>{
    xxx
    //设置定时器后停止监听
    setTimeout(()=>{
        watch1();  //2、调用本身函数即可两秒后停止监听
    },2000);
});

watchEffect():停止方式与watch()函数一致,都是声明后调用自己本身声明函数即可。

示例:由于watchEffect是非惰性,上来就会执行所以5秒后就会默认停止监听

<body>
    <div id="app"></div>


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

        const app = Vue.createApp({
            setup() {
                const { watch, reactive, toRefs, watchEffect } = Vue;
                const obj = reactive({ name: "changlu", age: 18 });

                // 监控reactive包装对象的属性,需要使用函数形式返回
                // 若是监控多个属性,需要写成数组形式,并且回调函数也写成数组形式
                // watch(() => [obj.name, obj.age], ([curval1, curlval2], [preval1, preval2]) => {
                //     console.log("name当前与之前值=>", curval1, preval1);
                //     console.log("age当前与之前值=>", curlval2, preval2);
                // });


                const mywatchEff = watchEffect(() => {
                    console.log(obj.name);
                    console.log(obj.age);

                    // 5秒后停止监听
                    setTimeout(() => {
                        mywatchEff();//函数调用一下即可停止监听
                    }, 5000);
                });

                // 解构导出指定的属性(使用toRefs保证具有相应效果)
                let { name, age } = toRefs(obj);
                return { name, age };
            },
            template: `
                <div>
                    name:<input v-model="name" />
                    age: <input v-model="age" />
                </div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

GIF

说明:初始是有效监听的,过了5秒就停止监听了。



4.4、设置watch()函数为非惰性(设置参数3 {immediate: true})

回顾一下,有惰性指的是只有当指定监控的属性发生改变才会被监控到,非惰性指的是初始化时默认会自动执行一次仅此而已。

方式:添加第三个参数配置对象中的immediatetrue

示例

<body>
    <div id="app"></div>


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

        const app = Vue.createApp({
            setup() {
                const { watch, reactive, toRefs, watchEffect } = Vue;
                const obj = reactive({ name: "changlu", age: 18 });

                watch([() => obj.name, () => obj.age], ([curval1, curlval2], [preval1, preval2]) => {
                    console.log("name当前与之前值=>", curval1, preval1);
                    console.log("age当前与之前值=>", curlval2, preval2);
                }, {
                    immediate: true   //立即属性
                });//核心:设置第三个参数为非惰性
            },
            template: `
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

image-20210725184645283



五、生命周期函数的新写法

介绍

在Composition API中,提供了生命周期函数的新写法,同样是从Vue类中获取到对应的生命周期函数:

image-20210725225244095

# 挂载前、后
beforeMount => onBeforeMount
mounted => onMounted
# 更新前、后
beforeUpdate => onBeforeUpdate
updated => onUpdated
# 失效前、后
beforeUnmount => onBeforeUnmount
unmounted => onUnmounted

//新的两个生命周期
onRenderTracked:每次渲染之后收集依赖时候自动执行的函数(第一次渲染就会执行)。
    页面每次渲染之后,vue会去收集响应式的依赖,一旦需要被重新收集的时候,该函数就会自动的执行一下。
onRenderTriggered:每次重新渲染被触发的时候。(第一次渲染不会执行)

示例

说明:我们来通过在setup函数中编写调用生命周期函数来进行测试。

<body>
    <div id="app"></div>


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

        const app = Vue.createApp({
            setup() {
                const { onBeforeMount, onMounted,
                    onBeforeUpdate, onUpdated,
                    onBeforeUnmount, onUnmounted,
                    onRenderTracked, onRenderTriggered
                } = Vue;
                // 挂载前、后
                onBeforeMount(() => {
                    console.log("onBeforeMount");
                });
                onMounted(() => {
                    console.log("onMounted");
                });
                //更新前、后
                onBeforeUpdate(() => {
                    console.log("onBeforeUpdate");
                });
                onUpdated(() => {
                    console.log("onUpdated");
                });
                //失效前、后
                onBeforeUnmount(() => {
                    console.log("onBeforeUnmount");
                });
                onUnmounted(() => {
                    console.log("onUnmounted");
                });
                //渲染之后收集依赖时
                onRenderTracked(() => {
                    console.log("onRenderTracked");
                });
                //重新被渲染之后触发
                onRenderTriggered(() => {
                    console.log("onRenderTriggered");
                });
                console.log(Vue);
                const { ref } = Vue;
                let say = ref("hello,world!");
                function handleClick() {
                    say.value = "hello,changlu!"
                }
                return { say, handleClick };
            },
            template: `
                <div @click="handleClick">{{say}}</div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

image-20210725230728194

image-20210725230900465



六、provide属性与inject属性配合使用

6.1、provide与inject取值与修改值(含示例)

provideinject在之前学习是用来父子组件中快速传递值的,其是单向流,子组件仅仅只能取值不能修改值。

  • 注意:在Compostition API中是可以对父组件传递来的provide修改值的,所以在设置provide传递时最好设置为readonly。

示例:使用provide与inject来让子组件使用父组件的属性与方法,在设置provide的name值时将其设置为readonly,防止子组件直接去修改值。

<body>
    <div id="app"></div>


    <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script>
    <script>
        //父组件
        const app = Vue.createApp({
            setup() {
                const { provide, ref, readonly } = Vue;
                const name = ref("changlu");
                // 1、设置provide键值对
                provide("name", readonly(name));//设置为readOnly,限制inject得到属性后修改
                // 提供给子组件一个函数方法,让其能够调用父组件方法来对name进行值的修改
                provide("changeName", (value) => {
                    name.value = value;
                })
                return {};
            },
            template: `
                <cl-item></cl-item>
            `
        });

        // 子组件
        app.component('cl-item', {
            setup() {
                const { inject } = Vue;
                // 2、通过inject拿取到,若是没有拿取到值,就会将参数2作为默认值
                let name = inject("name", "liner");
                const changeName = inject("changeName");
                // name.value = "tiantian";  //子组件不应该对父组件进行修改
                return { name, changeName };
            },
            template: `
                <div>{{name}}</div>
                <button @click="changeName('liner')">修改name</button>
            `
        })

        const vm = app.mount("#app");
    </script>
</body>

GIF



七、通过ref获取真实的Dom元素节点

大致流程:回顾之前获取dom元素是通过$refs.xxx形式拿取到的,在这里的话通过定义一个ref包装类型暴露出去,在指定的dom元素中设置ref=xxx,接着我们在setup()中定义onmounted()生命周期来获取到!

示例

<body>
    <div id="app"></div>


    <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script>
    <script>
        //父组件
        const app = Vue.createApp({
            setup() {
                const { ref, onMounted } = Vue;
                // 1、设置ref包装基本类型,传入null
                const divDom = ref(null);

                // 设置挂载后的生命周期函数
                // 4、在生命周期函数中(挂载后)拿取到指定dom元素中的值
                onMounted(() => {
                    console.log(divDom);
                    console.log(divDom.value);
                    // 最终拿到dom元素中的内容
                    console.log(divDom.value.textContent);
                })
                // 2、将该类型暴露出去
                return { divDom };
            },
            // 3、在指定的dom元素上设置ref键值对
            template: `
                <div ref="divDom">changluya</div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

image-20210725233650821



实际应用

1、todolist(包含增、删)

案例:将对应的各个模块部分内容抽离到一个函数进行返回,接着配合setup()实现todolist!

示例如下:其实对应input输入框直接使用v-model绑定即可,这里的话为了巩固学习就使用绑定监听事件。

<body>
    <div id="app"></div>
    
    <script src="https://unpkg.com/vue@3.1.5/dist/vue.global.js"></script>
    <script>
        // 列表值及列表相关操作
        const listRelativeEffect = () => {
            const { reactive } = Vue;
            const items = reactive([]);
            // 提交、删除
            const handleSubmit = (value) => {
                items.push(value);
            };
            const handleDel = (index) => {
                items.splice(index, 1);
            };
            return { items, handleSubmit, handleDel };
        };

        // 输入值及相关的内容绑定
        const inputRelativeEffect = () => {
            const { ref } = Vue;
            let inputvalue = ref("");
            // 输入函数
            const handleInput = (e) => {
                inputvalue.value = e.target.value;//对于ref包装的基本值需要使用xxx.value来设置
            }
            return { inputvalue, handleInput };
        };

        const app = Vue.createApp({
            setup() {
                let { inputvalue, handleInput } = inputRelativeEffect();
                let { items, handleSubmit, handleDel } = listRelativeEffect();
                return { inputvalue, items, handleInput, handleSubmit, handleDel };
            },
            template: `
                <div>
                    <input type="text" @input="handleInput" :value="inputvalue"/>
                    <button @click="()=>handleSubmit(inputvalue)">提交</button>
                    <ul>
                        <li v-for="(item,index) of items" :key="index">
                            {{item}}
                            <button @click="handleDel(index)">删除</button>
                        </li>
                    </ul>
                </div>
            `
        });

        const vm = app.mount("#app");
    </script>
</body>

GIF

【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。