Vue3+TS系统学习八 - 组件化知识补充(下)

简介: 组件化知识补充(下)

三. 模块引用


3.1. $refs


某些情况下,我们在组件中想要直接获取到元素对象或者子组件实例:

  • 在Vue开发中我们是不推荐进行DOM操作的;
  • 这个时候,我们可以给元素或者组件绑定一个ref的attribute属性;

组件实例有一个$refs属性:

  • 它一个对象Object,持有注册过 ref attribute 的所有 DOM 元素和组件实例。

App.vue的实现:

<template>
  <div>
    <h2 ref="title">哈哈哈</h2>
    <hello-world ref="helloCpn"></hello-world>
    <button @click="visitElement">访问元素或者组件</button>
  </div>
</template>
<script>
  import HelloWorld from './HelloWorld.vue';
  export default {
    components: {
      HelloWorld
    },
    methods: {
      visitElement() {
        // 访问元素
        console.log(this.$refs.title);
        // 访问组件实例
        this.$refs.helloCpn.showMessage();
      }
    }
  }
</script>

HelloWorld.vue实现:

<template>
  <div>
  </div>
</template>
<script>
  export default {
    methods: {
      showMessage() {
        console.log("我是HelloWorld组件的showMessage方法");
      }
    }
  }
</script>


3.2. $parent


我们可以通过$parent来访问父元素。

HelloWorld.vue的实现:

  • 这里我们也可以通过$root来实现,因为App是我们的根组件;
<template>
  <div>
    <button @click="visitParent">访问父组件</button>
  </div>
</template>
<script>
  export default {
    methods: {
      showMessage() {
        console.log("我是HelloWorld组件的showMessage方法");
      },
      visitParent() {
        console.log(this.$parent.message);
      }
    }
  }
</script>

注意:在Vue3中已经移除了$children的属性,所以不可以使用了。


四. 生命周期


4.1. 生命周期图片


什么是生命周期呢?

  • 每个组件都会经历从创建、挂载、更新、卸载等一系列的过程;
  • 在这个过程中的某一个阶段,用于可能会想要添加一些属于自己的代码逻辑(比如组件创建完后就请求一些服务器数据);
  • 但是我们如何可以知道目前组件正在哪一个过程呢?Vue给我们提供了组件的生命周期函数;

生命周期函数:

  • 生命周期函数是一些钩子函数,在某个时间会被Vue源码内部进行回调;
  • 通过对生命周期函数的回调,我们可以知道目前组件正在经历什么阶段;
  • 那么我们就可以在该生命周期中编写属于自己的逻辑代码了;

image.png                                                实例的生命周期


4.2. 生命周期演练


我们通过一个App和Home来演练所有的生命周期函数。

App.vue组件对象:

<template>
  <div>
    <button @click="toggle">切换</button>
    <div v-if="isShow">
      <home></home>
    </div>
  </div>
</template>
<script>
  import Home from './Home.vue';
  export default {
    components: {
      Home
    },
    data() {
      return {
        isShow: true
      }
    },
    methods: {
      toggle() {
        this.isShow = !this.isShow;
        console.log(this.isShow);
      }
    }
  }
</script>

Home.vue组件对象:

<template>
  <div>
    <button @click="changeMessage">修改message</button>
    <h2 ref="titleRef">{{message}}</h2>
  </div>
</template>
<script>
  export default {
    data() {
      return {
        message: "Hello World"
      }
    },
    methods: {
      changeMessage() {
        this.message = "你好啊,李银河";
      }
    },
    beforeUpdate() {
      console.log("beforeUpdate");
      console.log(this.$refs.titleRef.innerHTML);
    },
    updated() {
      console.log("updated");
      console.log(this.$refs.titleRef.innerHTML);
    },
    beforeCreate() {
      console.log("beforeCreate");
    },
    created() {
      console.log("created");
    },
    beforeMount() {
      console.log("beforeMount");
    },
    mounted() {
      console.log("mounted");
    },
    beforeUnmount() {
      console.log("beforeUnmount");
    },
    unmounted() {
      console.log("unmounted");
    }
  }
</script>


五. 组件的v-model


5.1. 组件的v-model


前面我们在input中可以使用v-model来完成双向绑定:

  • 这个时候往往会非常方便,因为v-model默认帮助我们完成了两件事;
  • v-bind:value的数据绑定和@input的事件监听;

如果我们现在封装了一个组件,其他地方在使用这个组件时,是否也可以使用v-model来同时完成这两个功能呢?

  • 也是可以的,vue也支持在组件上使用v-model;

当我们在组件上使用的时候,等价于如下的操作:

  • 我们会发现和input元素不同的只是属性的名称和事件触发的名称而已;

image.png

那么,为了我们的MyInput组件可以正常的工作,这个组件内的 <input> 必须:

  • 将其 value attribute 绑定到一个名叫 modelValue 的 prop 上;
  • 在其 input 事件被触发时,将新的值通过自定义的 update:modelValue 事件抛出;

MyInput.vue的组件代码如下:

<template>
  <div>
    <input :value="modelValue" @input="inputChange">
  </div>
</template>
<script>
  export default {
    props: ["modelValue"],
    emits: ["update:modelValue"],
    methods: {
      inputChange(event) {
        this.$emit("update:modelValue", event.target.value);
      }
    }
  }
</script>

在App.vue中,我们在使用MyInput可以直接使用v-model:

<template>
  <div>
    <my-input v-model="message"/>
    <button @click="changeMessage">修改message</button>
  </div>
</template>
<script>
  import MyInput from './MyInput.vue';
  export default {
    components: {
      MyInput
    },
    data() {
      return {
        message: ""
      }
    },
    methods: {
      changeMessage() {
        this.message = "Hello World"
      }
    }
  }
</script>


5.2. computed实现


在上面的案例中,我们可能会想到一种实现方法:直接将Props中的属性双向绑定到input上

<template>
  <div>
    <input v-model="modelValue">
  </div>
</template>
<script>
  export default {
    props: ["modelValue"]
  }
</script>

上面这种方式可以实现组件的双向绑定吗?答案是不可以

  • 因为我们在内部修改了props之后,外界并不知道我们对props的修改,所以并不会将事件传递出去;
  • 另外,在开发中直接修改props中的属性不是一个好的习惯,不要这样去做;

那么,我们依然希望在组件内部按照双向绑定的做法去完成,应该如何操作呢?我们可以使用计算属性的settergetter来完成。

<template>
  <div>
    <input v-model="value">
  </div>
</template>
<script>
  export default {
    props: ["modelValue"],
    emits: ["update:modelValue"],
    computed: {
      value: {
        get() {
          return this.modelValue;
        },
        set(value) {
          this.$emit("update:modelValue", value)
        }
      }
    }
  }
</script>


5.3. 绑定多个属性


我们现在通过v-model是直接绑定了一个属性,如果我们希望绑定多个属性呢?也就是我们希望在一个组件上使用多个v-model是否可以实现呢?

  • 我们知道,默认情况下的v-model其实是绑定了 modelValue 属性和 @update:modelValue的事件;
  • 如果我们希望绑定更多,可以给v-model传入一个参数,那么这个参数的名称就是我们绑定属性的名称;

我们先看一下在App.vue中我是如何使用的:

<template>
  <div>
    <my-input v-model="message" v-model:title="title"/>
    <h2>{{message}}</h2>
    <button @click="changeMessage">修改message</button>
    <hr>
    <h2>{{title}}</h2>
    <button @click="changeTitle">修改title</button>
  </div>
</template>
<script>
  import MyInput from './MyInput.vue';
  export default {
    components: {
      MyInput
    },
    data() {
      return {
        message: "",
        title: ""
      }
    },
    methods: {
      changeMessage() {
        this.message = "Hello World"
      },
      changeTitle() {
        this.title = "Hello Title"
      }
    }
  }
</script>

注意:这里我是绑定了两个属性的

<my-input v-model="message" v-model:title="title"/>

v-model:title相当于做了两件事:

  • 绑定了title属性;
  • 监听了 @update:title的事件;

所以,我们MyInput中的实现如下:

<template>
  <div>
    <input :value="modelValue" @input="input1Change">
    <input :value="title" @input="input2Change">
  </div>
</template>
<script>
  export default {
    props: ["modelValue", "title"],
    emits: ["update:modelValue", "update:title"],
    methods: {
      input1Change(event) {
        this.$emit("update:modelValue", event.target.value);
      },
      input2Change(event) {
        this.$emit("update:title", event.target.value);
      }
    }
  }
</script>
相关文章
|
2月前
|
缓存 JavaScript UED
Vue3中v-model在处理自定义组件双向数据绑定时有哪些注意事项?
在使用`v-model`处理自定义组件双向数据绑定时,要仔细考虑各种因素,确保数据的准确传递和更新,同时提供良好的用户体验和代码可维护性。通过合理的设计和注意事项的遵循,能够更好地发挥`v-model`的优势,实现高效的双向数据绑定效果。
154 64
|
2月前
|
JavaScript 前端开发 API
Vue 3 中 v-model 与 Vue 2 中 v-model 的区别是什么?
总的来说,Vue 3 中的 `v-model` 在灵活性、与组合式 API 的结合、对自定义组件的支持等方面都有了明显的提升和改进,使其更适应现代前端开发的需求和趋势。但需要注意的是,在迁移过程中可能需要对一些代码进行调整和适配。
124 60
|
17天前
|
JavaScript API 数据处理
vue3使用pinia中的actions,需要调用接口的话
通过上述步骤,您可以在Vue 3中使用Pinia和actions来管理状态并调用API接口。Pinia的简洁设计使得状态管理和异步操作更加直观和易于维护。无论是安装配置、创建Store还是在组件中使用Store,都能轻松实现高效的状态管理和数据处理。
67 3
|
2月前
|
前端开发 JavaScript 测试技术
Vue3中v-model在处理自定义组件双向数据绑定时,如何避免循环引用?
Web 组件化是一种有效的开发方法,可以提高项目的质量、效率和可维护性。在实际项目中,要结合项目的具体情况,合理应用 Web 组件化的理念和技术,实现项目的成功实施和交付。通过不断地探索和实践,将 Web 组件化的优势充分发挥出来,为前端开发领域的发展做出贡献。
45 8
|
2月前
|
存储 JavaScript 数据管理
除了provide/inject,Vue3中还有哪些方式可以避免v-model的循环引用?
需要注意的是,在实际开发中,应根据具体的项目需求和组件结构来选择合适的方式来避免`v-model`的循环引用。同时,要综合考虑代码的可读性、可维护性和性能等因素,以确保系统的稳定和高效运行。
41 1
|
2月前
|
JavaScript
Vue3中使用provide/inject来避免v-model的循环引用
`provide`和`inject`是 Vue 3 中非常有用的特性,在处理一些复杂的组件间通信问题时,可以提供一种灵活的解决方案。通过合理使用它们,可以帮助我们更好地避免`v-model`的循环引用问题,提高代码的质量和可维护性。
49 1
|
2月前
|
JavaScript
在 Vue 3 中,如何使用 v-model 来处理自定义组件的双向数据绑定?
需要注意的是,在实际开发中,根据具体的业务需求和组件设计,可能需要对上述步骤进行适当的调整和优化,以确保双向数据绑定的正确性和稳定性。同时,深入理解 Vue 3 的响应式机制和组件通信原理,将有助于更好地运用 `v-model` 实现自定义组件的双向数据绑定。
|
11天前
|
JavaScript
vue使用iconfont图标
vue使用iconfont图标
75 1
|
22天前
|
JavaScript 关系型数据库 MySQL
基于VUE的校园二手交易平台系统设计与实现毕业设计论文模板
基于Vue的校园二手交易平台是一款专为校园用户设计的在线交易系统,提供简洁高效、安全可靠的二手商品买卖环境。平台利用Vue框架的响应式数据绑定和组件化特性,实现用户友好的界面,方便商品浏览、发布与管理。该系统采用Node.js、MySQL及B/S架构,确保稳定性和多功能模块设计,涵盖管理员和用户功能模块,促进物品循环使用,降低开销,提升环保意识,助力绿色校园文化建设。
|
2月前
|
JavaScript 前端开发 开发者
vue学习第一章
欢迎来到我的博客!我是瑞雨溪,一名热爱前端的大一学生,专注于JavaScript与Vue,正向全栈进发。博客分享Vue学习心得、命令式与声明式编程对比、列表展示及计数器案例等。关注我,持续更新中!🎉🎉🎉
52 1
vue学习第一章