Vue3视图渲染技术(2)

我是南城余!阿里云开发者平台专家博士证书获得者!

欢迎关注我的博客!一同成长!

一名从事运维开发的worker,记录分享学习。

专注于AI,运维开发,windows Linux 系统领域的分享!

本章节对应知识库

南城余 — Java全栈 · 语雀

本内容来自尚硅谷课程,此处在知识库做了个人理解
————————————————
在这里插入图片描述

6.4 双向绑定

单项绑定和双向绑定

  • 单向绑定: 响应式数据的变化会更新dom树,但是dom树上用户的操作造成的数据改变不会同步更新到响应式数据
  • 双向绑定: 响应式数据的变化会更新dom树,但是dom树上用户的操作造成的数据改变会同步更新到响应式数据
    • 用户通过表单标签才能够输入数据,所以双向绑定都是应用到表单标签上的,其他标签不行
    • v-model专门用于双向绑定表单标签的value属性,语法为 v-model:value='',可以简写为 v-model=''
    • v-model还可以用于各种不同类型的输入,<textarea><select> 元素。
<script type="module" setup>//引入模块import { reactive,ref} from 'vue' let hbs = ref([]); //装爱好的值let user = reactive({username:null,password:null,introduce:null,pro:null})   function login(){alert(hbs.value);alert(JSON.stringify(user));}function clearx(){//user = {};// 这中写法会将数据变成非响应的,应该是user.username=""user.username=''user.password=''user.introduce=''user.pro=''hbs.value.splice(0,hbs.value.length);;}
</script><template><div>账号: <input type="text" placeholder="请输入账号!" v-model="user.username"> <br>密码: <input type="text" placeholder="请输入账号!" v-model="user.password"> <br>爱好: 吃 <input type="checkbox" name="hbs" v-model="hbs" value=""><input type="checkbox" name="hbs" v-model="hbs" value=""><input type="checkbox" name="hbs" v-model="hbs" value=""><input type="checkbox" name="hbs" v-model="hbs" value=""><br>简介:<textarea v-model="user.introduce"></textarea><br>籍贯:<select v-model="user.pro"><option value="1"></option><option value="2"></option><option value="3"></option><option value="4"></option><option value="5"></option><option value="6"></option></select> <br><button @click="login()">登录</button> <button @click="clearx()">重置</button><hr>显示爱好:{{ hbs }}<hr>显示用户信息:{{ user }}</div> 
</template> <style scoped>
</style>

6.5 属性计算

模板中的表达式虽然方便,但也只能用来做简单的操作。如果在模板中写太多逻辑,会让模板变得臃肿,难以维护。比如说,我们有这样一个包含嵌套数组的对象:

<script type="module" setup>//引入模块import { reactive,computed} from 'vue'const author = reactive({name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']})</script><template><div><p>{{author.name}} Has published books?:</p><span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span></div>
</template> <style scoped>
</style>
  • 这里的模板看起来有些复杂。我们必须认真看好一会儿才能明白它的计算依赖于 author.books。更重要的是,如果在模板中需要不止一次这样的计算,我们可不想将这样的代码在模板里重复好多遍。

因此我们推荐使用计算属性来描述依赖响应式状态的复杂逻辑。这是重构后的示例:

<script type="module" setup>//引入模块import { reactive,computed} from 'vue'const author = reactive({name: 'John Doe',books: ['Vue 2 - Advanced Guide','Vue 3 - Basic Guide','Vue 4 - The Mystery']})// 一个计算属性 refconst publishedBooksMessage = computed(() => {console.log("publishedBooksMessage")return author.books.length > 0 ? 'Yes' : 'No'})// 一个函数let hasBooks = ()=>{console.log("hasBooks")return author.books.length > 0?'Yes':'no'}</script><template><div><p>{{author.name}} Has published books?:</p><span>{{ author.books.length > 0 ? 'Yes' : 'No' }}</span><span>{{ hasBooks() }}</span><!-- 调用方法,每个标签都会调用一次 --><span>{{ hasBooks() }}</span><p>{{author.name}} Has published books?:</p><span>{{ publishedBooksMessage }}</span><!-- 属性计算,属性值不变时,多个个标签只会调用一次 --><span>{{ publishedBooksMessage }}</span></div>
</template> <style scoped>
</style>
  • 我们在这里定义了一个计算属性 publishedBooksMessagecomputed() 方法期望接收一个 getter 函数,返回值为一个计算属性 ref。和其他一般的 ref 类似,你可以通过 publishedBooksMessage.value 访问计算结果。计算属性 ref 也会在模板中自动解包,因此在模板表达式中引用时无需添加 .value

  • Vue 的计算属性会自动追踪响应式依赖。它会检测到 publishedBooksMessage 依赖于 author.books,所以当 author.books 改变时,任何依赖于 publishedBooksMessage 的绑定都会同时更新。

计算属性缓存 vs 方法

  • 若我们将同样的函数定义为一个方法而不是计算属性,两种方式在结果上确实是完全相同的,然而,不同之处在于计算属性值会基于其响应式依赖被缓存。一个计算属性仅会在其响应式依赖更新时才重新计算。这意味着只要 author.books 不改变,无论多少次访问 publishedBooksMessage 都会立即返回先前的计算结果!

6.6 数据监听器

计算属性允许我们声明性地计算衍生值。然而在有些情况下,我们需要在状态变化时执行一些“副作用”:例如更改 DOM,或是根据异步操作的结果去修改另一处的状态。我们可以使用 watch 函数在每次响应式状态发生变化时触发回调函数:

  • watch主要用于以下场景:
    • 当数据发生变化时需要执行相应的操作
    • 监听数据变化,当满足一定条件时触发相应操作
    • 在异步操作前或操作后需要执行相应的操作

监控响应式数据(watch):

<script type="module" setup>//引入模块import { ref,reactive,watch} from 'vue'let firstname=ref('')let lastname=reactive({name:''})let fullname=ref('')//监听一个ref响应式数据watch(firstname,(newValue,oldValue)=>{console.log(`${oldValue}变为${newValue}`)fullname.value=firstname.value+lastname.name})//监听reactive响应式数据的指定属性watch(()=>lastname.name,(newValue,oldValue)=>{console.log(`${oldValue}变为${newValue}`)fullname.value=firstname.value+lastname.name})//监听reactive响应式数据的所有属性(深度监视,一般不推荐)//deep:true 深度监视//immediate:true 深度监视在进入页面时立即执行一次watch(()=>lastname,(newValue,oldValue)=>{// 此时的newValue和oldValue一样,都是lastnameconsole.log(newValue)console.log(oldValue)fullname.value=firstname.value+lastname.name},{deep:true,immediate:false})
</script><template><div>全名:{{fullname}} <br>姓氏:<input type="text" v-model="firstname"> <br>名字:<input type="text" v-model="lastname.name" > <br></div>
</template> <style scoped>
</style>

监控响应式数据(watchEffect):

  • watchEffect默认监听所有的响应式数据
<script type="module" setup>//引入模块import { ref,reactive,watch, watchEffect} from 'vue'let firstname=ref('')let lastname=reactive({name:''})let fullname=ref('')//监听所有响应式数据watchEffect(()=>{//直接在内部使用监听属性即可!不用外部声明//也不需要,即时回调设置!默认初始化就加载!console.log(firstname.value)console.log(lastname.name)fullname.value=`${firstname.value}${lastname.name}`})
</script><template><div>全名:{{fullname}} <br>姓氏:<input type="text" v-model="firstname"> <br>名字:<input type="text" v-model="lastname.name" > <br></div>
</template> <style scoped>
</style>

watch vs. watchEffect

  • watchwatchEffect 都能响应式地执行有副作用的回调。它们之间的主要区别是追踪响应式依赖的方式:
    • watch 只追踪明确侦听的数据源。它不会追踪任何在回调中访问到的东西。另外,仅在数据源确实改变时才会触发回调。watch 会避免在发生副作用时追踪依赖,因此,我们能更加精确地控制回调函数的触发时机。
    • watchEffect,则会在副作用发生期间追踪依赖。它会在同步执行过程中,自动追踪所有能访问到的响应式属性。这更方便,而且代码往往更简洁,但有时其响应性依赖关系会不那么明确。

6.7. Vue生命周期

6.7.1 生命周期简介

每个 Vue 组件实例在创建时都需要经历一系列的初始化步骤,比如设置好数据侦听,编译模板,挂载实例到 DOM,以及在数据改变时更新 DOM。在此过程中,它也会运行被称为生命周期钩子的函数,让开发者有机会在特定阶段运行自己的代码!

  • 周期图解:

  • 常见钩子函数
    • onMounted() 注册一个回调函数,在组件挂载完成后执行。
    • onUpdated() 注册一个回调函数,在组件因为响应式状态变更而更新其 DOM 树之后调用。
    • onUnmounted() 注册一个回调函数,在组件实例被卸载之后调用。
    • onBeforeMount() 注册一个钩子,在组件被挂载之前被调用。
    • onBeforeUpdate() 注册一个钩子,在组件即将因为响应式状态变更而更新其 DOM 树之前调用。
    • onBeforeUnmount() 注册一个钩子,在组件实例被卸载之前调用。
6.7.2 生命周期案例
<script setup>import {ref,onUpdated,onMounted,onBeforeUpdate} from 'vue'let message =ref('hello')// 挂载完毕生命周期onMounted(()=>{console.log('-----------onMounted---------')let span1 =document.getElementById("span1")console.log(span1.innerText)})// 更新前生命周期onBeforeUpdate(()=>{console.log('-----------onBeforeUpdate---------')console.log(message.value)let span1 =document.getElementById("span1")console.log(span1.innerText)})// 更新完成生命周期onUpdated(()=>{console.log('-----------onUpdated---------')let span1 =document.getElementById("span1")console.log(span1.innerText)})
</script><template><div><span id="span1" v-text="message"></span> <br><input type="text" v-model="message"></div></template><style scoped>
</style>

6.8 Vue组件

6.8.1 组件基础

组件允许我们将 UI 划分为独立的、可重用的部分,并且可以对每个部分进行单独的思考。组件就是实现应用中局部功能代码和资源的集合!在实际应用中,组件常常被组织成层层嵌套的树状结构:

  • 这和我们嵌套 HTML 元素的方式类似,Vue 实现了自己的组件模型,使我们可以在每个组件内封装自定义内容与逻辑。

传统方式编写应用:

组件方式编写应用:

  • 组件化:对js/css/html统一封装,这是VUE中的概念

  • 模块化:对js的统一封装,这是ES6中的概念

  • 组件化中,对js部分代码的处理使用ES6中的模块化

6.8.2 组件化入门案例

案例需求: 创建一个页面,包含头部和菜单以及内容显示区域,每个区域使用独立组建!

1 准备vue项目

npm create vite
cd vite项目
npm install

2 安装相关依赖

npm install sass
npm install bootstrap

3 创建子组件 在src/components文件下 vscode需要安装Vetur插件,这样vue文件有快捷提示

  • Header.vue
<script setup type="module">
</script><template><div>欢迎: xx <a href="#">退出登录</a></div>
</template><style>
</style>
  • Navigator.vue
<script setup type="module">
</script><template><!-- 推荐写一个根标签--><div><ul><li>学员管理</li><li>图书管理</li><li>请假管理</li><li>考试管理</li><li>讲师管理</li></ul></div>
</template><style>
</style>
  • Content.vue
<script setup type="module">
</script><template><div>展示的主要内容!</div>
</template><style>
</style>
  • App.vue 入口组件App引入组件
<script setup>import Header  from './components/Header.vue'import Navigator  from './components/Navigator.vue'import Content  from './components/Content.vue'
</script><template><div><Header class="header"></Header><Navigator class="navigator"></Navigator><Content class="content"></Content></div>
</template><style scoped>.header{height: 80px;border: 1px solid red;}.navigator{width: 15%;height: 800px;display: inline-block;border: 1px blue solid;float: left;}.content{width: 83%;height: 800px;display: inline-block;border: 1px goldenrod solid;float: right;}</style>

4 启动测试

npm run dev
6.8.3 组件之间传递数据
6.8.3.1 父传子

Vue3 中父组件向子组件传值可以通过 props 进行,具体操作如下:

  1. 首先,在父组件中定义需要传递给子组件的值,接着,在父组件的模板中引入子组件,同时在引入子组件的标签中添加 props 属性并为其设置需要传递的值。

  2. 在 Vue3 中,父组件通过 props 传递给子组件的值是响应式的。也就是说,如果在父组件中的传递的值发生了改变,子组件中的值也会相应地更新。

  • 父组件代码:App.vue
<script setup>import Son from './components/Son.vue'import {ref,reactive,toRefs} from 'vue'let message = ref('parent data!')let title = ref(42)function changeMessage(){message.value = '修改数据!'title.value++}
</script><template><div><h2>{{ message }}</h2><hr><!-- 使用子组件,并且传递数据! --><Son :message="message" :title="title"></Son><hr><button @click="changeMessage">点击更新</button></div>
</template><style scoped>
</style>
  • 子组件代码:Son.vue
<script setup type="module">import {ref,isRef,defineProps} from 'vue'//声明父组件传递属性值defineProps({message:String ,title:Number})
</script><template><div><div>{{ message }}</div><div>{{ title }}</div></div>
</template><style>
</style>
6.8.3.2 子传父
  • 父组件: App.vue
<script setup>import Son from './components/Son.vue'import {ref} from 'vue'let pdata = ref('')const padd = (data) => {console.log('2222');pdata.value =data;}//自定义接收,子组件传递数据方法! 参数为数据!const psub = (data) => {console.log('11111');pdata.value = data;}
</script><template><div><!-- 声明@事件名应该等于子模块对应事件名!调用方法可以是当前自定义!--><Son @add="padd" @sub="psub"></Son><hr>{{ pdata }}</div>
</template><style>
</style>
  • 子组件:Son.vue
<script setup>import {ref,defineEmits} from 'vue'//1.定义要发送给父组件的方法,可以1或者多个let emites = defineEmits(['add','sub']);let data = ref(1);function sendMsgToParent(){console.log('-------son--------');//2.出发父组件对应的方法,调用defineEmites对应的属性emites('add','add data!'+data.value)emites('sub','sub data!'+data.value)data.value ++;}
</script><template><div><button @click="sendMsgToParent">发送消息给父组件</button></div>
</template>
6.8.3.3 兄弟传参
  • Navigator.vue: 发送数据到App.vue
<script setup type="module">import {defineEmits} from 'vue'const emits = defineEmits(['sendMenu']);//触发事件,向父容器发送数据function send(data){emits('sendMenu',data);}
</script><template><!-- 推荐写一个根标签--><div><ul><li @click="send('学员管理')">学员管理</li><li @click="send('图书管理')">图书管理</li><li @click="send('请假管理')">请假管理</li><li @click="send('考试管理')">考试管理</li><li @click="send('讲师管理')">讲师管理</li></ul></div>
</template><style></style>
  • App.vue: 发送数据到Content.vue
<script setup>import Header  from './components/Header.vue'import Navigator  from './components/Navigator.vue'import Content  from './components/Content.vue'import {ref} from "vue"//定义接受navigator传递参数var navigator_menu = ref('ceshi');const receiver = (data) =>{navigator_menu.value = data;}
</script><template><div><hr>{{ navigator_menu }}<hr><Header class="header"></Header><Navigator @sendMenu="receiver" class="navigator"></Navigator><!-- 向子组件传递数据--><Content class="content" :message="navigator_menu"></Content></div>
</template><style scoped>.header{height: 80px;border: 1px solid red;}.navigator{width: 15%;height: 800px;display: inline-block;border: 1px blue solid;float: left;}.content{width: 83%;height: 800px;display: inline-block;border: 1px goldenrod solid;float: right;}</style>
  • Content.vue
<script setup type="module">defineProps({message:String})
</script><template><div>展示的主要内容!<hr>{{ message }}</div>
</template><style>
</style>

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/223141.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kubernetes集群 应用实践 kafka部署

kubernetes集群 应用实践 kafka部署 零.1、环境说明 零.2、kafka架构说明 zookeeper在kafka集群中的作用 一、Broker注册 二、Topic注册 三、Topic Partition选主 四、生产者负载均衡 五、消费者负载均衡 一、持久化存储资源准备 1.1 创建共享目录 [rootnfsserver ~]# mkdir -…

医学实验室检验科LIS信息系统源码

实验室信息管理是专为医院检验科设计的一套实验室信息管理系统&#xff0c;能将实验仪器与计算机组成网络&#xff0c;使病人样品登录、实验数据存取、报告审核、打印分发&#xff0c;实验数据统计分析等繁杂的操作过程实现了智能化、自动化和规范化管理。 实验室管理系统功能介…

阿里云ECS配置IPv6后,如果无法访问该服务器上的网站,可检查如下配置

1、域名解析到这个IPv6地址,同一个子域名可以同时解析到IPv4和IPv6两个地址&#xff0c;这样就可以给网站配置ip4和ipv6双栈&#xff1b; 2、在安全组规则开通端口可访问&#xff0c;设定端口后注意授权对象要特殊设置“源:::/0” 3、到服务器nginx配置处&#xff0c;增加端口…

二值选择模型-以stata为工具

二值选择模型-以stata为工具 文章目录 1. 命令语法2. 模型 代码示例2.1 读取数据2.2 建立模型2.3 数据预测1. 命令语法 二值选择模型是计量经济学中常用的一种模型,用于处理因变量为二值(0或1)的情况。 这种模型通常用来研究个体在面临两个或多个离散选择时的决策行为。其中…

Mybatis之增删改查

目录 一、引言 二、Mybatis——增 举例&#xff1a;添加用户 三、Mybatis——删 举例&#xff1a;删除用户 四、Mybatis——改 举例&#xff1a;修改用户 五、Mybatis——查 六、注意 END&#xff1a; 一、引言 书接上回&#xff0c;我们在了解完mybatis之后&#xff0c;肯…

会员管理怎么做?

会员管理是企业运营的重要组成部分&#xff0c;它涉及到会员的招募、维护、激励、保留、转化等多个环节。下面&#xff0c;我们将结合具体的案例&#xff0c;详细介绍会员管理的具体做法。 首先&#xff0c;会员的招募是会员管理的第一步 企业需要通过各种方式吸引消费者成为会…

【大数据】NiFi 中的 Controller Service

NiFi 中的 Controller Service 1.Service 简介1.1 Controller Service 的配置1.1.1 SETTING 基础属性1.1.2 PROPERTIES 使用属性1.1.3 COMMENT 页签 1.2 Service 的使用范围 2.全局参数配置3.DBCPConnectionPool 的使用样例4.在 ExcuseGroovyScript 组件中使用 Service 1.Servi…

【Prometheus|报错】Out of bounds

【背景】进入Prometheus地址的9090端口&#xff0c;pushgateway&#xff08;0/1&#xff09;error : out of bounds 【排查分析】 1、out of bounds报错&#xff0c;是由于Prometheus向tsdb存数据出错&#xff0c;与最新存数据的时间序列有问题&#xff0c;有可能当前时间与最…

步兵 cocos2dx 加密和混淆

文章目录 摘要引言正文代码加密具体步骤代码加密具体步骤测试和配置阶段IPA 重签名操作步骤 总结参考资料 摘要 本篇博客介绍了针对 iOS 应用中的 Lua 代码进行加密和混淆的相关技术。通过对 Lua 代码进行加密处理&#xff0c;可以确保应用代码的安全性&#xff0c;同时提高性…

小白入门之安装MYSQL

重生之我在大四学JAVA 第三章 安装MYSQL 把MySQL复制到要安装的路径下解压 到解压后的bin路径下复制路径 接着以“管理员”身份打开命令行(如下图所示) 注意&#xff1a;一定要是管理员身份&#xff0c;否则由于后续部分命令需要权限&#xff0c;出现错误&#xff01; 转到…

C# .Net学习笔记—— Expression 表达式目录树

目录 一、什么是表达式目录树 二、Func与Expression的区别 1、Func是方法 3、使用ILSpy反编译解析看一下 ​编辑 ​编辑 4、拼装练习 5、动态生成硬编码&#xff08;通用、性能好&#xff09; 5、表达式目录树动态生成的用途&#xff1a; 6、递归解析表达式目录树 7、…

凸优化 2:如何判定凸函数?

凸优化 2&#xff1a;如何判定凸函数&#xff1f; 如何判断一个目标函数是凸函数&#xff1f;如果是凸函数&#xff0c;那ta的定义域是凸集合 一个函数求俩次梯度&#xff0c;大于等于0&#xff0c;那这个函数就是一个凸函数在同样条件下&#xff0c;怎么设计为凸函数模型&…

Go后端开发 -- 环境搭建

Go后端开发 – 环境搭建 文章目录 Go后端开发 -- 环境搭建一、环境配置二、IDE的选择三、使用go mod构建项目1.初始化项目2.添加依赖项3.运行项目 四、环境报错1.VS Code中gopls报错 一、环境配置 Go官网下载地址&#xff1a;https://golang.org/dl/ https://go.dev/dl/ Go官方…

安装nodejs,配置环境变量并将npm设置淘宝镜像源

安装nodejs并将npm设置淘宝镜像源 1. 下载nodejs 个人不喜欢安装包&#xff0c;所以是下载zip包的方式。这里我下载的node 14解压包版本 下载地址如下&#xff1a;https://nodejs.org/dist/v14.15.1/node-v14.15.1-win-x64.zip 想要其他版本的小伙伴去https://nodejs.org/di…

nodejs+vue+ElementUi资源互助共享平台的设计

后台&#xff1a;管理员功能有个人中心&#xff0c;用户管理&#xff0c;卖家管理&#xff0c;咨询师管理&#xff0c;萌宝信息管理&#xff0c;幼儿知识管理&#xff0c;保姆推荐管理&#xff0c;音频资源管理&#xff0c;二手商品管理&#xff0c;商品分类管理&#xff0c;资…

第26关 K8s日志收集揭秘:利用Log-pilot收集POD内业务日志文件

------> 课程视频同步分享在今日头条和B站 大家好&#xff0c;我是博哥爱运维。 OK&#xff0c;到目前为止&#xff0c;我们的服务顺利容器化并上了K8s&#xff0c;同时也能通过外部网络进行请求访问&#xff0c;相关的服务数据也能进行持久化存储了&#xff0c;那么接下来…

管理 Jenkins 详细指南

目录 系统配置 安全 状态信息 故障 排除 工具和操作 系统配置 系统&#xff0c;配置全局设置和路径&#xff0c;端口更改&#xff0c;下载地址等。 工具&#xff0c;配置工具、其位置和自动安装程序。 插件&#xff0c;添加、删除、禁用或启用可以扩展 Jenkins 功能的插…

2. 行为模式 - 命令模式

亦称&#xff1a; 动作、事务、Action、Transaction、Command 意图 命令模式是一种行为设计模式&#xff0c; 它可将请求转换为一个包含与请求相关的所有信息的独立对象。 该转换让你能根据不同的请求将方法参数化、 延迟请求执行或将其放入队列中&#xff0c; 且能实现可撤销…

电力系统风储联合一次调频MATLAB仿真模型

微❤关注“电气仔推送”获得资料&#xff08;专享优惠&#xff09; 简介&#xff1a; 同一电力系统在不同风电渗透率下遭受同一负荷扰动时&#xff0c;其频率变化规律所示&#xff1a; &#xff08;1&#xff09;随着电力系统中风电渗透率的不断提高&#xff0c;风电零惯性响…

09.list 容器

9、list 容器 功能&#xff1a; 将数据进行链式存储 链表&#xff08;list&#xff09;是一种物理存储单元上非连续的存储结构&#xff0c;数据元素的逻辑顺序是通过链表中的指针链接实现的 链表的组成&#xff1a; 链表由一系列结点组成 结点的组成&#xff1a; 一个是存…