Vue3.0上手

生命周期钩子

vue3.0提供了 setup onMounted onUnmounted onUpdated 生命周期钩子,都在vue 上。

import { onMounted, onUpdated, onUnmounted } from 'vue'

const MyComponent = {
  setup() {
    onMounted(() => {
      console.log('mounted!')
    })
    onUpdated(() => {
      console.log('updated!')
    })
    onUnmounted(() => {
      console.log('unmounted!')
    })
  }
}
vue2.0和vue3.0之间生命周期区别
  • beforeCreate -> use setup()* created -> use setup()* beforeMount -> onBeforeMount* mounted -> onMounted* beforeUpdate -> onBeforeUpdate* updated -> onUpdated* beforeUnmount -> onBeforeUnmount* unmounted -> onUnmounted* errorCaptured -> onErrorCaptured* renderTracked -> onRenderTracked* renderTriggered -> onRenderTriggered

setUp 函数

执行时间

在创建组件实例时,在初始 prop 解析之后立即调用 setup。在生命周期方面,它是在 beforeCreate 钩子之前调用的。

函数

setup 函数接受两个参数,第一个参数 props第二个参数 context

props

props是响应式的,在传入新的 props 时会对其进行更新,并且可以通过使用 watchEffectwatch 进行观测和响应,不要对props进行解构赋值,解构之后将不具有响应性。

export default {
  props: {
    name: String
  },
  setup(props) {
    watchEffect(() => {
      console.log(`name is: ` + props.name)
    })
  }
}
context:执行上下文

常用的 emit slots attrs 在context可以获取到。

export default defineComponent({
  name: "CardList",
  components: { Blank },
  props: {
    list: {
      type: Array,
      default: () => {
        return [];
      },
    },
  },
  setup(props, context) {
    // 实例化 router
    const router = useRouter();
    const toView = (item) => {
      router.push({ name: "Article", query: { id: item.id } });
    };
    const like = (index) => {
      context.emit("like", index);
    };
    return {
      toView,
      like,
    };
  },
});

computedwatch的使用,filters移出

filters 不在vue3中支持,官方推荐使用computed来代替filter的使用

computedwatch 也是在vue上的,使用之前需要import导入。

import { computed, watch, ref } from 'vue';
....
setup() {
  const route = useRoute();
  const name = ref('pe');
  const computedA = computed(() => {
      return name.value + '--nameA'
  })
  const computedB= computed(() => {
     return name.value + '--nameB'
  })
  watch(route,(nowVal,preVal) => {
    // do some thing
  })
  watch(name,(nowVal,preVal) => {
    // do some thing
  })
  watch(
       [() => count, () => name]
       ([count, name], [preCount, preName]) => { 
           //count新值, preCount旧值
           console.log('log输出') //这里是监听数据变化后执行的函数
       }, 
       {
          lazy: false
       })//在第一次创建不监听
  
  return {
    computedA,
    computedB
  }
} 

ref reactive toRef toRaw 是什么?怎么用?

ref

ref接受一个内部值并返回一个响应式且可变的 ref 对象。ref 对象具有指向内部值的单个 property .value

ref将一个变量进行代理实现了响应式,想要访问这个变量的值必须获取变量的value 才能访问得到。

<div>
    <span>{{name}}</span>
    <span>{{age}}</span>
    <button @click="change">AGE+1</button>
    // 点击按钮 发现 age + 1,但是 name没有变化
</div>
...
setup() {
    let name = 'hs'
    const age = ref(10);
    const change = () => {
       name  = 'hs' + '1'
       age.value = age.value += 1;
       console.log(name,age.value);
    }
} 

点击button 发现 age+ 1,但是 name没有变化,还是原来的值。

日志输入:age: 11;name: hs1

name数据改变了但是页面没有更新,因为name不是响应式数据

通过ref获取Dom?

在vue2中我们想要获取Dom的时候,可以在dom上添加ref,然后通过$refs获取到Dom, 在vue3中,我们通过提供的ref方法传入一个null并且定义与页面元素上ref相对应。

<template>
  <div>
    <h1 ref="h1Ref">Hello Word</h1>
  </div>
</template>
<script>
import { ref, onMounted } from '@vue/composition-api'
export default {
  setup() {
    // 创建一个 DOM 引用
    const h1Ref = ref(null)
    // 在 DOM 首次加载完毕之后,才能获取到元素的引用
    onMounted(() => {
      // 为 dom 元素设置字体颜色
      // h1Ref.value 是原生DOM对象
      console.log(h1Ref.value)
    })
    // 把创建的引用 return 出去
    return {
      h1Ref
    }
  }
}
</script>
reactive

reactive定义引用类型的响应式数据,定义的数据不需要和ref一样通过value获取值,可以直接获取

setup() {
  // const bh = reactive(10) => error
  const bh = reactive({val: 10};
  const getBh = () => {
    return bh; // 直接返回
  }
  return {
    bh,
  }
}
toRef

toRef: 可以用来为源响应式对象上的 property 性创建一个 ref。然后可以将 ref 传递出去,从而保持对其源 property 的响应式连接。

const state = reactive({
  foo: 1,
  bar: 2
})

const fooRef = toRef(state, 'foo')

fooRef.value++
console.log(state.foo) // 2

state.foo++
console.log(fooRef.value) // 3

上案例,将statefoofooRef绑定了,可以说fooRef是对state.foo的引用,并在外层包裹了一层ref 。在实际的开发中,如果想要得到某个多层的对象下面的属性时,可以采用toRef

toRaw

toRaw :返回 reactivereadonly 代理的原始对象。

const foo = {}
const reactiveFoo = reactive(foo)

console.log(toRaw(reactiveFoo) === foo) // true

hooks引入,可以做什么?

hooks 提高了代码的复用性,代码逻辑清晰。

hooks可以在组件外部调用Vue的所有能力,包括onMounted,ref, reactive等等。

useMousePosition.ts

// hooks
import {onBeforeUnmount, onMounted, ref} from 'vue
export default function () {
  const x = ref(-1) ; // x 绑定为响应式数据
  const y = ref(-1);
  const clickHandler=(event:MouseEvent)=>{
    x.value = event.pageX
    y.value = event.pageY
  } 
  onMounted(()=>{
    window.addEventListener('click', clickHandlker)
  })
  onBeforeUnmount(()=>{
    window.removeEventListner('click', clickHandler)
  })
  return {
    x,
    y
  }
}
<template>
<div>
  <h2>x: {{x}}, y: {{y}}</h2>
</div>
</template>

<script>

import {
  ref
} from "vue"
/* 
在组件中引入并使用自定义hook
自定义hook的作用类似于vue2中的mixin技术
自定义Hook的优势: 很清楚复用功能代码的来源, 更清楚易懂
*/
import useMousePosition from './hooks/useMousePosition'

export default {
  setup() {

    const {x, y} = useMousePosition() // 这里就用了 hooks 函数, 从而提高了复用性

    return {
      x,
      y,
    }
  }
}
</script>

Teleport组件

teleportvue3新增的组件。他可以让我们将组件插入到指定的Dom结构下。

使用案例:

在项目中,有一个场景:在页面滚动区域过长的情况下,需要能够一键回到顶部的这样一样操作按钮。

在Vue3中,就可以利用Teleport来实现这个功能。只需要操作按钮组件编写完成,然后将Teleportto属性绑定到置顶的Dom上即可。

toUper.vue

<template>
  <!-- #app 代表这个 Dom将要挂载到id为App的dom下方 -->
  <teleport to="#app">
      <div class="toUpper animated flash" v-if="show">
        <div class="ic" @click="toHome()">
          <i class="iconfont icon-shouye1"></i>
        </div>
        <div class="ic" @click="toUp()">
          <i class="iconfont icon-up"></i>
        </div>
      </div>
  </teleport>
</template>
<script>
import { defineComponent } from "vue";
import { useRouter } from 'vue-router';
import useScrollToTop from "@/hooks/useScrollToTop";
export default defineComponent({
  name: "ToUpper",
  props: {
    show: {
      type: Boolean,
      default: false,
    },
  },
  setup() {
      const router = useRouter();
    const toUp = () => {
      useScrollToTop();
    };
    const toHome = () => {
        router.push({path: '/'});
    }
    return {
      toUp,
      toHome,
    };
  },
});
</script>

<style lang="scss" scoped>
.toUpper {
  position: sticky;
  top: 90%;
  left: 90%;
}
.ic {
  float: right;
  display: block;
  margin-right: 40px;
  width: 40px;
  height: 40px;
  border-radius: 50%;
  background: #528bff;
  display: flex;
  align-items: center;
  justify-content: center;
  &:hover {
      cursor: pointer;
  }
  .iconfont {
    color: #fff;
  }
}
</style>

Home.vue

<template>
  <div class="home" if="home">
    <Header @changStatus="changStatus" :status="status" />
    <div class="main">
      <router-view></router-view>
      <div id="upper"></div>
    </div>
    <!-- 当页面滚动区域操作20之后才显示  -->
    <to-upper :show="scrollTop > 20" />
  </div>**
**</template>

provide & inject(数据共享)

provide()和 inject()可以实现嵌套组件之间的数据传递。这个两个函数只能在setup()函数中使用。父级组件中使用provide()函数可以使数据向下传递,子组件中使用inject()接收上层传过来的数据。
实现代码:
根组件(父组件)parent.vue

<template>
  <div>
    <child-one></child-one>
    <child-two></child-two>
  </div>
</template>

<script>
  import { provide } from '@vue/composition-api'
  import ChildOne from '@/components/Child'
  import ChildTwo from '@/components/Child'
  export default {
    components: {
       ChildOne,
       ChildTwo
    },
    setup() {
    // provide('要共享的数据名称', 被共享的数据)
      provide('globalName', 'vue') 
    }
  }
</script>

childOne.vue

<template>
  <div>
    <!--页面展示数据globalName -->
    {{globalName}} 
  </div>
</template>

<script>
  import { inject } from '@vue/composition-api'
  export default {
    name: 'ChildOne',
    setup() {
      const globalName = inject('globalName') 调用 inject 函数时,通过指定的数据名称,获取到父级共享的数据
      return {
        globalName
      }
    }
  }
</script>

childTwo.vue

<template>
  <div>
    <!--页面展示数据globalName -->
    {{globalName}} 
  </div>
</template>

<script>
  import { inject } from '@vue/composition-api'
  export default {
    name: 'ChildTwo',
    setup() {
      const globalName = inject('globalName') 调用 inject 函数时,通过指定的数据名称,获取到父级共享的数据
      return {
        globalName
      }
    }
  }
</script>

APP配置

config是一个包含了 Vue 应用全局配置的对象。你可以在应用挂载前修改其下属性:

errorHandler: 错误的处理回调

warnHandler: 警告的处理回调

globalProperties:全局的属性

optionMergeStrategies:自定义项合并策略

performance: 性能调试。接受布尔值,设置为 true 。可以在 浏览器开发工具的 performance/timeline 面板中启用对组件初始化、编译、渲染和更新的性能追踪

import App from './App.vue'
const app = crateApp(App);
app.config.errorHandler = (err) => {}; //处理错误回调
app.config.warnHandler= (warn) => {}; //
app.config.globalProperties.isAndroid = true;
app.config.performace = true; // 开启性能调试 

vue3项目参考

Gitee

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值