# 2. 实战

# 1. 访问真实 dom 节点

  • 组件如果是options写法仍通过this.$refs访问
  • 组件如果是setup写法,则需要通过ref包装然后访问value
setup() {
    const rootRef = ref(null)
    // rootRef需在onMounted中才能访问到,此处为null
    console.log('rootRef.value', rootRef.value)
    return {
      rootRef
    }
  },
  • 获取元素 el 位置、本身样式,transform 合并用 concat
const rect = el.getBoundingClientRect()
const style = getComputedStyle(el)

function syncTransform(wrapper, inner) {
  const wrapperTransform = getComputedStyle(wrapper).transform
  const innerTransform = getComputedStyle(inner).transform
  console.log('wrapperTransform :', wrapperTransform)
  wrapper.style.transform =
    // tansform合并用concat,最开始为'none'
    wrapperTransform === 'none' ? innerTransform : wrapperTransform.concat('', innerTransform)
}

# 2. better-scroll 使用要点

better-scroll初始化包括的节点只能有一个,因为better-scroll只对第一个子节点有效果

# 3.自定义指令

v-loading.title/v-loading:title区别:前者 title 通过binding.modifiers访问,后者通过binding.arg访问。

<div class="recommend" v-loading:[loadingText]="loading"></div>
data() { return { loadingText: '正在载入...', } },
// binding的打印结果
{
  arg: "正在载入..."
  dir: {mounted: ƒ, updated: ƒ}
  instance: Proxy {recommendItemClick: ƒ,} // 使用该指令的组件
  modifiers: {}
  oldValue: undefined
  value: true
}

4.原生 dom

  • 获取style,getComputedStyle浏览器原生支持,const style = getComputedStyle(el)

  • 判断包含类,el.classList.contains(className),更多见 element 组件库

  1. 组件可以添加emits:['xxx']选项来展示对外派发的事件

6.通过ref包装的变量,在watch 中可以自动展开,computed 中不能自动展开

const scrollY = ref(0)
watch(scrollY,newY => {....})
const fixedTitle = computed(()=>{
  if(scrollY.value < 0 ) return ''
})
  1. setup返回对象中的key会和组件props属性里面的值处于同级

如图,click/probeTypeprops,rootRef/scrollsetup对象中返回的值

8.transition动画用法发生变化

由 v2 transition -> router-view 变成 router-view->transition->keep-alive

<!-- vue3 -->
<router-view v-slot="{ Component }">
  <!-- appear为在当前路由时刷新时出现动画 -->
  <transition appear name="slide">
    <keep-alive>
      <component :is="Component" :singer="selectedSinger" />
    </keep-alive>
  </transition>
</router-view>

<!-- vue2 -->
<transition appear name="slide">
  <router-view :singer="selectedSinger"></router-view>
</transition>
  1. computed中通过this.xx访问其他属性时,会做一次赖收集,所以如果computed中同一个属性多次访问的话做缓存有利于性能优化

  2. 通过钩子返回的访问DOM元素的同一个ref在不同组件中使用得到的对应的DOM元素

  3. v-model默认的propsmodelValue

  4. render 函数帮助(opens new window)

  5. vuex vue-router

import { useRouter } from 'vue-router'
import { useStore } from 'vuex'
export default {
  setup() {
    const store = useStore()
    const router = useRouter()
  },
}
  1. watch props属性变化用法区别
export default {
  // vue2 vue3
  props:{
    modelValue:String
  }
  created(){
    this.$watch('modelValue', (newModelValue) => {...})
  }
  watch:{
    modelValue(newModelValue){...}
  }
}

// vue3
export default {
  props:{
    modelValue:String
  }
  setup(props){
    watch(()=>props.modelValue,(newModelValue)=>{...})
  }
}
  1. watch/watchEffect 的区别
  • watch 需要指定监听值,能够获取新老值,不会立即执行,除非配置immediate:true
  • watchEffect 不需要指定监听值,不能获取老值,会立即执行并且自动进行依赖收集,立即执行类似 watch 配置immediate:true的效果,如果需要等页面更新完成之后再执行,可以添加配置flush:'post'
  1. watch 用法
  • watch 通过 ref、reactive、computed 包裹的值都可以直接 watch,即 watch 第一个参数无需使用函数返回方式
  • 基本类型使用 ref 包裹进行 watch,配置项无需传入deep:true即可观察
  • 引用类型可用 ref、reactive 包裹,如果观察的是对象整体,使用 ref 包裹时需传入deep:true,reactive 无需传

17 reactive 可以使用 ref 包裹的值,获得它的响应式

const num = ref(1)
const requestParam = reactive({
  page_size: 50,
  page: num,
})