通过10个实例小练习,快速熟练 Vue3.0 核心新特性

Vue3.0 发 beta 版都有一段时间了,正式版也不远了,所以真的要学习一下 Vue3.0 的语法了。
GitHub 博客地址: https://github.com/biaochenxuying/blog
环境搭建
$ git pull https://github.com/vuejs/vue-next.git
$ cd vue-next && yarn
下载完成之后打开代码, 开启 sourceMap :
tsconfig.json 把 sourceMap 字段修改为 true:
"sourceMap": truerollup.config.js 在 rollup.config.js 中,手动键入:
output.sourcemap = true生成 vue 全局的文件:
yarn dev在根目录创建一个 demo 目录用于存放示例代码,并在 demo 目录下创建 html 文件,引入构建后的 vue 文件
api 的使用都是很简单的,下文的内容,看例子代码就能懂了的,所以下面的例子不会做过多解释。
reactive
reactive: 创建响应式数据对象
setup 函数是个新的入口函数,相当于 vue2.x 中 beforeCreate 和 created,在
beforeCreate之后created之前执行。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>reactive</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive } = Vue
const App = {
template: `
<button @click='click'>reverse</button>
<div style="margin-top: 20px">{{ state.message }}</div>
`,
setup() {
console.log('setup ');
const state = reactive({
message: 'Hello Vue3!!'
})
click = () => {
state.message = state.message.split('').reverse().join('')
}
return {
state,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>

ref & isRef
ref : 创建一个响应式的数据对象
isRef : 检查值是否是 ref 的引用对象。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>ref & isRef</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef } = Vue
const App = {
template: `
<button @click='click'>count++</button>
<div style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const count = ref(0);
console.log("count.value:", count.value) // 0
count.value++
console.log("count.value:", count.value) // 1
// 判断某值是否是响应式类型
console.log('count is ref:', isRef(count))
click = () => {
count.value++;
console.log("click count.value:", count.value)
}
return {
count,
click,
}
}
}
createApp(App).mount('#app')
</script>
</html>

Template Refs
使用 Composition API 时,反应性引用和模板引用的概念是统一的。
为了获得对模板中元素或组件实例的引用,我们可以像往常一样声明 ref 并从 setup() 返回。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>Template Refs</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef, toRefs, onMounted, onBeforeUpdate } = Vue
const App = {
template: `
<button @click='click'>count++</button>
<div ref="count" style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const count = ref(null);
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(count.value) // <div/>
})
click = () => {
count.value++;
console.log("click count.value:", count.value)
}
return {
count,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>Template Refs</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef, toRefs, onMounted, onBeforeUpdate } = Vue
const App = {
template: `
<div v-for="(item, i) in list" :ref="el => { divs[i] = el }">
{{ item }}
</div>
`,
setup() {
const list = reactive([1, 2, 3])
const divs = ref([])
// make sure to reset the refs before each update
onBeforeUpdate(() => {
divs.value = []
})
onMounted(() => {
// the DOM element will be assigned to the ref after initial render
console.log(divs.value) // [<div/>]
})
return {
list,
divs
}
}
}
createApp(App).mount('#app')
</script>
</html>

toRefs
toRefs : 将响应式数据对象转换为单一响应式对象
将一个 reactive 代理对象打平,转换为 ref 代理对象,使得对象的属性可以直接在 template 上使用。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>toRefs</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, isRef, toRefs } = Vue
const App = {
// template: `
// <button @click='click'>reverse</button>
// <div style="margin-top: 20px">{{ state.message }}</div>
// `,
// setup() {
// const state = reactive({
// message: 'Hello Vue3.0!!'
// })
// click = () => {
// state.message = state.message.split('').reverse().join('')
// console.log('state.message: ', state.message)
// }
// return {
// state,
// click
// }
// }
template: `
<button @click='click'>count++</button>
<div style="margin-top: 20px">{{ message }}</div>
`,
setup() {
const state = reactive({
message: 'Hello Vue3.0!!'
})
click = () => {
state.message = state.message.split('').reverse().join('')
console.log('state.message: ', state.message)
}
return {
click,
...toRefs(state)
}
}
}
createApp(App).mount('#app')
</script>
</html>

computed
computed : 创建计算属性
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>computed</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, computed } = Vue
const App = {
template: `
<button @click='handleClick'>count++</button>
<div style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const refData = ref(0);
const count = computed(()=>{
return refData.value;
})
const handleClick = () =>{
refData.value += 1 // 要修改 count 的依赖项 refData
}
console.log("refData:" , refData)
return {
count,
handleClick
}
}
}
createApp(App).mount('#app')
</script>
</html>

<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>computed</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, computed } = Vue
const App = {
template: `
<button @click='handleClick'>count++</button>
<div style="margin-top: 20px">{{ count }}</div>
`,
setup() {
const refData = ref(0);
const count = computed({
get(){
return refData.value;
},
set(value){
console.log("value:", value)
refData.value = value;
}
})
const handleClick = () =>{
count.value += 1 // 直接修改 count
}
console.log(refData)
return {
count,
handleClick
}
}
}
createApp(App).mount('#app')
</script>
</html>

watch & watchEffect
watch : 创建 watch 监听
watchEffect : 如果响应性的属性有变更,就会触发这个函数
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>watch && watchEffect</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, ref, watch, watchEffect } = Vue
const App = {
template: `
<div class="container">
<button style="margin-left: 10px" @click="handleClick()">按钮</button>
<button style="margin-left: 10px" @click="handleStop">停止 watch</button>
<button style="margin-left: 10px" @click="handleStopWatchEffect">停止 watchEffect</button>
<div style="margin-top: 20px">{{ refData }}</div>
</div>`
,
setup() {
let refData = ref(0);
const handleClick = () =>{
refData.value += 1
}
const stop = watch(refData, (val, oldVal) => {
console.log('watch ', refData.value)
})
const stopWatchEffect = watchEffect(() => {
console.log('watchEffect ', refData.value)
})
const handleStop = () =>{
stop()
}
const handleStopWatchEffect = () =>{
stopWatchEffect()
}
return {
refData,
handleClick,
handleStop,
handleStopWatchEffect
}
}
}
createApp(App).mount('#app')
</script>
</html>

v-model
v-model:就是双向绑定
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>v-model</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, watchEffect } = Vue
const App = {
template: `<button @click='click'>reverse</button>
<div></div>
<input v-model="state.message" style="margin-top: 20px" />
<div style="margin-top: 20px">{{ state.message }}</div>`,
setup() {
const state = reactive({
message:'Hello Vue 3!!'
})
watchEffect(() => {
console.log('state change ', state.message)
})
click = () => {
state.message = state.message.split('').reverse().join('')
}
return {
state,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>

readonly
使用 readonly 函数,可以把 普通 object 对象、reactive 对象、ref 对象 返回一个只读对象。
返回的 readonly 对象,一旦修改就会在 console 有 warning 警告。
程序还是会照常运行,不会报错。
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>readonly</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, readonly, watchEffect } = Vue
const App = {
template: `
<button @click='click'>reverse</button>
<button @click='clickReadonly' style="margin-left: 20px">readonly++</button>
<div style="margin-top: 20px">{{ original.count }}</div>
`,
setup() {
const original = reactive({ count: 0 })
const copy = readonly(original)
watchEffect(() => {
// works for reactivity tracking
console.log(copy.count)
})
click = () => {
// mutating original will trigger watchers relying on the copy
original.count++
}
clickReadonly = () => {
// mutating the copy will fail and result in a warning
copy.count++ // warning!
}
return {
original,
click,
clickReadonly
}
}
}
createApp(App).mount('#app')
</script>
</html>

provide & inject
provide 和 inject 启用类似于 2.x provide / inject 选项的依赖项注入。
两者都只能在 setup() 当前活动实例期间调用。
import { provide, inject } from 'vue'
const ThemeSymbol = Symbol()
const Ancestor = {
setup() {
provide(ThemeSymbol, 'dark')
}
}
const Descendent = {
setup() {
const theme = inject(ThemeSymbol, 'light' /* optional default value */)
return {
theme
}
}
}
inject 接受可选的默认值作为第二个参数。
如果未提供默认值,并且在 Provide 上下文中找不到该属性,则 inject 返回 undefined。
Lifecycle Hooks
Vue2 与 Vue3 的生命周期勾子对比:
| Vue2 | Vue3 |
|---|---|
| beforeCreate | setup(替代) |
| created | setup(替代) |
| beforeMount | onBeforeMount |
| mounted | onMounted |
| beforeUpdate | onBeforeUpdate |
| updated | onUpdated |
| beforeDestroy | onBeforeUnmount |
| destroyed | onUnmounted |
| errorCaptured | onErrorCaptured |
| 空 | onRenderTracked |
| 空 | onRenderTriggered |
除了 2.x 生命周期等效项之外,Composition API 还提供了以下调试挂钩:
onRenderTrackedonRenderTriggered
这两个钩子都收到一个 DebuggerEvent,类似于观察者的 onTrack 和 onTrigger 选项:
export default {
onRenderTriggered(e) {
debugger
// inspect which dependency is causing the component to re-render
}
}
例子:
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Hello Vue3.0</title>
<style>
body,
#app {
text-align: center;
padding: 30px;
}
</style>
<script src="../../packages/vue/dist/vue.global.js"></script>
</head>
<body>
<h3>Lifecycle Hooks</h3>
<div id='app'></div>
</body>
<script>
const { createApp, reactive, onMounted, onUpdated, onUnmounted } = Vue
const App = {
template: `
<div class="container">
<button @click='click'>reverse</button>
<div style="margin-top: 20px">{{ state.message }}</div>
</div>`
,
setup() {
console.log('setup!')
const state = reactive({
message: 'Hello Vue3!!'
})
click = () => {
state.message = state.message.split('').reverse().join('')
}
onMounted(() => {
console.log('mounted!')
})
onUpdated(() => {
console.log('updated!')
})
onUnmounted(() => {
console.log('unmounted!')
})
return {
state,
click
}
}
}
createApp(App).mount('#app')
</script>
</html>

最后
笔者 GitHub 博客地址: https://github.com/biaochenxuying/blog
本文只列出了笔者觉得会用得非常多的 api,Vue3.0 里面还有不少新特性的,比如 customRef、markRaw ,如果读者有兴趣可看 Vue Composition API 文档。
Vue Composition API 文档: https://composition-api.vuejs.org/api.html#setup
vue-next 地址: https://github.com/vuejs/vue-next
参考文章:
支持一下下
通过10个实例小练习,快速熟练 Vue3.0 核心新特性的更多相关文章
- 快速进阶Vue3.0
在2019.10.5日发布了Vue3.0预览版源码,但是预计最早需要等到 2020 年第一季度才有可能发布 3.0 正式版. 可以直接看 github源码. 新版Vue 3.0计划并已实现的主要架构改 ...
- 背水一战 Windows 10 (1) - C# 6.0 新特性
[源码下载] 背水一战 Windows 10 (1) - C# 6.0 新特性 作者:webabcd 介绍背水一战 Windows 10 之 C# 6.0 新特性 介绍 C# 6.0 的新特性 示例1 ...
- 背水一战 Windows 10 (43) - C# 7.0 新特性
[源码下载] 背水一战 Windows 10 (43) - C# 7.0 新特性 作者:webabcd 介绍背水一战 Windows 10 之 C# 7.0 新特性 介绍 C# 7.0 的新特性 示例 ...
- linux常用命令与实例小全
转至:https://www.cnblogs.com/xieguohui/p/8296864.html linux常用命令与实例小全 阅读目录(Content) 引言 一.安装和登录 (一) ...
- 微信小程序快速开发上手
微信小程序快速开发上手 介绍: 从实战开发角度,完整系统地介绍了小程序的开发环境.小程序的结构.小程序的组件与小程序的API,并提供了多个开发实例帮助读者快速掌握小程序的开发技能,并能自己动手开发出小 ...
- 10个jQuery小技巧
收集的10个 jQuery 小技巧/代码片段,可以帮你快速开发. 1.返回顶部按钮 你可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. $('a.top' ...
- 人人必知的10个jQuery小技巧
收集的10个 jQuery 小技巧/代码片段,可以帮你快速开发. 1.返回顶部按钮 你可以利用 animate 和 scrollTop 来实现返回顶部的动画,而不需要使用其他插件. // Back t ...
- Selenium 2.0 WebDriver 自动化测试 使用教程 实例教程 API快速参考
Selenium 2.0 WebDriver 自动化测试 使用教程 实例教程 API快速参考 //System.setProperty("webdriver.firefox.bin" ...
- redis3.2.10单实例安装测试
redis3.2.10单实例安装测试 主要是实际使用环境中使用,为了方便快速部署,特意记录如下: # root用户 yum -y install make gcc-c++ cmake bison-de ...
随机推荐
- python高级特性之封包与解包
前言 文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者:kwsy PS:如有需要Python学习资料的小伙伴可以加点击下方链接 ...
- 带权值的LCA
例题:http://poj.org/problem?id=1986 POJ1986 Distance Queries Language: Default Distance Queries Time L ...
- 65535与TCP连接数的关系测试结论
首先说结论: .是否有关系 .有关系 对于客户端 -.对于客户端来说,只有65535,因为根据TCP四元组的sport来说,sport只有16位,所以(2^16)-1是65535.也就是最多有6553 ...
- 装机摸鱼日记01--DDR3AMD专用内存+QHQF(6400T)试水
前些日子在某鱼入手了两条AMD专用内存,宏想的DDR3-1600MHz-8G内存和一块高贵阿苏斯Z170-P-D3主板,然后某宝600多买了一颗QHQF(当然也可以玩QHQJ,更便宜,估计三百多),准 ...
- 微信小程序基本知识
逻辑实现 1 使用动态数据展示列表(可以考虑使用wx:for属性配合动态数组渲染全部列表项,以减少WXML页面的代码量) eg: <view class='listGroup' wx:for= ...
- 学习Python爬虫的4幅思维导图
这次给大家带来的是4 幅思维导图,梳理了 Python 爬虫部分核心知识点:网络基础知识,Requests,BeautifulSoup,urllib 和 Scrapy 爬虫框架. 爬虫是一个非常有趣的 ...
- Mysql表的对应关系
表关系 一对一一张表中的一条记录与另一张表中最多有一条明确的关系:通常,此设计方案保证两张表中使用同样的主键即可假设一张学生表:id 姓名 年龄 性别 籍贯 婚否 住址那么姓名 年龄 性别 这种字段比 ...
- Java IO 流--FileUtils 工具类封装
IO流的操作写多了,会发现都已一样的套路,为了使用方便我们可以模拟commosIo 封装一下自己的FileUtils 工具类: 1.封装文件拷贝: 文件拷贝需要输入输出流对接,通过输入流读取数据,然后 ...
- 来自BAT大厂前端工程师的自白-怎么才能学好前端
如果说理解学好web前端是先能找到一份工作,那么你应该这样做: 1.制定好一下系统的web前端学习规划,每天定量,学完什么知识点就掌握,能自己应用,而不是能看懂,写不出来东西. 2.不要自己一个人闷头 ...
- RedHat 的 crontab
Chapter 39. Automated Tasks In Linux, tasks can be configured to run automatically within a specifie ...