vue3.0

vue3.0入门

1.安装新版本vue

npm install -g @vue/cli

2.查看版本

vue --version

3.项目初始化

vue create cli3-test //vue create [项目名称]
main.js文件
import { createApp } from 'vue'
import App from './App.vue'
 
createApp(App).mount('#app')
router.js路由文件
// 可以根据路由模式的不同,后面俩可以只引用一个
import { createRouter, createWebHistory, createWebHashHistory } from 'vue-router'
import Home from '@/views/Home.vue'
 
// 构建我们的页面路由配置,可以看到,这里和原来的写法并无二致。
const routes = [
  {
    path: '/',
    component: Home
  }, {
    path: '/about',
    component: () => import('@/views/About.vue'),
  }
]
 
const router = createRouter({
  // 使用 hash 模式构建路由( url中带 # 号的那种)
  history: createWebHashHistory(),
  // 使用 history 模式构建路由 ( url 中没有 # 号,但生产环境需要特殊配置)
  // history: createWebHistory(),
  routes
})
export default router
得益于 vue3.0 的特性,我们现在不比把组件内容全部包裹在某一个 div 下面了,一个 template 里面可以有多个根节点元素

App.vue

<template>
  <router-view />
</template>

About.vue

<template>
  这里是关于我们的页面
  <router-link to="/">点这里去首页</router-link>
</template>

在main.js挂载

import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
 
// 将创建的 App 搞个别名
const app = createApp(App)
 
// 使用路由配置
app.use(router)
 
// 挂载运行
app.mount('#app')

4.setup()函数

有两个参数:== props == 、== context ==
** 在 setup 函数中 return 出去的东西,可以在模板区域直接使用,也不必理会 this **

1)props

// MyBook.vue

export default {
  props: {
    title: String
  },
  setup(props) {
    console.log(props.title)
  }
}
// WARNING
// 因为 props 是响应式的,你不能使用 ES6 解构,它会消除 prop 的响应性
// 如果需要解构 prop,可以在 setup 函数中使用 toRefs 函数来完成此操作:
// About.vue

import { toRefs } from 'vue'

setup(props) {
  const { title } = toRefs(props)

  console.log(title.value)
}

2)context

// About.vue

export default {
  setup(props, context) {
    // Attribute (非响应式对象)
    console.log(context.attrs)

    // 插槽 (非响应式对象)
    console.log(context.slots)

    // 触发事件 (方法)
    console.log(context.emit)
  }
}
// About.vue
// 不是响应式的,这意味着你可以安全地对 context 使用 ES6 解构
export default {
  setup(props, { attrs, slots, emit }) {
    ...
  }
}

5.ref

// Home.vue
<template>
  <router-link to="/about">点这里去关于我们页面</router-link>
  <div class="home">
    这里是一个计数器 >>> <span class="red">{{count}}</span> <br>
    <button @click="countAdd">{{btnText}}</button>
  </div>
</template>
 
<script>
// ref 是 vue 3.0 的一个重大变化,其作用为创建响应式的值
import { ref } from 'vue'
// 导出依然是个对象,不过对象中只有一个 setup 函数
export default {
  setup () {
    // 定义一个不需要改变的数据
    const btnText = '点击按钮'
    // 定义一个 count 的响应式数据,并赋值为 0
    const count = ref(0)
    // 定义一个函数,修改 count 的值。
    const countAdd = () => {
      count.value++
    }
    // 导出一些内容给上面的模板区域使用
    return {
      btnText,
      count,
      countAdd
    }
  }
}
</script>
<style lang="scss">
.home {
  line-height: 2;
  .red {
    color: red;
  }
}
</style>

unref

如果参数是一个 ref,则返回内部值,否则返回参数本身。这是 val = isRef(val) ? val.value : val 的语法糖函数。

function useFoo(x: number | Ref<number>) {
  const unwrapped = unref(x) // unwrapped 现在一定是数字类型
}

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
export default {
  setup(props) {
    useSomeFeature(toRef(props, 'foo'))
  }
}

toRefs

将响应式对象转换为普通对象,其中结果对象的每个 property 都是指向原始对象相应 property 的 ref

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

const stateAsRefs = toRefs(state)
/*
stateAsRefs 的类型:

{
  foo: Ref<number>,
  bar: Ref<number>
}
*/

// ref 和原始 property 已经“链接”起来了
state.foo++
console.log(stateAsRefs.foo.value) // 2

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

toRefs 只会为源对象中包含的 property 生成 ref。如果要为特定的 property 创建 ref,则应当使用 toRef

isRef

检查值是否为一个 ref 对象。

customRef

<input v-model="text" />
function useDebouncedRef(value, delay = 200) {
  let timeout
  return customRef((track, trigger) => {
    return {
      get() {
        track()
        return value
      },
      set(newValue) {
        clearTimeout(timeout)
        timeout = setTimeout(() => {
          value = newValue
          trigger()
        }, delay)
      }
    }
  })
}

export default {
  setup() {
    return {
      text: useDebouncedRef('hello')
    }
  }
}

shallowRef

const foo = shallowRef({})
// 改变 ref 的值是响应式的
foo.value = {}
// 但是这个值不会被转换。
isReactive(foo.value) // false

triggerRef

const shallow = shallowRef({
  greet: 'Hello, world'
})

// 第一次运行时记录一次 "Hello, world"
watchEffect(() => {
  console.log(shallow.value.greet)
})

// 这不会触发副作用,因为 ref 是浅层的
shallow.value.greet = 'Hello, universe'

// 记录 "Hello, universe"
triggerRef(shallow)

6.reactive

reactive 和 ref 的区别就是,reactive 是处理对象或者数组的

<template>
  <router-link to="/">点这里去首页</router-link>
  <hr>
  <dl>
    <dt>{{state.name}}</dt>
    <dd>性别:{{state.sex}}</dd>
    <dd>地址:{{state.address}}</dd>
  </dl>
  <button @click="addressChange">更新地址</button>
</template>
<script>
// reactive 是 vue 3.0 的一个重大变化,其作用为创建响应式的对象或数组
import { reactive } from 'vue'
// 导出依然是个对象,不过对象中只有一个 setup 函数
export default {
  setup () {
    // 定义一个 state 的响应式对象数据,并赋值
    const state = reactive({
      name: 'FungLeo',
      sex: 'boy',
      address: '上海'
    })
    console.log(state)
    // 定义一个函数,修改 state 的值。
    const addressChange = () => {
      state.address += '浦东'
    }
    // 导出一些内容给上面的模板区域使用
    return {
      state,
      addressChange
    }
  }
}
</script>

7.生命周期函数

2.03.0
beforeCreatesetup
createdsetup
beforeMountonBeforeMount
mountedonMounted
beforeUpdateonBeforeUpdate
updatedonUpdated
beforeDestroyonBeforeUnmount
destroyedonUnmounted
errorCapturedonErrorCaptured
// 你需要使用到什么生命周期,就引出来什么生命周期
import {
  onBeforeMount,
  onMounted,
  onBeforeUpdate,
  onUpdated,
  onBeforeUnmount,
  onUnmounted,
  ref
} from 'vue'

export default {
  // setup 函数,就相当于 vue 2.0 中的 created
  setup () {
    const count = ref(0)
    // 其他的生命周期都写在这里
    onBeforeMount (() => {
      count.value++
      console.log('onBeforeMount', count.value)
    })
    onMounted (() => {
      count.value++
      console.log('onMounted', count.value)
    })
    // 注意,onBeforeUpdate 和 onUpdated 里面不要修改值,会死循环的哦!
    onBeforeUpdate (() => {
      console.log('onBeforeUpdate', count.value)
    })
    onUpdated (() => {
      console.log('onUpdated', count.value)
    })
    onBeforeUnmount (() => {
      count.value++
      console.log('onBeforeUnmount', count.value)
    })
    onUnmounted (() => {
      count.value++
      console.log('onUnmounted', count.value)
    })
    // 定义一个函数,修改 count 的值。
    const countAdd = () => {
      count.value++
    }
    return {
      count,
      countAdd
    }
  }
}

8.Provide / Inject

只能在当前活动实例的 setup() 期间调用

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  provide: {
    location: 'North Pole',
    geolocation: {
      longitude: 90,
      latitude: 135
    }
  }
}
</script>
<!-- src/components/MyMarker.vue -->
<script>
export default {
  inject: ['location', 'geolocation']
}
</script>
provide

provide 函数允许你通过两个参数定义 property:

  1. name ( 类型)
  2. value
<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    provide('location', 'North Pole')
    provide('geolocation', {
      longitude: 90,
      latitude: 135
    })
  }
}
</script>
Inject

inject 函数有两个参数:

  1. 要 inject 的 property 的 name
  2. 默认值 (可选)
<!-- src/components/MyMarker.vue -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')

    return {
      userLocation,
      userGeolocation
    }
  }
}
</script>
响应性
<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    provide('location', location)
    provide('geolocation', geolocation)
  }
}
</script>
<!-- 现在,如果这两个 property 中有任何更改,MyMarker 组件也将自动更新!-->
<!-- src/components/MyMap.vue -->
<!-- 提供 -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }

    provide('location', location)
    provide('geolocation', geolocation)
    provide('updateLocation', updateLocation)
  }
}
</script>
<!-- src/components/MyMarker.vue -->
<!-- 接收 -->
<script>
import { inject } from 'vue'

export default {
  setup() {
    const userLocation = inject('location', 'The Universe')
    const userGeolocation = inject('geolocation')
    const updateUserLocation = inject('updateLocation')

    return {
      userLocation,
      userGeolocation,
      updateUserLocation
    }
  }
}
</script>
readonly

__ 如果要确保通过 provide 传递的数据不会被 inject 的组件更改,我们建议对提供者的 property 使用 readonly __

<!-- src/components/MyMap.vue -->
<template>
  <MyMarker />
</template>

<script>
import { provide, reactive, readonly, ref } from 'vue'
import MyMarker from './MyMarker.vue'

export default {
  components: {
    MyMarker
  },
  setup() {
    const location = ref('North Pole')
    const geolocation = reactive({
      longitude: 90,
      latitude: 135
    })

    const updateLocation = () => {
      location.value = 'South Pole'
    }

    provide('location', readonly(location))
    provide('geolocation', readonly(geolocation))
    provide('updateLocation', updateLocation)
  }
}
</script>

9.计算属性

<template>
  <router-link to="/">点这里去首页</router-link>
  <hr>
  <div class="home">
    这里是一个计数器 >>> <span class="red">{{count}}</span> <br>
    右边的数字是上面的数字的十倍 >>> <span class="red">{{bigCount}}</span> <br>
    右边的数字是上面的数字的一百倍 >>> <span class="red">{{computeCount['100x']}}</span> <br>
    右边的数字是上面的数字的一千倍 >>> <span class="red">{{computeCount['1000x']}}</span> <br>
    <button @click="countAdd">点这个按钮上面的数字会变</button>
  </div>
</template>
 
<script>
// 需要使用计算属性,也需要从 vue 中导出引入
import { ref, computed } from 'vue'
// 导出依然是个对象,不过对象中只有一个 setup 函数
export default {
  setup () {
    // 定义一个 count 的响应式数据,并赋值为 0
    const count = ref(0)
    // 定义一个函数,修改 count 的值。
    const countAdd = () => {
      count.value++
    }
    // 计算属性,使用计算函数并命名,然后在 return 中导出即可
    const bigCount = computed(() => {
      return count.value * 10
    })
    // 计算多个属性,可以通过返回一个对象的方式来实现
    const computeCount = computed(() => {
      return {
        '100x': count.value * 100,
        '1000x': count.value * 1000,
      }
    })
    // 导出一些内容给上面的模板区域使用
    return {
      count,
      countAdd,
      bigCount,
      computeCount
    }
  }
}
</script>

10.watch

3 个参数:

  1. 一个想要侦听的响应式引用或 getter 函数
  2. 一个回调
  3. 可选的配置选项
import { ref, watch } from 'vue'

const counter = ref(0)
watch(counter, (newValue, oldValue) => {
  console.log('The new counter value is: ' + counter.value)
})
// src/components/UserRepositories.vue `setup` function
import { fetchUserRepositories } from '@/api/repositories'
import { ref, onMounted, watch, toRefs } from 'vue'

// 在我们组件中
setup (props) {
  // 使用 `toRefs` 创建对prop的 `user` property 的响应式引用
  const { user } = toRefs(props)

  const repositories = ref([])
  const getUserRepositories = async () => {
    // 更新 `prop.user` 到 `user.value` 访问引用值
    repositories.value = await fetchUserRepositories(user.value)
  }

  onMounted(getUserRepositories)

  // 在 user prop 的响应式引用上设置一个侦听器
  watch(user, getUserRepositories)

  return {
    repositories,
    getUserRepositories
  }
}

watch重点为了监听做事情. 看重的不是返回结果, 而是属性的变化.
computed重点为了得到一个属性值,看重的是它的返回结果.

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值