营销型企业网站建设体会,wordpress可以建站吗,网站公司备案通知,会计实帐培训1.Vue中路由传参
1.params传参
params 传参是通过URL路径来传递参数#xff0c;这种方式传递的参数是必选的。这种传参方式需要在路由配置时在路由路径位置提前指定参数。
路由配置
const router new VueRouter({routes: [{path: /user/:id, // 这里的:id就是参数name: u…1.Vue中路由传参
1.params传参
params 传参是通过URL路径来传递参数这种方式传递的参数是必选的。这种传参方式需要在路由配置时在路由路径位置提前指定参数。
路由配置
const router new VueRouter({routes: [{path: /user/:id, // 这里的:id就是参数name: user,component: User}]
})路由跳转
// 使用 router.push 跳转
router.push({ name: user, params: { id: 123 }})// 使用 router-link 组件
router-link :to{ name: user, params: { id: 123 }}User/router-link// 使用路径传参
router.push(/user/${id})接收参数 params传递参数可以用过页面路由对象route的params属性访问到。
!-- template --
templatediv{{ $route.params.id}}/div
/template
!-- script setup --
script setupimport { useRoute } from vue-routerconst route useRoute()console.log(route.params.id)
/script2.query传参
query 传参是通过URL的查询字符串来传递参数这种方式传递的参数是可选的。这种方式不需要提前配置路由路径直接在路由跳转时在路径或者配置中传递参数即可。
路由跳转
// 使用 router.push 跳转
this.$router.push({ path: /search, query: { keyword: vue }})// 使用 router-link 组件
router-link :to{ path: /search, query: { keyword: vue }}Search/router-link// 使用路径传参
router.push(/user/?id${id})
接收参数 这种方式传递的参数会挂载到页面路由对象route的query对象上。
!-- template --
templatediv{{ $route.query.id}}/div
/template
!-- script setup --
script setupimport { useRoute } from vue-routerconst route useRoute()console.log(route.query.id)
/script2. hash和history路由区别
hash路由地址上在路径后面带#号history路由地址上不带#号.在刷新界面时hash路由会加载对应页面history路由会报404错误,因此需要在前端服务器作出特殊的配置让其在404错误时直接跳转到首页。这里出现404错误的原因是当访问页面时页面路由只有在vuerouter初始化后才有效因此在这之前是访问不到页面的需要通过服务器将此时的页面指定到入口页面来初始化vuerouter是页面路由生效hash会支持低版本浏览器history只支持高版本浏览器因为其是HTML5新增的API。hash路由不会重新加载页面history路由会重新加载页面。history会有历史记录 HTML5新增了pushState和replaceState方法可以改变url但是不会刷新页面也不会产生历史记录。history是需要服务端配合的hash路由不需要。
3.watch与computed的区别
这里的对比主要是以Vue3的script setup为主
主要功能不同
computed是计算属性watch时监听监听data中的数据变化。computed主要是用于以某一个响应式数据为基础来计算出一个新的数据使用。当依赖的数据变化之后会根据计算结果重新计算值。watch主要用于来侦听某一个响应式数据当数据变化时来执行一些特定的操作。computed更加注重数据不建议在内部做一些副作用或者与数据计算无关的操作。
参数不同
computed接受一个参数参数可以是一个getter函数该函数内部需要至少使用一个响应式函数来计算并返回计算值必须要有返回值。参数也可以是一个配置对象 配置对象包含getset两个方法get方法与上面的getter函数作为参数要求是一样的。watch函数接收三个参数第一个参数可以为getter函数或者一个响应式对象或者是一个包含响应式对象的数据。第二个参数是一个副作用函数用于在watch数据变化后重新执行。第三个参数传入一个配置对象。第二个参数传入的函数会被自动挂载三个参数第一个参数为更新后的新值第二个参数为更新前的旧值第三个参数是一个函数onCleanup用户两次变化之间执行清理工作。
执行效果不同
computed函数在初始化的时候就会执行一次并且会计算出一个结果将这个结果缓存下来如果下次数据变化后结果和上一次结果相同则将上一次的结果返回。watch是一个惰性api在初始化时不会执行只有当数据变化后才会执行通过也不会有缓存机制。
返回值不同
computed函数返回一个ref对象计算结果就是其value属性同时在模板中使用时也会自动解包。本质上是生成一个computedRef对象并且将传入的getter生成一个effect首先在函数中调用efferct.run(执行一次获得结果将结果挂载到ref上在之后的每一次数据变化都会判断计算结果是否与上一次结果相同如果不同再重新执行effect.run函数。watch 函数返回一个stop函数该函数在调用之后就会销毁内部的effect与依赖之间的关联停止watch的监听。
其他
watch函数第三个参数配置对象可以传入一个immediate: true来实现和computed相似的初始化即执行一次。watch函数第三个参数配置对象可以传入一个deep: true来实现深度监听。watch函数第三个参数配置对象可以传入一个once: true来只执行一次。
4.Vue中的插槽使⽤
1. 插槽
slot 元素是一个插槽出口 (slot outlet)标示了父元素提供的插槽内容 (slot content) 将在哪里被渲染。 插槽本身就是从父组件中传入的因此可以访问父组件中所有的数据其作用域与父组件作用域相同。
如果在外部没有传入任何内容的情况下插槽可以设置默认内容。
button typesubmitslotSubmit !-- 默认内容 --/slot
/button2. 具名插槽
有时在一个组件中包含多个插槽出口是很有用的。举例来说在一个 BaseLayout 组件中有如下模板
div classcontainerheader!-- 标题内容放这里 --/headermain!-- 主要内容放这里 --/mainfooter!-- 底部内容放这里 --/footer
/div对于这种场景slot 元素可以有一个特殊的 attribute name用来给各个插槽分配唯一的 ID以确定每一处要渲染的内容
div classcontainerheaderslot nameheader/slot/headermainslot/slot/mainfooterslot namefooter/slot/footer
/div这类带 name 的插槽被称为具名插槽 (named slots)。没有提供 name 的 slot 出口会隐式地命名为“default”。 要为具名插槽传入内容我们需要使用一个含 v-slot 指令的 template 元素并将目标插槽的名字传给该指令
BaseLayouttemplate v-slot:header!-- header 插槽的内容放这里 --/template
/BaseLayoutv-slot可以简写为#
当一个组件同时接收默认插槽和具名插槽时所有位于顶级的非template 节点都被隐式地视为默认插槽的内容。所以上面也可以写成
3. 条件插槽
有时你需要根据插槽是否存在来渲染某些内容。
你可以结合使用 $slots 属性与 v-if 来实现。
templatediv classcarddiv v-if$slots.header classcard-headerslot nameheader /slot/divdiv v-if$slots.default classcard-contentslot/slot/divdiv v-if$slots.footer classcard-footerslot namefooter/slot/div/div
/template$slots是一个对象这个对象上挂载了所有插槽的名称和内容。
4. 动态插槽名
态指令参数在 v-slot 上也是有效的即可以定义下面这样的动态插槽名
base-layouttemplate v-slot:[dynamicSlotName].../template!-- 缩写为 --template #[dynamicSlotName].../template
/base-layout5. 作用域插槽
在上面的渲染作用域中我们讨论到插槽的内容无法访问到子组件的状态。 然而在某些场景下插槽的内容可能想要同时使用父组件域内和子组件域内的数据。要做到这一点我们需要一种方法来让子组件在渲染时将一部分数据提供给插槽。 我们也确实有办法这么做可以像对组件传递 props 那样向一个插槽的出口上传递 attributes
!-- MyComponent 的模板 --
divslot :textgreetingMessage :count1/slot
/div当需要接收插槽 props 时默认插槽和具名插槽的使用方式有一些小区别。下面我们将先展示默认插槽如何接受 props通过子组件标签上的 v-slot 指令直接接收到了一个插槽 props 对象
MyComponent v-slotslotProps{{ slotProps.text }} {{ slotProps.count }}
/MyComponentv-slot“slotProps” 可以类比这里的函数签名和函数的参数类似我们也可以在 v-slot 中使用解构
MyComponent v-slot{ text, count }{{ text }} {{ count }}
/MyComponent具名作用域插槽 具名作用域插槽的工作方式也是类似的插槽 props 可以作为 v-slot 指令的值被访问到v-slot:name“slotProps”。当使用缩写时是这样
MyComponenttemplate #headerheaderProps{{ headerProps }}/templatetemplate #defaultdefaultProps{{ defaultProps }}/templatetemplate #footerfooterProps{{ footerProps }}/template
/MyComponent注意 slot元素的name属性是Vue一个特殊的保留字段不会作为值传递给插槽。 如果具名插槽和默认插槽都存在则在默认插槽中如果想使用作用域插槽则必须使用默认名为default的具名插槽同时在template标签上使用v-slot:default来获取作用域插槽的值。 无渲染组件 一个组件使用作用域插槽有外部组件来控制其页面样式同时该组件内部通过一定的逻辑处理需要的数据并通过2作用域插槽传递出去外部组件使用时可以直接获取到需要的数据源而只关心页面样式内部组件只需要关心数据处理而不需要关心页面样式。这样的组件我们称之为无渲染组件。
总结
子组件使用slot父组件可以向其传递模板内容称之为插槽。插槽可以通过name属性来命名具名插槽可以同时存在多个。使用时需要用template标签包裹内容在其上使用v-slot指令 来指定插槽的名称也可以使用#来简写。v-slot:插槽名作用域插槽可以向子组件传递数据同时接收子组件传递过来的数据。使用时在子组件通过slot绑定属性传递数据父组件中通过v-slot指令来接收数据。默认作用域插槽可以在组件上使用v-slot来接收数据对象剧名作用域插槽只要有一个具名需要在template标签上使用v-slot指令来接收数据对象。具名和默认插槽同时使用时需要将默认插槽命名为default。具名插槽在子组件中可以使用 s l o t s 来访问是否存在对应的插槽名也可以使用 slots来访问是否存在对应的插槽名也可以使用 slots来访问是否存在对应的插槽名也可以使用scopedSlots来访问插槽内容。具名插槽的名称可以使用动态指令参数来定义。
5. Vue响应式
1.ref
ref函数可以用来创建一个响应式的数据该数据会暴露一个.value属性我们可以使用这个属性来访问或修改该值。
import { ref } from vue
const count ref(0)
console.log(count.value) // 0
count.value
console.log(count.value) // 1如果想要在组件模板中访问我们就需要将该数据声明到setup函数中并返回
import { ref } from vueexport default {// setup 是一个特殊的钩子专门用于组合式 API。setup() {const count ref(0)// 将 ref 暴露给模板return {count}}
}div{{ count }}/divref函数可以接受任何类型的值作为参数ref的响应性具有深层响应特性简单来说就是改变传入对象的深层属性时也会触发重新渲染这是由于ref内部原理中使用了ES6的Proxy代理对象可以监听对象的属性变化同时每一次监听到变化后会保存当前依赖如果访问到深层属性就会遍历深层属性然后生成代理。 注意 这里的深层代理与Vue2的深层代理完全不同谁留的深层代理只有访问到该变量的生成属性才会遍历生成代理如果没访问深层属性本质上代理就只有一层。 如果不想慎用深层代理可以使用shallowRef函数来创建浅层响应式数据。
shallowRef 这个函数功能上与ref类似但只会代理一层即只有value属性改变时才会触发更新如果value属性是一个对象改变该对象的属性不会触发更新。
const state shallowRef({ count: 1 })// 不会触发更改
state.value.count 2// 会触发更改
state.value { count: 2 }额外的 ref 解包细节
1. 如果将ref函数赋值给一个响应式对象的属性则在访问时就会自动解包 const count ref(0)
const state reactive({count
})console.log(state.count) // 0 不需要再手动解包
state.count 1
console.log(count.value) // 1如果在使用中用一个新的ref来替换掉了state.count访问时也会直接访问到新值。同时外层的这个响应式对象必须是深层的如果是一个浅层的就无法自动解报。
2. 当ref数据作为原生数组或者原生map的元素时不会解包 const books reactive([ref(Vue 3 Guide)])// 这里需要 .valueconsole.log(books[0].value)const map reactive(new Map([[count, ref(0)]]))// 这里需要 .valueconsole.log(map.get(count).value)ref在模板中访问时h会自动解包
在框架内部会对其进行解包我们直接书写变量名就行。只有顶级的ref对象才会解包如果ref对象被赋值到其他的变量属性上这是访问改变属性上无法得到该数据. const count ref(0)const object { id: ref(1) }{{ count 1 }} // 正常显示因为顶层
{{ object.id 1 }} // 无法解包因为不是顶层这时候我们就需要使用.value来访问或者我们也可以使用解构语法将数据解构出来使用。
const { id } object // 这样在模板中使用就会是正常的2. reactive
reactive函数用来创建一个响应式的数据该数据是一个代理对象我们可以使用这个对象的属性来访问或修改该值。
import { reactive } from vue
const state reactive({ count: 0 })
console.log(state.count) // 0
state.count
console.log(state.count) // 1这个函数创建的响应式对象那个就和普通的对象那个没有什么区别但Vue会拦截这个对象的所有属性监听变化。 当ref传入的值是一个对象时在内部就会调用这个方法来创建响应式数据。 所以跟ref一样这个函数也是会深层代理。
注意: 如果我们不想要深层代理可以使用shallowReactive函数来创建浅层响应式数据。这个函数也只会浅层监听。
注意: 虽然reactive返回的对象基本上和原对象没什么区别但由于是代理两者之间是相互独立的如果修改了原对象的属性代理对象不会改变。对一个原始对象调用reactive函数总是会得到一个相同的代理对象当传入的原始对象那个已经有代理对象时会直接返回该代理对象。
这里是由于Vue在创建代理对象是都会为每一个代理对象上绑定一个__v_isReactive属性一但第二次代理该对象就会判断搞对象那个是否有这个属性如果有就说明该对象已经被代理过。
局限: reactive函数使用ES6的proxyAPI,但是这个api只能够代理对象数据无法代理原始数据。 还有就是我们在使用时不可以为响应式对象重新赋值一但重新赋值就会是去上一次的代理。如果我们该响应式对象结构或者将该属性传递个函数中就会失去响应式。
因此 Vue官方更建议使用后ref函数来创建响应式数据。