CodeWhy
快来分享你的内容吧~
- 2023-08-12·前端求coderwhy js高级完整视频,这个资源里少了第24集[流泪][流泪][流泪] 资源 https://pan.baidu.com/s/1kgHQ_EuX8IjhewncPVsJpA?pwd=2upn#/home////想吃饭敢当:【超级会员V4】通过百度网盘分享的文件:js高级链接:https://pan.baidu.com/s/1ARSxP7Z7mgtRywzVJtlo-w 提取码:1234复制这段内容打开「百度网盘APP 即可获取」看看这里面有没有你需要的1120分享
- 2023-04-14·全栈开发
求coderwhy js高级完整视频,这个资源里少了第24集[流泪][流泪][流泪] 资源 https://pan.baidu.com/s/1kgHQ_EuX8IjhewncPVsJpA?pwd=2upn#/home////
codewhy的Vue3学习笔记-组件化开发
<html> <head></head> <body> <div class="content ql-editor"> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">父子组件间的通信</strong></h4> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>父组件 => 子组件 :通过props属性</li> <li data-list="bullet"><span class="ql-ui"></span>子组件 => 父组件: 通过$emit触发事件</li> </ol> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">父传子</strong></h5> <p><br></p> <p>我们可以通过 props 来完成组件之间的通信</p> <p><strong>props是什么?</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>props 是你可以在组件上注册一些自定义的 attribute</li> <li data-list="bullet"><span class="ql-ui"></span>父组件可以给这些 attribute 赋值,子组件通过 attribute 的名称获取到对应的值</li> </ol> <p><strong>props有两种常见的用法:</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>方式一:字符串数组,数组中的字符串就是 attribute 的名称</li> <li data-list="bullet"><span class="ql-ui"></span>方拾二:对象类型;对象类型我们可以在指定 props 名称的同时,指定它需要传递的类型,是否是必须的,默认值</li> </ol> <p><strong>props的数组用法</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> //子组件-showMessage </div> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <div>组件展示的title:{{title}}</div> </div> <div class="ql-code-block"> <div>组件展示的content:{{content}}</div> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> props:["title", "content"] </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> <div class="ql-code-block"> // 父组件 </div> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <div> </div> <div class="ql-code-block"> <show-message title="heihei" content="this is a boring boy"> </div> <div class="ql-code-block"> </show-message> </div> <div class="ql-code-block"> </div> </div> <div class="ql-code-block"> </template> </div> </div> <p><strong>props的对象用法</strong></p> <p>数组用法只能传入 attribute 的名称,并不能对形式做限制和传入默认值</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>指定传入的 attribute 的类型</li> <li data-list="bullet"><span class="ql-ui"></span>指定传入的 attribute 是否是必传的</li> <li data-list="bullet"><span class="ql-ui"></span>指定没有传入时,attribute 的默认值</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> props:{ </div> <div class="ql-code-block"> //指定类型 </div> <div class="ql-code-block"> title: String, </div> <div class="ql-code-block"> //指定类型 同时指定是否必选,默认值 </div> <div class="ql-code-block"> content: { </div> <div class="ql-code-block"> type: String, </div> <div class="ql-code-block"> require: true, </div> <div class="ql-code-block"> default:"哈哈哈" </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> </div> <p><strong>对象类型的其他写法</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> props: { </div> <div class="ql-code-block"> msg: String, </div> <div class="ql-code-block"> // 基础类型检查(null 和 undefined 会通过任何类型检测) </div> <div class="ql-code-block"> propA: [String, Number], </div> <div class="ql-code-block"> //可能多个类型 </div> <div class="ql-code-block"> propB: {type: String, require: true} </div> <div class="ql-code-block"> //必填 </div> <div class="ql-code-block"> propC:{type: Number, default:100 } </div> <div class="ql-code-block"> // 带有默认值的数字 </div> <div class="ql-code-block"> propD:{ </div> <div class="ql-code-block"> type: Object, </div> <div class="ql-code-block"> default() { return { message:'hello' } } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> //带有默认值的对象 </div> <div class="ql-code-block"> propE:{ </div> <div class="ql-code-block"> validator(value) { </div> <div class="ql-code-block"> //这个值必须 匹配下面字符串中的一个 </div> <div class="ql-code-block"> return ['success', 'denger', 'error'].includes(value) </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> // 自定义验证函数 </div> <div class="ql-code-block"> propF:{ </div> <div class="ql-code-block"> type:Function, </div> <div class="ql-code-block"> // 与对象或函数默认值不同,这不是一个工厂函数 </div> <div class="ql-code-block"> default() { </div> <div class="ql-code-block"> return 'Default Function' </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> </div> <p><strong>非Prop的Attribute</strong></p> <p>当我们传递给一个组件某个属性但是该属性没有定义对应的props或者emits时,就称之为非props的Attribute</p> <p>例如常见的:class , style , id</p> <p><strong>Attribute继承</strong></p> <p>当组件有单个根节点时,非 Prop 的 Attribute 将自动添加到根节点的 Attribute 中</p> <p><strong>禁用Attribute继承和多根节点</strong></p> <p>如果我们不希望组件的根元素继承 attribute,可以在组件中设置 inheritAttrs : false</p> <p><strong>我们可以通过 $attrs 来访问所有的 非 props 的 attribute</strong></p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">子传父</strong></h5> <p><br></p> <p><strong>前置知识</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span><strong>emits</strong></li> </ol> <p>emits可以是数组或者对象,从组件触发自定义事件,对象可以进行参数验证</p> <p><strong>如何实现</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>首先,我们需要在<strong>子组件中定义好在某些情况下触发的事件名称</strong>;</li> <li data-list="bullet"><span class="ql-ui"></span>其次,在<strong>父组件中以 v-on 的方式传入要监听的事件名称</strong>,并绑定到对应的方法中</li> <li data-list="bullet"><span class="ql-ui"></span>最后在子组件中发生某个事件的时候,根据事件名称触发对应的事件</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> // 父组件 </div> <div class="ql-code-block"> <h2>当前计数: {{counter}}</h2> </div> <div class="ql-code-block"> <counter-operation @add="addOne"></counter-operation> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> counter: 0 </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> methods: { </div> <div class="ql-code-block"> addOne() { </div> <div class="ql-code-block"> this.counter++ </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 子组件 </div> <div class="ql-code-block"> <button @click="increment">+1</button> </div> <div class="ql-code-block"> emits: { </div> <div class="ql-code-block"> add: null, </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> num: 0 </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> methods: { </div> <div class="ql-code-block"> increment() { </div> <div class="ql-code-block"> console.log("+1"); </div> <div class="ql-code-block"> this.$emit("add"); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> incrementN() { </div> <div class="ql-code-block"> const flag = this.$emit('addN', this.num, "why", 18); </div> <div class="ql-code-block"> console.log(flag,'flag'); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> </div> <p><strong>自定义事件</strong></p> <p>自定义事件我理解的是:子组件传值给父组件的时候,父组件可以自定义事件名称例如 @customName 然后子组件就可以通过 emits 来接收到这个自定义事件并调用它,通过 this.$emits("customName",..args)args 是父组件中的这个自定义事件所需要的参数,可以传多个</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">非父子组件的通信</strong></h5> <p><br></p> <p>在我们实际开发中还有很多非父子组件的通信</p> <p><strong>主要有两种方式:</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>Provide/Inject</li> <li data-list="bullet"><span class="ql-ui"></span>Mitt 全局事件总线</li> </ol> <p><strong>Provide 和 Inject</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>比如有一些<strong>深度嵌套的组件</strong>,<strong>子组件想要获取父组件的部分内容</strong>;</li> <li data-list="bullet"><span class="ql-ui"></span>如果我们任然<strong>将 props 沿着组件链逐级传递下去</strong>,就会非常的麻烦;</li> <li data-list="bullet"><span class="ql-ui"></span>对于这种情况,我们可以使用 <strong>Provide 和 Inject:</strong></li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>无论层级结构有多深,父组件都可以作为其所有子组件的依赖提供者</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>父组件有一个 <strong>provider 选项</strong>来提供数据,子组件有一个 <strong>inject 选项</strong>来开始使用这些数据</li> <li data-list="bullet"><span class="ql-ui"></span>实际上,你可以将依赖注入看成 'lang range props' 除了:父组件不需要知道哪些子组件使用它 provide 的property,子组件不需要知道 inject 的 property 来自哪里</li> </ol> <p><img src="https://pic.code-nav.cn/planet_post_image/1619930914211520514/9zfhnxlv.jpeg"></p> <div class="ql-code-block-container"> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> // 父组件 </div> <div class="ql-code-block"> provide() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> name: "why", </div> <div class="ql-code-block"> age: 18, </div> <div class="ql-code-block"> length: computed(() => this.names.length) // ref对象 .value </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> </script> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> // 子组件 :在子组件中写入后 就可以把它当做data中的数据进行使用 </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> inject: ["name", "age", "length"], </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> </div> <p><strong>全局事件总线mitt库</strong></p> <p>Vue3 从实例中移除了 $on 、$off 和 $once 方法,如果我们希望继续使用全局事件总线 Vue3 推荐使用 mitt 库</p> <p><strong>不是很理解,不知道实际使用场景</strong></p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">插槽Slot</strong></h5> <p><br></p> <p><strong>使用场景:</strong></p> <p>在开发中,我们会经常封装一个个可复用的组件:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>前面我们会通过props传递给组件一些数据,让组件进行展示</li> <li data-list="bullet"><span class="ql-ui"></span>但是<strong>为了让组件有更强的通用性</strong>,我们不能将组件的内容限制为<strong>固定的</strong>div,span等等元素</li> <li data-list="bullet"><span class="ql-ui"></span>比如某种情况下我们使用组件,希望组件显示的是一个按钮<strong>,换一种情况</strong>组件显示的说一张图片,</li> <li data-list="bullet"><span class="ql-ui"></span>我们应该让<strong>使用者可以决定莫一块区域到底存放什么内容和元素</strong></li> </ol> <p>举个栗子:假如我们定制一个通用的导航组件 -NavBar</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>这个组件分为三个区域,左边 - 中间 - 右边</li> <li data-list="bullet"><span class="ql-ui"></span><img src="https://pic.code-nav.cn/planet_post_image/1619930914211520514/iifyd0yx.jpeg"></li> <li data-list="bullet"><span class="ql-ui"></span>但是你看,左边可能显示一个菜单图标,也可能显示一个返回按钮,可能还是什么都不显示;中间和右边同理</li> </ol> <p><strong>使用插槽slot</strong></p> <p><strong>重要提醒:</strong></p> <p>插槽的使用其实就是抽取共性,预留不同;我们将共同的元素,内容依然组件内进行封装;同时将不同的元素使用slot 作为占位符,让使用这个组件的实例来定义 slot 内的内容</p> <p>vue 中将 <slot> 元素作为承载分发内容的出口;在封装组件中,使用特殊的元素 <span style="color: rgb(167, 167, 167);"><slot> </span>就可以为封装组件开启一个插槽,插槽内的内容完全取决于其实例组件</p> <p><strong>插槽的默认内容</strong></p> <p>有时候我们希望在使用插槽时,如果没有对应的内容,那么我们需要显示一个默认的内容,这个默认的内容只会在没有插入内容时候才会显示</p> <div class="ql-code-block-container"> <div class="ql-code-block"> //使用插槽的组件 </div> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <div> </div> <div class="ql-code-block"> <MySlotCpn> </div> <div class="ql-code-block"> 111 // 这里的内容就会放到定义好的插槽中, </div> <div class="ql-code-block"> </MySlotCpn> </div> <div class="ql-code-block"> </div> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> import MySlotCpn from './MySlotCpn.vue'; </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> components: { </div> <div class="ql-code-block"> MySlotCpn </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> <div class="ql-code-block"> // 插槽组件 </div> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <div> </div> <div class="ql-code-block"> <slot> </div> <div class="ql-code-block"> <i>我是默认的i元素</i> //当使用这个插槽组件但是没有往插槽中插入任何东西就会显示默认的,否则显示的就是父组件的插入元素 </div> <div class="ql-code-block"> </slot> </div> <div class="ql-code-block"> </div> </div> <div class="ql-code-block"> </template> </div> </div> <p><strong>多个插槽效果</strong></p> <p>如果一个组件中含有多个插槽,但是元素我们插入多个内容,我们会发现每个插槽都会插入所有的内容,为了让内容插到对应的插槽就有了<strong>具名插槽</strong></p> <p><strong>具名插槽就是给插槽起一个名字 </strong><strong style="color: rgb(167, 167, 167);"><slot> </strong><strong>元素就有了一个特殊的 attribute:name , 一个不带 name 的 slot 会含有隐式的名字 default , 它的效果是:</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> //使用插槽的元素 </div> <div class="ql-code-block"> <template v-slot:left> </div> <div class="ql-code-block"> this is left </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> // 插槽 这里slot加载到页面中是没有slot元素的,它只是一个占位符 </div> <div class="ql-code-block"> <slot name="left"></slot> </div> </div> <p><strong>动态插槽名</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>目前我们使用的插槽名称都是固定的;例如:v-slot<strong>:left</strong>, 这里这个 left 就是写死的,我们可以通过 <strong>v-slot:[dynamicSlotName]</strong>,</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> <template v-slot:[name]>//这个name就是data中定义的动态数据 </div> <div class="ql-code-block"> </template> </div> </div> <p>具名插槽的缩写:即把v-slot:替换为#</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">渲染作用域</strong></h5> <p><br></p> <p>在vue中有渲染作用域的概念:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>父模板中的所有内容都是在父级作用域中编译;子模板也是一样;其实很好理解;例如我们无法在父模板中访问或者使用子模板的data变量或者方法</li> </ol> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">作用域插槽</strong></h5> <p><br></p> <p>从上面可知,父子作用域独立,但是有时候我们希望<strong>插槽</strong>可以访问到子组件中的内容,这个是很常见的需求</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>当一个组件被用来渲染一个数组元素时,我们使用插槽,并且希望插槽中没有显示每项的内容,这时候就需要作用域插槽</li> </ol> <p>如果还有其他的具名插槽, 那么默认插槽也必须使用 template 来编写</p> <p><strong>独占默认插槽的缩写</strong></p> <p>如果我们的插槽是默认插槽default,那么在使用的时候 v-slot:default="slotProps" 可以简写为 v-slot="slotProps"</p> <p>默认插槽和具名插槽混合使用:使用 v-slot:why(一个名称其他也行)来定义具名插槽,使用 v-slot="slotProps"来使用默认插槽</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">动态组件的使用</strong></h5> <p><br></p> <p>动态组件是使用 component 组件,通过特殊的 attribute <strong>is </strong>实现</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <button v-for="item in tabs" :key="item" </div> <div class="ql-code-block"> @click="itemClick(item)" </div> <div class="ql-code-block"> :class="{active: currentTab === item}"> </div> <div class="ql-code-block"> {{item}} </div> <div class="ql-code-block"> </button> </div> <div class="ql-code-block"> <!-- 2.动态组件 --> </div> <div class="ql-code-block"> <keep-alive include="home,about,category" max='2'> </div> <div class="ql-code-block"> <component :is="currentTab" </div> <div class="ql-code-block"> name="coderwhy" </div> <div class="ql-code-block"> :age="18" </div> <div class="ql-code-block"> @pageClick="pageClick"> </div> <div class="ql-code-block"> </component> </div> <div class="ql-code-block"> </keep-alive> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> tabs: ["home", "about", "category"], </div> <div class="ql-code-block"> currentTab: "home" </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> methods() { </div> <div class="ql-code-block"> itemClick(item) { </div> <div class="ql-code-block"> this.currentTab = item; </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> pageClick() { </div> <div class="ql-code-block"> console.log("page内部发生了点击"); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> <h3><strong style="color: rgb(51, 51, 51);">认识 keep-alive</strong></h3> <p><br></p> <p><strong>产生背景</strong></p> <p>在默认情况下,我们在切换组件时候,about组件会被销毁掉,再次回来时会重新创建组件,但是我们在开发中我们希望继续保持组件的状态,而不是销毁掉,这个时候我们可以使用一个内置组件:keep-alive</p> <p><strong>keep-alive属性</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>include : string | RegExp | Array。只有在名称匹配的组件会被缓存</li> <li data-list="bullet"><span class="ql-ui"></span>exclude : string | RegExp | Array。任何匹配的组件都不会被缓存</li> <li data-list="bullet"><span class="ql-ui"></span>max : number | string。最多可以缓存多少组实例,一旦达到这个数字,那么缓存中最近没有被访问的实例被销毁</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> <!-- 2.动态组件 --> </div> <div class="ql-code-block"> <keep-alive include="home,about,category" max='2'> </div> <div class="ql-code-block"> <component :is="currentTab" </div> <div class="ql-code-block"> name="coderwhy" </div> <div class="ql-code-block"> :age="18" </div> <div class="ql-code-block"> @pageClick="pageClick"> </div> <div class="ql-code-block"> </component> </div> <div class="ql-code-block"> </keep-alive> </div> </div> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">缓存组件的生命周期</strong></h5> <p><br></p> <p>对于缓存的组件来说,再次进入时,我们是不会执行created或者mounted等生命周期函数的</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>但是我们有时候希望监听何时重新进入和离开这个组件</li> <li data-list="bullet"><span class="ql-ui"></span>这时候我们可以使用activated和deactivated来监听;</li> </ol> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">vue实现异步组件</strong></h5> <p><br></p> <p><strong>1. 产生背景:</strong></p> <p>当我们项目过大了,对于某些组件我们希望可以通过异步的方式来进行加载(目的是可以对其分包处理,也就是让 wabpack 对其进行单独打包)</p> <p><strong>2. 使用</strong></p> <p>vue 给我们提供了一个函数:defineAsyncComponent 它接收两种类型参数,</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>工厂函数,该工厂函数需要返回一个 Promise 对象</li> <li data-list="bullet"><span class="ql-ui"></span>接收一个对象类型,对异步函数进行配置</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> //工厂函数写法 </div> <div class="ql-code-block"> import defineAsyncComponent from 'vue' </div> <div class="ql-code-block"> const AsyncHome = defineAsyncComponent(()=>import("./AsyncHome.vue")) </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> components: { </div> <div class="ql-code-block"> AsyncHome </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> // 对象写法 </div> <div class="ql-code-block"> const AsyncCategory = defineAsyncComponent({ </div> <div class="ql-code-block"> loader: () => import("./AsyncCategory.vue"), </div> <div class="ql-code-block"> loadingComponent: Loading, </div> <div class="ql-code-block"> // errorComponent, </div> <div class="ql-code-block"> // 在显示loadingComponent组件之前, 等待多长时间 </div> <div class="ql-code-block"> delay: 2000, </div> <div class="ql-code-block"> /** </div> <div class="ql-code-block"> * err: 错误信息, </div> <div class="ql-code-block"> * retry: 函数, 调用retry尝试重新加载 </div> <div class="ql-code-block"> * attempts: 记录尝试的次数 </div> <div class="ql-code-block"> */ </div> <div class="ql-code-block"> onError: function(err, retry, attempts) { </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">异步组件和 Suspense</strong></h5> <p><br></p> <p><strong>注意: 这是一个实验性的特性,API可能随时修改</strong></p> <p>Suspense 是一个内置的全局组件,该组件有两个插槽:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>default: 如果 default 可以显示,那么显示 default 内容</li> <li data-list="bullet"><span class="ql-ui"></span>fallback:如果 default 无法显示 那么会显示 fallback 插槽的内容</li> </ol> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">$ref的使用</strong></h5> <p><br></p> <p><strong>使用场景:</strong></p> <p>在某些情况下,我们组件想要直接获取到元素对象或者子组件示例:我们可以给元素绑定一个 ref 的 attribute 属性</p> <p><strong>组件实例有一个 $refs 属性:</strong></p> <p>它是一个对象,持有注册过 ref attribute 的所有DOM元素和组件实例</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">生命周期</strong></h5> <p><br></p> <p><strong>定义:</strong></p> <p>每个组件都会经历从创建,挂载,更新,卸载等一系列的过程。在这些过程的某个阶段,可能会想要添加一些属于自己的代码逻辑,(比如请求数据)这个时候就需要 Vue 给我们提供的生命周期函数来实现</p> <p><strong>使用:</strong></p> <p>生命周期函数就是一些钩子函数,在某个时间会被 Vue 源码内部进行回调,我们调用生命周期函数在里面写自己的逻辑,这样就可以实现页面在加载完成同时做完我们的事情</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">组件的v-model</strong></h5> <p><br></p> <div class="ql-code-block-container"> <div class="ql-code-block"> // 父组件 </div> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <hy-input v-model="message" v-model:title="title" @my-event="add"></hy-input> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> import HyInput from './HyInput.vue'; </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> components: { </div> <div class="ql-code-block"> HyInput </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> message: "Hello World", </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> methods:{ </div> <div class="ql-code-block"> add (val) { </div> <div class="ql-code-block"> this.num += val </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> <div class="ql-code-block"> // 子组件 </div> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <input v-model="value"> </div> <div class="ql-code-block"> <input v-model="why"> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> props: { </div> <div class="ql-code-block"> modelValue: String, </div> <div class="ql-code-block"> title: String </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> emits: ["update:modelValue", "update:title"], </div> <div class="ql-code-block"> computed: { </div> <div class="ql-code-block"> value: { </div> <div class="ql-code-block"> set(value) { </div> <div class="ql-code-block"> this.$emit("update:modelValue", value); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> get() { </div> <div class="ql-code-block"> return this.modelValue; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> why: { </div> <div class="ql-code-block"> set(why) { </div> <div class="ql-code-block"> this.$emit("update:title", why); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> get() { </div> <div class="ql-code-block"> return this.title; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> </div> <p><strong>总结:</strong></p> <p>父组件需要在使用的子组件中写 attribute ; v-model 值为一个对象,当我们把这个值传入子组件后,子组件就可以通过 $emit 来实现在子组件中直接修改父组件中的值,并响应式更新</p> <p>具体实现是通过子组件的 computed 的 get 接收父组件传来的值和 set 修改父组件传来的值,使用 emits 来声明我们 this.$emit 所需要的第一个参数,通常是这样的 update:modelValue</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">子组件绑定多个属性(使用 v-model )</strong></h5> <p><br></p> <p><strong>需求:</strong></p> <p>我们希望在一个组件上使用多个 v-model 来绑定多个属性</p> <p>我们知道,默认情况下的 v-model 其实是绑定了 modelValue 属性和 @update:modelValue 事件,当我们需要给一个组件绑定多个属性时,可以这样写 v-model:num='data' 其中 num 是传给子组件 props 接收参数的名称,data 是传过去的父组件的 data 中定义的数据</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">Mixin</strong></h5> <p><br></p> <p><strong>产生背景:</strong></p> <p>我们在实际开发中,会遇到组件和组件之间有时候会存在相同的代码逻辑,我们希望<strong>对相同的代码逻辑进行抽取,这样就不用重复书写,</strong>那么我们就可以使用Mixin来实现</p> <p><strong>使用:</strong></p> <p>Mixin 提供了一种非常灵活的方式,来分发 Vue 组件中可复用功能,</p> <p>一个Mixin对象可以包含任何组件选项;</p> <p>当组件使用 Mixin 对象时,所有 Mixin 对象的选项将被混合进入该组件本身的选项中;</p> <p><strong>Mixin的合并规则</strong></p> <p>如果 Mixin 对象中的选项和组件对象中的选项发生冲突,vue会这样操作</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>如果是data函数的返回值对象</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>返回值对象默认会进行合并</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>如果data返回值对象的属性发生了冲突,那么会保留组件自身的数据</li> <li data-list="bullet"><span class="ql-ui"></span>如果是生命周期钩子函数</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>钩子函数会被合并到数组中,都会被调用;</li> <li data-list="bullet"><span class="ql-ui"></span>值为对象的选项,例如 methods,components, directives, 将会合并为一个对象</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>例如methods选择,如果都定义了方法,那么就会合并,但是如果对象的key相同,那么就会取组件对象的键值对</li> </ol> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">全局混入Mixin</strong></h5> <p><br></p> <p>如果组件中某些选择,是所有组件都需要的,那么我们可以使用全局Mixin</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>全局 Mixin 可以使用应用 app 的方法 mixin 来完成注册</li> <li data-list="bullet"><span class="ql-ui"></span>一旦注册,那么全局混入的选项将会影响每一个组件</li> </ol> <p><br></p> </div> </body> </html>
coderwhy的Vue3笔记 -组合式API2
<html> <head></head> <body> <div class="content ql-editor"> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">认识h函数</strong></h4> <p><br></p> <p>Vue绝大多数情况使用模板来创建HTML,但是有些地方需要JavaScript的编辑能力,我们可以使用渲染函数,它比模板更接近编译器</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">VNode和VDOM</strong></h5> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>vue在生成真实DOM之前,会将我们的节点转成VNode,而VNode组合在一起形成一颗树结构,就是虚拟DOM(VDOM)</li> <li data-list="bullet"><span class="ql-ui"></span>事实上,我们之前编写的template中的HTML最终也是使用渲染函数生成对应的VNode</li> <li data-list="bullet"><span class="ql-ui"></span>那么,如果想要使用JavaScript来生成相应的VNode,我们可以自己来编写creatVNode函数实现</li> <li data-list="bullet"><span class="ql-ui"></span>我们可以使用h()函数:一个用于创建vnode的函数;其实更准确的命名是createVNode()函数,所有h()又是语法糖啦!!!</li> </ol> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">h()函数使用方法</strong></h5> <p><br></p> <p>它接收三个参数:</p> <ol> <li data-list="ordered"><span class="ql-ui"></span>type:</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>类型:string | object | function</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>详细:HTML标签名,组件,异步组件,函数式组件。使用返回 null 的函数将渲染一个注释。此参数是必需的。</li> <li data-list="ordered"><span class="ql-ui"></span>props:</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>类型:object</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>详细:一个对象,与我们将在模板中使用的 attribute、prop 和事件相对应。可选。</li> <li data-list="ordered"><span class="ql-ui"></span>children:</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>类型:string | Array | Object</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>详细:子代 VNode,使用 h() 生成,或者使用字符串来获取“文本 VNode”,或带有插槽的对象。可选。</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> h('div', {}, [ </div> <div class="ql-code-block"> 'Some text comes first.', </div> <div class="ql-code-block"> h('h1', 'A headline'), </div> <div class="ql-code-block"> h(MyComponent, { </div> <div class="ql-code-block"> someProp: 'foobar' </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> ]) </div> </div> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">注意:</strong></h5> <p><br></p> <p>如果没有props,(第二个参数)那么通常可以将children作为第二个参数,如果会产生歧义,那么就可以将null作为第二个参数,将children作为第三个参数</p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">vue中使用JSX</strong></h4> <p><br></p> <p><strong>使用配置</strong></p> <p>如果想要在vue项目中使用jsx,我们需要添加对jsx的支持,我们可以用Babel来进行转换,我们需要在Babel中配置对应的插件,</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>安装Babel支持vue的jsx插件</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> npm install @vue/babel-plugin-jsx -D </div> </div> <ol> <li data-list="bullet"><span class="ql-ui"></span>在<a href="http://babel.config.js" target="_blank">babel.config.js</a>配置文件中配置插件</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> module.exports = { </div> <div class="ql-code-block"> presets: [ </div> <div class="ql-code-block"> '@vue/cli-plugin-babel/preset' </div> <div class="ql-code-block"> ], </div> <div class="ql-code-block"> plugins: [ </div> <div class="ql-code-block"> "vue/babel-plugin-jsx" </div> <div class="ql-code-block"> ] </div> <div class="ql-code-block"> } </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">自定义指令</strong></h4> <p><br></p> <p>vue允许我们自己来定义一些自定义指令</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">使用场景</strong></h5> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>在Vue中,代码的复用和抽象主要还是通过组件</li> <li data-list="bullet"><span class="ql-ui"></span>通常,当你需要对DOM元素进行底层操作时候,我们需要用到自定义指令</li> </ol> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">使用方式</strong></h5> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>自定义局部指令:组件中通过directives选项,只能在当前组件中使用</li> <li data-list="bullet"><span class="ql-ui"></span>自定义全局指令:app的directive方法。可以在任意组件中使用</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> // 局部指令 </div> <div class="ql-code-block"> directives: { </div> <div class="ql-code-block"> focus: { </div> <div class="ql-code-block"> mounted(el, bindings, vnode, preVnode) { </div> <div class="ql-code-block"> console.log(bindings, vnode, preVnode, "focus mounted"); </div> <div class="ql-code-block"> el.focus(); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> // 全局指令 </div> <div class="ql-code-block"> app.directive("focus", { </div> <div class="ql-code-block"> mounted(el, bindings, vnode, preVnode) { </div> <div class="ql-code-block"> console.log("focus mounted"); </div> <div class="ql-code-block"> el.focus(); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }) </div> </div> <p><strong>一个指令定义的对象,Vue提供了如下的几个钩子函数:</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>created:在绑定元素的attribute或事件监听器被应用之前调用;</li> <li data-list="bullet"><span class="ql-ui"></span>beforeMount:当指令第一次绑定到元素并且在挂载父组件之前调用;</li> <li data-list="bullet"><span class="ql-ui"></span>mounted:在绑定元素的父组件被挂载后调用;</li> <li data-list="bullet"><span class="ql-ui"></span>beforeUpdate:在更新包含组件的VNode之前调用;</li> <li data-list="bullet"><span class="ql-ui"></span>updated:在包含组件的VNode及其子组件的VNode更新后调用;</li> <li data-list="bullet"><span class="ql-ui"></span>beforeUnmount:在卸载绑定元素的父组件之前调用;</li> <li data-list="bullet"><span class="ql-ui"></span>unmounted:当指令与元素解除绑定且父组件已卸载时,只调用一次;</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">自定义指令的参数和修饰符</strong></h4> <p><br></p> <div class="ql-code-block-container"> <div class="ql-code-block"> <button v-if="counter < 2" v-why:info.aaaa-bbbb="'coderwhy'" >当前计数: {{counter}}</button> </div> </div> <ol> <li data-list="bullet"><span class="ql-ui"></span>info是参数名称</li> <li data-list="bullet"><span class="ql-ui"></span>aaa-bbb是修饰符的名称</li> <li data-list="bullet"><span class="ql-ui"></span>后面传入具体的值</li> <li data-list="bullet"><span class="ql-ui"></span>在生命周期中,我们可以通过bingings获取到对应的内容</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">认识Teleport</strong></h4> <h5><strong style="color: rgb(51, 51, 51);">为了解决?</strong></h5> <p><br></p> <p>在组件开发中,我们封装一个组件A,在另一个组件B中使用,组件A中template的元素,会被挂载到组件B中template的某个位置,但是某些情况下,我们希望组件不是挂载在这个组件树上的,可能是移动到Vue app之外的其他位置,例如移动到body元素上</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">是什么?</strong></h5> <p><br></p> <p>他是一个Vue提供的内置组件,类似React的Portals</p> <p>它有两个属性:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>to:指定将其内容移动到的目标元素,可以使用选择器;</li> <li data-list="bullet"><span class="ql-ui"></span>disabled:是否禁用teleport的功能;</li> </ol> <p><br></p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">getCurrentInstance</strong></h4> <p><br></p> <p>用户获取全局属性(在setup中没有this) 官方说的是 : 支持访问内部组件实例</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> import { getCurrentInstance } from "vue"; </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> setup() { </div> <div class="ql-code-block"> const instance = getCurrentInstance(); </div> <div class="ql-code-block"> console.log(instance.appContext.config.globalProperties.$name); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> mounted() { </div> <div class="ql-code-block"> console.log(this.$name); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> methods: { </div> <div class="ql-code-block"> foo() { </div> <div class="ql-code-block"> console.log(this.$name); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">Vue插件</strong></h4> <p><br></p> <p>通常我们向Vue全局添加一些功能,会采用插件的模式,写法有两种:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>对象类型:一个对象,但是必须包含一个install函数,该函数会在安装插件时执行,</li> <li data-list="bullet"><span class="ql-ui"></span>函数类型:一个function,这个函数会在安装插件时自动执行,</li> </ol> <p>插件功能没有限制,比如一下几种都可以:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>添加全局方法或者property,通过把他们添加到config.globalProperties上实现;</li> <li data-list="bullet"><span class="ql-ui"></span>添加全局资源:指令,过滤器,过渡等;</li> <li data-list="bullet"><span class="ql-ui"></span>通过全局mixin来添加一些组件选项;</li> <li data-list="bullet"><span class="ql-ui"></span>一个库,提供自己的API,同时提供上面提到的一个或多个功能</li> </ol> <p><img src="https://pic.code-nav.cn/planet_post_image/1619930914211520514/p5vzwu1p.jpeg"></p> <p><br></p> </div> </body> </html>
coderwhy的vue3课程笔记02-组合式API
<html> <head></head> <body> <div class="content ql-editor"> <p><br></p> <h2><strong style="color: rgb(51, 51, 51);">组合式API</strong></h2> <h4><strong style="color: rgb(51, 51, 51);">产生背景</strong></h4> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>在Vue2中,我们编写组件的方式是Options API :也就是在对应的属性中编写对应的功能模块;例如:data定义数据, methiods中定义方法,computed中定义计算属性;watch中监听属性的变化;也包括生命周期钩子</li> <li data-list="bullet"><span class="ql-ui"></span>但是这种代码有弊端:当我们实现某一个功能;这个功能对应的代码逻辑会被拆分到各个属性中;当我们组件变大变复杂后,同一个功能的逻辑就会被拆分的很分散;尤其是在后期维护上,对用对于一个没有编写过这个代码的人来说;</li> <li data-list="bullet"><span class="ql-ui"></span>所以我们就想要把同一个逻辑关注点相关的代码收集在一起;这也就是Composition API要帮我们做的事情,也有人把Vue Composition API 称为VCA</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">Composition API是什么?</strong></h4> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>如果我们想要使用Ccomposition API 那么我们首先需要一个环境(实际使用它编写代码的地方),在Vue组件中,这个位置就是setup函数</li> <li data-list="bullet"><span class="ql-ui"></span>setup其实就是组件的另外一个选项:只不过这个选项强大到可以我们用它来替代之前所编写的大部分其他选项;如methods、computed、watch、data、生命周期等等</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">setup函数的参数</strong></h4> <p><br></p> <p><strong>他的第一个参数: props</strong></p> <p>props非常好理解,它其实就父组件传递过来的属性会被放到props对象,如果我们在setup中需要使用,我们可以直接通过props参数获取</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>对于定义props类型。和之前一样</li> <li data-list="bullet"><span class="ql-ui"></span>在template中依然可以正常使用props中属性,如message</li> <li data-list="bullet"><span class="ql-ui"></span>注意:我们在setup函数中想要使用props,我们不可用通过this去获取 因为props有直接作为参数传递到setup函数中,所有我们可以直接通过参数获取使用</li> </ol> <p><strong>另外一个参数:context</strong></p> <p>我们也称之为是一个SetupContext, 它里面包含三个属性:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>attrs:所有的非prop的attribute</li> <li data-list="bullet"><span class="ql-ui"></span>slots: 父组件传递过来的插槽(这个在以渲染函数返回时会有作用)</li> <li data-list="bullet"><span class="ql-ui"></span>emit : 当我们组件内部需要发出事件时会用到emit(因为我们不能访问this,所以不可用通过this.$emit发出事件)</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">setup函数的返回值</strong></h4> <p><br></p> <p>setup既然是一个函数,那么它也可以有返回值,它的返回值的作用有:</p> <ol> <li data-list="ordered"><span class="ql-ui"></span>可以在模板template中被使用;</li> <li data-list="ordered"><span class="ql-ui"></span>也就是说我们可以通过setup的返回值来代替data的选项</li> <li data-list="ordered"><span class="ql-ui"></span>甚至是我们可以返回一个执行函数来代替在methods中定义的方法</li> </ol> <p>注意:我们定义的变量,然后再定义方法改变变量,是不能实现页面响应式刷新的,这是因为默认情况下,我们定义一个变量,Vue并不会跟踪它的变化来引起页面的响应式</p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">setup不可用使用this</strong></h4> <p><br></p> <p>官方表示:this并没有指向当前组件实例,并且在setup被调用指点,data、computed 、 methods等都没有被解析,所以无法在setup中获取this</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">Reactive API</strong></h5> <p><br></p> <p>如果我们想要在setup中定义的数据提供响应式的特性,那么我们可以使用reactive的函数:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>当我们使用reactive函数处理我们的数据之后,数据再次被使用就会进行依赖收集</li> <li data-list="bullet"><span class="ql-ui"></span>当数据发生变化,所有收集到的依赖都是进行对应的响应式操作</li> <li data-list="bullet"><span class="ql-ui"></span>事实上,我们编写的data选项,也是在内部交给了reactive函数将其编程为响应式对象的</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">Ref API</strong></h4> <p><br></p> <p>因为reactive API对传入类型是有限制的,它要求我们必须传入的是一个对象或者数组类型:如果我们传入的是基本类型 vue会给出警告</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>vue3给我们提供了另外的API ref API ;ref 会返回一个可变的响应式对象,该对象作为一个响应式的引用维护着它内部的值,这也是ref名称的来源;它内部的值是在ref的value属性中被维护的</li> <li data-list="bullet"><span class="ql-ui"></span>注意:</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>在模板引入ref的值时,Vue会帮助我们进行解包操作,所以我们并不需要在模板中通过<a href="http://ref.value" target="_blank">ref.value</a>来使用ref(这里是将ref放入reactive属性中 如果不是放在reactive属性中就需要<a href="http://ref.value" target="_blank">ref.value</a>)</li> <li data-list="bullet" class="ql-indent-1"><span class="ql-ui"></span>但是在setup函数内部,它依然是一个ref引用,我们使用需要使用<a href="http://ref.value" target="_blank">ref.value</a></li> </ol> <p><br></p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">readonly</strong></h4> <p><br></p> <p>我们通过reactive或者ref可以获取到一个响应式的对象,但是在某些情况下,我们需要把这个数据传入到其他地方(组件)中使用,但是我们希望它不能被修改</p> <p>vue3为我们提供了readonly的方法,readonly会返回原生对象的只读代理(它是一个Proxy,这是一个proxy的set方法被劫持;不能对其进行修改)</p> <p>使用:</p> <p>在开发中我们通常会把readonly方法传入三个类型的参数:普通对象;reactive返回的对象;ref对象</p> <p>使用规则:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>readonly返回的对象都是不允许修改的;</li> <li data-list="bullet"><span class="ql-ui"></span>但是经过readonly处理的原来的对象是允许被修改的;</li> <li data-list="bullet"><span class="ql-ui"></span>本质上就是readonly返回的对象的setter方法被劫持了</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">Reactive判断的API</strong></h4> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>isProxy : 检查对象是否是由reactive或readonly创建的proxy</li> <li data-list="bullet"><span class="ql-ui"></span>isReactive: 检查对象是否是由reactive创建的响应式代理;如果该代理是readonly建的,但包裹了由reacive创建的另一个代理,它也会返回true</li> <li data-list="bullet"><span class="ql-ui"></span>isReadonly: 检查对象是否是由readonly创建的只读代理</li> <li data-list="bullet"><span class="ql-ui"></span>toRaw: 返回reactive或readonly代理的原始对象(不建议保留对原始对象的持久引用)</li> <li data-list="bullet"><span class="ql-ui"></span>shallowReactive:创建一个响应式代理,它跟踪其自身property的响应式,但不执行嵌套对象的深层响应式转换(深层还是原生对象)</li> <li data-list="bullet"><span class="ql-ui"></span>shallowReadonly: 创建一个proxy,使其自身的property为只读,但不执行嵌套对象的深度只读转换(深沉还是可读,可写的)</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">toRefs</strong></h4> <p><br></p> <p>如果我们使用ES6的解构对象,对reactive返回的对象进行解构获取值,那么无论是修改解构后的变量,还是修改reactive返回的state对象,数据都不再是响应式的</p> <p>那么我们如果想要解构出reactive返回的值而且还想要响应式,可以使用toRefs的函数,可以将reactive返回的对象中的属性都转成ref</p> <div class="ql-code-block-container"> <div class="ql-code-block"> const state = reactive({ </div> <div class="ql-code-block"> name: "why", </div> <div class="ql-code-block"> age: 18 </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> const {name, age} = toRefs(state) </div> </div> <p>这样 解构出来的name个age本身都是ref了, 这样的做法相当于已经在<a href="http://state.name" target="_blank">state.name</a>和<a href="http://ref.value" target="_blank">ref.value</a>之间建立链接,任何一个修改都会引起另一个变化</p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">ref的其他API</strong></h4> <p><br></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>unref :如果我们想要获取一个ref引用中的value,那么也可以通过unref方法</li> <li data-list="bullet"><span class="ql-ui"></span>它接收一个值,如果参数是一个ref 则返回内部value,否则返回参数本身;它其实是一个语法糖,它做的事情就是val = isRef(val) ? <a href="http://val.value" target="_blank">val.value</a> : value 其中isRef是判断一个值是否是一个ref对象</li> <li data-list="bullet"><span class="ql-ui"></span>shallowRef : 创建一个浅层的ref对象</li> <li data-list="bullet"><span class="ql-ui"></span>triggerRef : 手动触发和shallowRef相关联的副作用</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">customRef</strong></h4> <p><br></p> <p>创建一个自定义的ref,并对其依赖项跟踪和更新触发进行显示控制:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>它需要一个工厂函数,该函数接受track和trigger函数作为参数 其中track()是告诉Vue这个value值是需要被跟踪的,trigger()是告诉vue去更新页面</li> <li data-list="bullet"><span class="ql-ui"></span>并且返回一个带有get和set的对象;</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> //useDebounceRef.js文件 </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> import { customRef } from 'vue'; </div> <div class="ql-code-block"> // 自定义ref 接收的value是一个字符串 </div> <div class="ql-code-block"> export default function(value, delay = 300) { </div> <div class="ql-code-block"> let timer = null; </div> <div class="ql-code-block"> return customRef((track, trigger) => { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> get() { </div> <div class="ql-code-block"> track(); </div> <div class="ql-code-block"> return value; </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> set(newValue) { </div> <div class="ql-code-block"> clearTimeout(timer); </div> <div class="ql-code-block"> timer = setTimeout(() => { </div> <div class="ql-code-block"> value = newValue; </div> <div class="ql-code-block"> trigger(); </div> <div class="ql-code-block"> }, delay); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> <div class="ql-code-block"> // 示例 </div> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <div> </div> <div class="ql-code-block"> <input v-model="message"/> </div> <div class="ql-code-block"> <h2>{{message}}</h2> </div> <div class="ql-code-block"> </div> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> import debounceRef from './hook/useDebounceRef'; </div> <div class="ql-code-block"> export default { </div> <div class="ql-code-block"> setup() { </div> <div class="ql-code-block"> const message = debounceRef("Hello World"); </div> <div class="ql-code-block"> return {message}}} </div> <div class="ql-code-block"> </script> </div> <div class="ql-code-block"> <style scoped> </div> <div class="ql-code-block"> </style> </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">computed</strong></h4> <p><br></p> <p><strong>是什么?</strong></p> <p>计算属性:当我们的某些属性是依赖其他状态转化得到,我们就可以使用计算属性来实现</p> <p><strong>怎么实现?</strong></p> <p>在组合式API,我们使用computed选项来完成的</p> <div class="ql-code-block-container"> <div class="ql-code-block"> const firstName = ref("Kobe"); </div> <div class="ql-code-block"> const lastName = ref("Bryant"); </div> <div class="ql-code-block"> // 1.用法一: 传入一个getter函数 </div> <div class="ql-code-block"> // computed的返回值是一个ref对象 </div> <div class="ql-code-block"> const fullName = computed(() => firstName.value + " " + lastName.value); </div> <div class="ql-code-block"> // 2.用法二: 传入一个对象, 对象包含getter/setter,返回一个可读写的ref对象 </div> <div class="ql-code-block"> const fullName1 = computed({ </div> <div class="ql-code-block"> get: () => firstName.value + " " + lastName.value, </div> <div class="ql-code-block"> set(newValue) { </div> <div class="ql-code-block"> const names = newValue.split(" "); </div> <div class="ql-code-block"> firstName.value = names[0]; </div> <div class="ql-code-block"> lastName.value = names[1]; </div> <div class="ql-code-block"> } </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">侦听数据的变化</strong></h4> <p><br></p> <p><strong>作用:</strong></p> <p>我们可以通过watch选项来侦听data或者props的数据变化,当数据变化时执行操作</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">1. watchEffect</strong></h5> <p><br></p> <p>当侦听到某些响应式数据变化时,我们希望执行某些操作,</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>首先,watchEffect传入的函数会被立即执行,并且在执行过程中收集依赖</li> <li data-list="bullet"><span class="ql-ui"></span>其次,只有当收集的依赖变化时,watchEffect传入的函数才会执行</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> const name = ref("why"); </div> <div class="ql-code-block"> const stop = watchEffect(() => { </div> <div class="ql-code-block"> console.log("name:", name.value); </div> <div class="ql-code-block"> }); </div> <div class="ql-code-block"> // 我们运行 stop();就会停止侦听 </div> </div> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">2. watchEffect清除副作用</strong></h5> <p><br></p> <p>在开发中,我们需要在侦听函数中执行网络请求,但是网络请求还没有到达的时候,我们停止了侦听,或者侦听器函数被再次执行了,为了解决这种问题,</p> <p><br></p> <p>在我们给watchEffect传入的函数被回调时,我们可以从回调函数中,获取一个参数:onInvalidate,当副作用即将重新执行或者侦听器被停止时会执行该函数传入的回调函数,我们可以在传入的回调函数中,执行一些清除工作</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> const name = ref("why"); </div> <div class="ql-code-block"> const age = ref(18); </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> const stop = watchEffect((onInvalidate) => { </div> <div class="ql-code-block"> const timer = setTimeout(() => { </div> <div class="ql-code-block"> console.log("网络请求成功~"); </div> <div class="ql-code-block"> }, 2000) </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 根据name和age两个变量发送网络请求 </div> <div class="ql-code-block"> onInvalidate(() => { </div> <div class="ql-code-block"> // 在这个函数中清除额外的副作用 </div> <div class="ql-code-block"> // request.cancel() </div> <div class="ql-code-block"> clearTimeout(timer); </div> <div class="ql-code-block"> console.log("onInvalidate"); </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> console.log("name:", name.value, "age:", age.value); </div> <div class="ql-code-block"> }); </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">使用ref获取元素或者组件</strong></h4> <h5><strong style="color: rgb(51, 51, 51);">使用:</strong></h5> <p><br></p> <p>我们定义一个ref对象,绑定到元素或者组件的ref的属性上即可;</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <template> </div> <div class="ql-code-block"> <div> </div> <div class="ql-code-block"> <h2 ref="titleRef">这里是一个title</h2> </div> <div class="ql-code-block"> </div> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> setup(){ </div> <div class="ql-code-block"> const titieRef = ref(null) </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> titleRef </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">watchEffect的执行时机</strong></h4> <h5><strong style="color: rgb(51, 51, 51);">执行时机:</strong></h5> <p><br></p> <p>setup函数在执行时就会立即执行一次watchEffect的副作用函数,这个时候DOM并没有挂载,所有打印的一定是null,而当DOM挂载时,watchEffect的依赖会变化,副作用就会再次执行,打印出对应的内容</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">调整执行时机:</strong></h5> <p><br></p> <p>如果我们不希望第一次的执行,我们需要改变副作用的执行时机,那么我们需要修改watchEffect的第二个参数,是一个对象,默认是{flush: "pre"},我们可以修改成{flush: "post"}这样就可以实现我们想要的效果</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> const title = ref(null); </div> <div class="ql-code-block"> const demo = ref(null); </div> <div class="ql-code-block"> const stop= watchEffect(() => { </div> <div class="ql-code-block"> console.log(title.value, demo.value); </div> <div class="ql-code-block"> }, { </div> <div class="ql-code-block"> flush: "post" </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> // stop()可以停止侦听 </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">watch的使用</strong></h4> <p><br></p> <div class="ql-code-block-container"> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> setup() { </div> <div class="ql-code-block"> const info = reactive({name: "why", age: 18}); </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 1.侦听watch时,传入一个getter函数 </div> <div class="ql-code-block"> watch(() => info.name, (newValue, oldValue) => { </div> <div class="ql-code-block"> console.log("newValue:", newValue, "oldValue:", oldValue); </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 2.传入一个可响应式对象: reactive对象/ref对象 </div> <div class="ql-code-block"> // 情况一: reactive对象获取到的newValue和oldValue本身都是reactive对象 </div> <div class="ql-code-block"> watch(info, (newValue, oldValue) => { </div> <div class="ql-code-block"> console.log("newValue:", newValue, "oldValue:", oldValue,'ssss'); </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> // 如果希望newValue和oldValue是一个普通的对象 </div> <div class="ql-code-block"> watch(() => { </div> <div class="ql-code-block"> return {...info} </div> <div class="ql-code-block"> }, (newValue, oldValue) => { </div> <div class="ql-code-block"> console.log("newValue:", newValue, "oldValue:", oldValue, "oldValue:"); </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> // 情况二: ref对象获取newValue和oldValue是value值的本身 </div> <div class="ql-code-block"> // const name = ref("why"); </div> <div class="ql-code-block"> // watch(name, (newValue, oldValue) => { </div> <div class="ql-code-block"> // console.log("newValue:", newValue, "oldValue:", oldValue); </div> <div class="ql-code-block"> // }) </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> const changeData = () => { </div> <div class="ql-code-block"> info.name = "kobe"; </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 1.定义可响应式的对象 </div> <div class="ql-code-block"> const info = reactive({name: "why", age: 18}); </div> <div class="ql-code-block"> const name = ref("why"); </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 2.侦听器watch </div> <div class="ql-code-block"> watch([() => ({...info}), name], ([newInfo, newName], [oldInfo, oldName]) => { </div> <div class="ql-code-block"> console.log(newInfo, newName, oldInfo, oldName); </div> <div class="ql-code-block"> },{ </div> <div class="ql-code-block"> deep: true, </div> <div class="ql-code-block"> immediate: true </div> <div class="ql-code-block"> }) </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> changeData, </div> <div class="ql-code-block"> info </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> </script> </div> </div> <p>从上面代码中,可以知道watch的第一个参数,可以是 回调函数(返回值是我们监听的对象),可以是一个值,可以是一个数组,第二个参数是一个回调函数,当依赖发生变化它会执行,第三个参数是一个对象,可以修改它的一些执行时机</p> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">它与watchEffect的区别</strong></h5> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>它是懒执行副作用,即只有当侦听的源发生变化它才会执行回调函数;</li> <li data-list="ordered"><span class="ql-ui"></span>更加明确的说明说明状态应该触发侦听器的重新运行;</li> <li data-list="ordered"><span class="ql-ui"></span>可以访问侦听前后的值</li> </ol> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">JSX的babel配置</strong></h4> <p><br></p> <p>如果我们能在项目中使用jsx,那么我们需要添加对jsx的支持;jsx我们通常会通过babel进行转换(react也是)</p> <p>对于vue 我们只需要在Babel中配置对应的插件既可</p> <div class="ql-code-block-container"> <div class="ql-code-block"> npm install @vue/babel-plugin-jsx -D </div> <div class="ql-code-block"> //在babel.config.js文件配置插件 </div> <div class="ql-code-block"> module.exports = { </div> <div class="ql-code-block"> presets:[ </div> <div class="ql-code-block"> '@vue/cli-plugin-bable/preset' </div> <div class="ql-code-block"> ], </div> <div class="ql-code-block"> plugins: [ </div> <div class="ql-code-block"> "@vue/babel-plugin-jsx" </div> <div class="ql-code-block"> ] </div> <div class="ql-code-block"> } </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">组合式API中的Provide和Inject</strong></h4> <p><br></p> <div class="ql-code-block-container"> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> // 父组件中,我们通过Provide来创建数据 </div> <div class="ql-code-block"> import { provide } from 'vue'; </div> <div class="ql-code-block"> const name = ref("coderwhy"); </div> <div class="ql-code-block"> let counter = ref(100); </div> <div class="ql-code-block"> provide("name", readonly(name)); </div> <div class="ql-code-block"> provide("counter", readonly(counter)); </div> <div class="ql-code-block"> // 子组件通过Inject来获取父组件的值 </div> <div class="ql-code-block"> import { inject } from 'vue'; </div> <div class="ql-code-block"> const name = inject("name"); </div> <div class="ql-code-block"> const counter = inject("counter"); </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> <h5><strong style="color: rgb(51, 51, 51);">注意:</strong></h5> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>我们可以在provide值时使用ref和reactive来增加provide值和inject值之间的响应性, 这样父组件修改保存到provide的值,子组件也会接收到变化</li> <li data-list="ordered"><span class="ql-ui"></span>provide可以传入两个参数:</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>name:提供的属性名称</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>value:提供对应的属性值</li> <li data-list="ordered"><span class="ql-ui"></span>inject可以传入两个参数:</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>要inject的property的name</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>默认值</li> <li data-list="ordered"><span class="ql-ui"></span>我们需要修改可响应的值,那么我们最好在数据提供处来进行修改,并把修改写成一个方法,并暴露出去给子组件使用</li> </ol> <p><br></p> </div> </body> </html>
coderwhy的vue3课程笔记01-基础预语法
<html> <head></head> <body> <div class="content ql-editor"> <p>课程资源地址:百度网盘</p> <p>链接:https://pan.baidu.com/s/1GlPOgb1yv6HJrp_GWQ8ZFg?pwd=fo3w</p> <p>提取码:fo3w</p> <p>--来自百度网盘超级会员V6的分享</p> <h4><strong style="color: rgb(51, 51, 51);">v-once:用于指定元素或者组件只渲染一次</strong></h4> <p><br></p> <p>当数据发生变化时,元素或者组件以及其所有的子元素将视为静态内容并且跳过;用于<strong>性能优化</strong></p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">v-bind: 动态绑定一个或多个attribute(ps:属性), 或者向另一个组件传递props值</strong></h4> <p><br></p> <p>v-bind的语法糖是 :</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <img v-bind:src='src' alt='' /> </div> <div class="ql-code-block"> <img :src='src' /> </div> <div class="ql-code-block"> // 其他写法 </div> <div class="ql-code-block"> <div :[name]="value">哈哈哈</div> </div> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> name: "cba", </div> <div class="ql-code-block"> value: "kobe" </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> <div :="info">哈哈哈哈</div> </div> <div class="ql-code-block"> info: { </div> <div class="ql-code-block"> name: "why", </div> <div class="ql-code-block"> age: 18, </div> <div class="ql-code-block"> height: 1.88 </div> <div class="ql-code-block"> } </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">v-on :绑定事件</strong></h4> <p><br></p> <p>前面我们绑定了元素的内容和属性,在前端开发中另外一个非常重要的特性就是交互 , 所以vue是使用v-on来实现事件监听</p> <p><strong>v-on的使用:</strong></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>缩写 :·@</li> <li data-list="ordered"><span class="ql-ui"></span> 参数:event</li> <li data-list="ordered"><span class="ql-ui"></span>修饰符:</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>stop- 调用 event.stopPropagation()</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.prevent - 调用 event.preventDefault()。</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.capture-添加事件侦听器时使用capture模式。</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.self - 只当事件是从侦听器绑定的元素本身触发时才触发回调。.{keyAlias}- 仅当事件是从特定键触发时才触发回调。</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.once - :只触发一次回调。</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.left - 只当点击鼠标左键时触发。</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.right - 只当点击鼠标右键时触发。</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.middle - 只当点击鼠标中键时触发。</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>.passive-{ passive: true }模式添加侦听器☐ 用法:绑定事件监听</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> <button v-on:click="btn1Click($event,'syh')">按钮1</button> </div> <div class="ql-code-block"> <div class="area" v-on:mousemove="mouseMove">div</div> </div> <div class="ql-code-block"> <div class="area" @="{click: btn1Click, mousemove: mouseMove}"></div> </div> <div class="ql-code-block"> methods: { </div> <div class="ql-code-block"> btn1Click() { </div> <div class="ql-code-block"> console.log("按钮1发生了点击"); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> mouseMove() { </div> <div class="ql-code-block"> console.log("鼠标移动"); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">v-show和 v-if的区别</strong></h4> <p><br></p> <p><strong>首先</strong></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>v-show是不支持template</li> <li data-list="ordered"><span class="ql-ui"></span>v-show不可用和v-else一起使用;</li> </ol> <p><strong>其次,本质的区别:</strong></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>v-show元素无论是否需要显示。它的Dom实际上都存在</li> <li data-list="ordered"><span class="ql-ui"></span>v-if当条件为false的时候;其对应的原生压根不会渲染到dom中</li> </ol> <p><strong>最后;使用场景</strong></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>如果我们的原生需要在显示和隐藏之间频繁的切换,那么使用v-show否则就使用v-if</li> </ol> <p><strong>注意: </strong></p> <p>因为v-if是一个指令,所有必须将其添加到一个元素上;但是我们切换的是多个元素呢?这个时候我们就可以使用template</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <template v-if="isShowHa"> </div> <div class="ql-code-block"> <h2>哈哈哈哈</h2> </div> <div class="ql-code-block"> <h2>哈哈哈哈</h2> </div> <div class="ql-code-block"> <h2>哈哈哈哈</h2> </div> <div class="ql-code-block"> </template> </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">v-for列表渲染</strong></h4> <p><br></p> <p><strong>基本使用</strong></p> <p>基本格式是: item in arr</p> <p>item是我们给每项元素起的一个别名, arr是数组名称</p> <p>当我们遍历一个数组的时候有时候会需要拿到数组的索引</p> <p>我们可以使用格式:(item, index) in arr;</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <template id="my-app"> </div> <div class="ql-code-block"> <h2>电影列表</h2> </div> <div class="ql-code-block"> <ul> </div> <div class="ql-code-block"> <!-- 遍历数组 --> </div> <div class="ql-code-block"> <li v-for="(movie, index) in movies">{{index+1}}.{{movie}}</li> </div> <div class="ql-code-block"> </ul> </div> <div class="ql-code-block"> <h2>个人信息</h2> </div> <div class="ql-code-block"> <ul> </div> <div class="ql-code-block"> <!-- 遍历对象 --> </div> <div class="ql-code-block"> <li v-for="(value, key, index) in info">{{value}}-{{key}}-{{index}}</li> </div> <div class="ql-code-block"> </ul> </div> <div class="ql-code-block"> <h2>遍历数字</h2> </div> <div class="ql-code-block"> <ul> </div> <div class="ql-code-block"> <li v-for="(num, index) in 10">{{num}}-{{index}}</li> </div> <div class="ql-code-block"> </ul> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> const App = { </div> <div class="ql-code-block"> template: '#my-app', </div> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> movies: [ </div> <div class="ql-code-block"> "星际穿越", </div> <div class="ql-code-block"> "盗梦空间", </div> <div class="ql-code-block"> "大话西游", </div> <div class="ql-code-block"> "教父", </div> <div class="ql-code-block"> "少年派" </div> <div class="ql-code-block"> ], </div> <div class="ql-code-block"> info: { </div> <div class="ql-code-block"> name: "why", </div> <div class="ql-code-block"> age: 18, </div> <div class="ql-code-block"> height: 1.88 </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> </div> <p><img src="https://pic.code-nav.cn/planet_post_image/1619930914211520514/bj2mdzpi.jpeg"></p> <h3><strong style="color: rgb(51, 51, 51);">注意:</strong></h3> <p><br></p> <p>当我们需要循环(v-for)包括多个元素或者判断包括多个元素(v-if)的时候,我们可以使用templete来包裹这多个元素。</p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">vue对原生数组的封装(使用其方法会触发ui变化)</strong></h4> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>push()``pop() shift() unshift()``splice() sort() reverse() 上面的是直接改变原生数组</li> <li data-list="ordered"><span class="ql-ui"></span>filter() concat() slice() 不会改变原数组</li> </ol> <p><br></p> <h3><strong style="color: rgb(51, 51, 51);">Vue3的Options-API</strong></h3> <p><br></p> <p>在实际开发中,我们会遇到一些情况,比如我们可能需要<strong>对数据进行一些转化</strong>后再显示,或将<strong>多个数据结合起来</strong>进行显示;如果把这些逻辑直接写在template中,这样就会使得UI里放逻辑,就违背了vue设计的愿景, 这个时候compute计算属性就产生了</p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">computed 计算属性</strong></h4> <p><br></p> <p>对于任何响应式数据的复杂逻辑,都应该放在使用computed</p> <p>计算属性将被混入到组件实例中。所有getter和setter的上下文自动绑定为组件实例</p> <p><strong>使用方法:</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> firstName: "Kobe", </div> <div class="ql-code-block"> lastName: "Bryant", </div> <div class="ql-code-block"> score: 80, </div> <div class="ql-code-block"> message: "Hello World" </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> computed: { </div> <div class="ql-code-block"> // 定义了一个计算属性叫fullname </div> <div class="ql-code-block"> fullName() { </div> <div class="ql-code-block"> return this.firstName + " " + this.lastName; </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> result() { </div> <div class="ql-code-block"> return this.score >= 60 ? "及格": "不及格"; </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> reverseMessage() { </div> <div class="ql-code-block"> return this.message.split(" ").reverse().join(" "); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> } </div> </div> <p><br></p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">watch 监听器</strong></h4> <p><br></p> <p>我理解为当data变化后watch定义的函数来执行data变化产生的副作用</p> <p><strong>使用:</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> // 侦听question的变化时, 去进行一些逻辑的处理(JavaScript, 网络请求) </div> <div class="ql-code-block"> question: "Hello World", </div> <div class="ql-code-block"> anwser: "" </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> watch: { </div> <div class="ql-code-block"> // question侦听的data中的属性的名称 </div> <div class="ql-code-block"> // newValue变化后的新值 </div> <div class="ql-code-block"> // oldValue变化前的旧值 </div> <div class="ql-code-block"> question: function(newValue, oldValue) { </div> <div class="ql-code-block"> console.log("新值: ", newValue, "旧值", oldValue); </div> <div class="ql-code-block"> this.queryAnswer(); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> </div> <p><strong>监听器watch的配置选项:</strong></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>watch只是在侦听info的引用变化,对于内部属性的变化说不会做出相应的,我们可以使用选项deep进行更深层的侦听;</li> <li data-list="ordered"><span class="ql-ui"></span>另外一个属性,是希望一开始就会立即执行一次:</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>这个时候我们使用immediate选项</li> <li data-list="ordered" class="ql-indent-1"><span class="ql-ui"></span>这个时候无论后面的数据是否有变化,侦听的函数都会有限执行一次;</li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> watch: { </div> <div class="ql-code-block"> // 默认情况下我们的侦听器只会针对监听的数据本身的改变(内部发生的改变是不能侦听) </div> <div class="ql-code-block"> // info(newInfo, oldInfo) { </div> <div class="ql-code-block"> // console.log("newValue:", newInfo, "oldValue:", oldInfo); </div> <div class="ql-code-block"> // } </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 深度侦听/立即执行(一定会执行一次) </div> <div class="ql-code-block"> info: { </div> <div class="ql-code-block"> handler: function(newInfo, oldInfo) { </div> <div class="ql-code-block"> console.log("newValue:", newInfo.nba.name, "oldValue:", oldInfo.nba.name); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> deep: true, // 深度侦听 </div> <div class="ql-code-block"> // immediate: true // 立即执行 </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> //也可以监听info的属性 </div> <div class="ql-code-block"> 'info.name': function(){ </div> <div class="ql-code-block"> console.log(this.info.name, 'info.name'); </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> }, </div> </div> <p><strong>watch的其他使用方法</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> const unwatch = this.$watch("info", function(newInfo, oldInfo) { </div> <div class="ql-code-block"> console.log(newInfo, oldInfo); </div> <div class="ql-code-block"> }, { </div> <div class="ql-code-block"> deep: true, </div> <div class="ql-code-block"> immediate: true </div> <div class="ql-code-block"> }) </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">v-model绑定表单数据</strong></h4> <p><br></p> <ol> <li data-list="ordered"><span class="ql-ui"></span>v-model指令可以在表单 input,textarea以及select元素上创建双向数据绑定,</li> <li data-list="ordered"><span class="ql-ui"></span>它会根据控件类型自动选择正确的方法来更新元素</li> <li data-list="ordered"><span class="ql-ui"></span>v-model本质上是语法糖,它负责监听用户的输入事件来更新数据,并在极端场景下进行一些特殊处理;</li> </ol> <p><strong>v-model的原理 :两个操作</strong></p> <ol> <li data-list="bullet"><span class="ql-ui"></span>v-bind绑定value属性的值;</li> <li data-list="bullet"><span class="ql-ui"></span>v-on绑定input事件监听到函数中,函数会获取最新的值赋值到绑定的属性中</li> </ol> <p><strong>具体使用</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> //绑定textarea article是一个字符串 </div> <div class="ql-code-block"> <textarea v-model="article"> </textarea> </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> //绑定checkbox -单个勾选框 isAgree是一个布尔值 </div> <div class="ql-code-block"> <input id='agreement' type="checkbox" v-model="isAgree" /> </div> <div class="ql-code-block"> //绑定checkbox -多个复选框 hobbies是一个数组 </div> <div class="ql-code-block"> <label for="basketball"> </div> <div class="ql-code-block"> <input id="basketball" type="checkbox" v-model="hobbies" value="basketball"> 篮球 </div> <div class="ql-code-block"> </label> </div> <div class="ql-code-block"> <label for="football"> </div> <div class="ql-code-block"> <input id="football" type="checkbox" v-model="hobbies" value="football"> 足球 </div> <div class="ql-code-block"> </label> </div> <div class="ql-code-block"> <label for="tennis"> </div> <div class="ql-code-block"> <input id="tennis" type="checkbox" v-model="hobbies" value="tennis"> 网球 </div> <div class="ql-code-block"> </label> </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> //radio gender是一个字符串 是input的value </div> <div class="ql-code-block"> <label for="male"> </div> <div class="ql-code-block"> <input id="male" type="radio" v-model="gender" value="male">男 </div> <div class="ql-code-block"> </label> </div> <div class="ql-code-block"> <label for="female"> </div> <div class="ql-code-block"> <input id="female" type="radio" v-model="gender" value="female">女 </div> <div class="ql-code-block"> </label> </div> <div class="ql-code-block"> </div> <div class="ql-code-block"> // 绑定select fruit是一个字符串的时候就是单选,如果是一个数组就是多选 </div> <div class="ql-code-block"> <select v-model="fruit" multiple size="2"> </div> <div class="ql-code-block"> <option value="apple">苹果</option> </div> <div class="ql-code-block"> <option value="orange">橘子</option> </div> <div class="ql-code-block"> <option value="banana">香蕉</option> </div> <div class="ql-code-block"> </select> </div> </div> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">v-model 的修饰符</strong></h4> <p><br></p> <p><strong>1. -lazy</strong></p> <p>默认情况下,v-model在进行双向绑定时,绑定的是input事件那么每次输入后就会将最新的值和绑定的属性进行同步,如果我们加上lazy符号那么绑定的事件切换为change事件,只有在提交时候才会触发</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <template id="my-app"> </div> <div class="ql-code-block"> <input type ="text" v-model.lazy = "message"> </div> <div class="ql-code-block"> <h2>{{ message }}</h2> </div> <div class="ql-code-block"> </template> </div> </div> <p><strong>2. - number</strong></p> <p>如果我们希望将输入转化为数字,那么就使用.number在可以转化的情况下,会将其转化为number类型</p> <div class="ql-code-block-container"> <div class="ql-code-block"> <input type='text' v-model.number = 'message' /> </div> </div> <p><strong>3. -trim</strong></p> <p>如果要自动过滤掉用户输入的空白字符,可以给v-model后面在上.trim修饰符</p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">组件化开发</strong></h4> <p><br></p> <p><strong>定义一个全局组件</strong></p> <div class="ql-code-block-container"> <div class="ql-code-block"> // 使用app注册一个全局组件app.component() </div> <div class="ql-code-block"> // 全局组件: 意味着注册的这个组件可以在任何的组件模板中使用 </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> app.component("component-a", { </div> <div class="ql-code-block"> template: "#component-a", </div> <div class="ql-code-block"> data() { </div> <div class="ql-code-block"> return { </div> <div class="ql-code-block"> title: "我是标题", </div> <div class="ql-code-block"> desc: "我是内容, 哈哈哈哈哈", </div> <div class="ql-code-block"> }; </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> methods: { </div> <div class="ql-code-block"> btnClick() { </div> <div class="ql-code-block"> console.log("按钮的点击"); </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> }); </div> <div class="ql-code-block"> </script> </div> <div class="ql-code-block"> //模板 </div> <div class="ql-code-block"> <template id="component-a"> </div> <div class="ql-code-block"> <h2>{{title}}</h2> </div> <div class="ql-code-block"> <p>{{desc}}</p> </div> <div class="ql-code-block"> <button @click="btnClick">按钮点击</button> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> // 使用 </div> <div class="ql-code-block"> <component-a></component-a> </div> </div> <p>在通过app.component注册一个组价的时候,第一个参数是组件的名称,第二个是一个对象</p> <p><br></p> <h4><strong style="color: rgb(51, 51, 51);">注册局部组件</strong></h4> <p><br></p> <p>全局组价是在程序一开始就会执行,全局组件就会被注册好, 但是有时候我们的某些组件在刚开始并没有被用到。并且全局组件webpack打包时候也是对其打包,用户在下载对应JavaScript包时候也会增加包的大小</p> <p>所以我们在开发中使用组件应采用<strong>局部注册</strong>:</p> <ol> <li data-list="bullet"><span class="ql-ui"></span>局部注册是在我们需要使用到的组件中,通过component属性选择来进行注册,类似于computed,methods</li> <li data-list="bullet"><span class="ql-ui"></span>该components选项对应的是一个对象,对象中的键值对是 <strong>组件的名称:组件对象</strong></li> </ol> <div class="ql-code-block-container"> <div class="ql-code-block"> <template id="component-a"> </div> <div class="ql-code-block"> <h2>我是组件A</h2> </div> <div class="ql-code-block"> <p>我是内容, 哈哈哈哈</p> </div> <div class="ql-code-block"> </template> </div> <div class="ql-code-block"> <script> </div> <div class="ql-code-block"> const ComponentA = { </div> <div class="ql-code-block"> template: "#component-a" </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> const App = { </div> <div class="ql-code-block"> template: '#my-app', </div> <div class="ql-code-block"> components: { </div> <div class="ql-code-block"> ComponentA: ComponentA </div> <div class="ql-code-block"> }, </div> <div class="ql-code-block"> } </div> <div class="ql-code-block"> const app = Vue.createApp(App); </div> <div class="ql-code-block"> app.mount('#app'); </div> <div class="ql-code-block"> </script> </div> </div> <p><br></p> </div> </body> </html>
友友们,求codewhy前端资源🥺 #求资源#
