3-6eslint规范代码
0,1,2off,warn,error
vue/muti-word-component-names:off
3-13模块化难度上升
usemousePosition.ts
import { ref, onMounted, onUnmounted } from 'vue'
function useMousePosition() {
const x = ref(0)
const y = ref(0)
const updateMouse = (e: MouseEvent) => {
x.value = e.pageX
y.value = e.pageY
}
onMounted(() => {
document.addEventListener('click', updateMouse)
})
onUnmounted(() => {
document.removeEventListener('click', updateMouse)
})
return {x, y}
}
export default useMousePosition
useURLLoader.ts
import { ref } from 'vue'
import axios from 'axios'
function useURLLoader<T>(url: string) {
const result = ref<T | null>(null)
const loading = ref(true)
const loaded = ref(false)
const error = ref(null)
axios.get(url).then((rawData) => {
loading.value = false
loaded.value = true
result.value = rawData.data
}).catch(e => {
error.value = e
loading.value = false
})
return {
result,
loading,
error,
loaded
}
}
export default useURLLoader
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<h1>{{count}}</h1>
<h1>{{double}}</h1>
<h1>{{greetings}}</h1>
<p>{{error}}</p>
<Suspense>
<template #default>
<div>
<async-show />
<dog-show />
</div>
</template>
<template #fallback>
<h1>Loading !...</h1>
</template>
</Suspense>
<button @click="openModal">Open Modal</button><br/>
<modal :isOpen="modalIsOpen" @close-modal="onModalClose"> My Modal !!!!</modal>
<h1 v-if="loading">Loading!...</h1>
<img v-if="loaded && Array.isArray(result)" :src="result[0].url" >
<h1>X: {{x}}, Y: {{y}}</h1>
<button @click="increase">👍+1</button><br/>
<button @click="changeLang('en')">英文</button><br/>
<button @click="changeLang('ch')">中文</button><br/>
<button @click="updateGreeting">Update Title</button>
</div>
</template>
<script lang="ts">
import { provide, ref, computed, reactive, toRefs, watch, onErrorCaptured, defineComponent } from 'vue'
import useMousePosition from './hooks/useMousePosition'
import useURLLoader from './hooks/useURLLoader'
import Modal from './components/Modal.vue'
import AsyncShow from './components/AsyncShow.vue'
import DogShow from './components/DogShow.vue'
interface DataProps {
count: number;
double: number;
increase: () => void;
}
interface DogResult {
message: string;
status: string;
}
interface CatResult {
id: string;
url: string;
width: number;
height: number;
}
export default defineComponent({
name: 'App',
components: {
Modal,
AsyncShow,
DogShow,
},
setup() {
// provide 提供数据
const lang = ref('en')
provide('lang', lang)
const changeLang = (type: string) => {
lang.value = type
}
const error = ref(null)
onErrorCaptured((e: any) => {
error.value = e
return true
})
const data: DataProps = reactive({
count: 0,
increase: () => { data.count++},
double: computed(() => data.count * 2),
})
const { x, y } = useMousePosition()
const { result, loading, loaded } = useURLLoader<CatResult[]>('https://api.thecatapi.com/v1/images/search?limit=1')
watch(result, () => {
if (result.value) {
console.log('value', result.value[0].url)
}
})
const greetings = ref('')
const updateGreeting = () => {
greetings.value += 'Hello! '
}
const refData = toRefs(data)
const modalIsOpen = ref(false)
const openModal = () => {
modalIsOpen.value = true
}
const onModalClose = () => {
modalIsOpen.value = false
}
return {
...refData,
greetings,
updateGreeting,
x,
y,
result,
loading,
loaded,
modalIsOpen,
openModal,
onModalClose,
error,
changeLang
}
}
});
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
h1 {
font-size: 5rem;
}
button {
font-size: 3rem;
}
</style>
vue2对于typescript的支持非常有限的vue class vue.extends
3-16-typescript对vue的加持
hellworld.vue
<template>
<div class="hello">
<h1>{{ msg }}</h1>
<p>
For a guide and recipes on how to configure / customize this project,<br>
check out the
<a href="https://cli.vuejs.org" target="_blank" rel="noopener">vue-cli documentation</a>.
</p>
<h3>Installed CLI Plugins</h3>
<ul>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-babel" target="_blank" rel="noopener">babel</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-typescript" target="_blank" rel="noopener">typescript</a></li>
<li><a href="https://github.com/vuejs/vue-cli/tree/dev/packages/%40vue/cli-plugin-eslint" target="_blank" rel="noopener">eslint</a></li>
</ul>
<h3>Essential Links</h3>
<ul>
<li><a href="https://vuejs.org" target="_blank" rel="noopener">Core Docs</a></li>
<li><a href="https://forum.vuejs.org" target="_blank" rel="noopener">Forum</a></li>
<li><a href="https://chat.vuejs.org" target="_blank" rel="noopener">Community Chat</a></li>
<li><a href="https://twitter.com/vuejs" target="_blank" rel="noopener">Twitter</a></li>
<li><a href="https://news.vuejs.org" target="_blank" rel="noopener">News</a></li>
</ul>
<h3>Ecosystem</h3>
<ul>
<li><a href="https://router.vuejs.org" target="_blank" rel="noopener">vue-router</a></li>
<li><a href="https://vuex.vuejs.org" target="_blank" rel="noopener">vuex</a></li>
<li><a href="https://github.com/vuejs/vue-devtools#vue-devtools" target="_blank" rel="noopener">vue-devtools</a></li>
<li><a href="https://vue-loader.vuejs.org" target="_blank" rel="noopener">vue-loader</a></li>
<li><a href="https://github.com/vuejs/awesome-vue" target="_blank" rel="noopener">awesome-vue</a></li>
</ul>
</div>
</template>
<script lang="ts">
import { defineComponent } from 'vue'
const component =
defineComponent({
name: 'HelloWorld',
props: {
msg: {
required: true,
type: String
}
},
setup(props, context) {
console.log(props)
console.log(context)
}
})
export default component;
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h3 {
margin: 40px 0 0;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
teleport
瞬间移动,瞬间传送
样式在其他组件当中容易变得混乱
<template>
<teleport to="#modal">
<div id="center" v-if="isOpen">
<h2><slot>this is a modal</slot></h2>
<h2>{{lang}}</h2>
<h2>{{currentUser && currentUser.name}}</h2>
<button @click="buttonClick">Close</button>
</div>
</teleport>
</template>
<script lang="ts">
import { defineComponent, inject } from 'vue'
export default defineComponent({
props: {
isOpen: Boolean,
},
emits: {
'close-modal': null
},
setup(props, context) {
// inject 拿到 provide 提供的数据
const lang = inject('lang')
const currentUser = inject<{ name: string }>('currentUser')
const buttonClick = () => {
context.emit('close-modal')
}
return {
buttonClick,
lang,
currentUser
}
}
})
</script>
<style>
#center {
width: 200px;
height: 200px;
border: 2px solid black;
background: white;
position: fixed;
left: 50%;
top: 50%;
margin-left: -100px;
margin-top: -100px;
}
</style>
3-18-suspense
异步请求的困境
suspense是ue3退出的一个内置的特殊组件,返回一个promise
全局api的修改
全局配置:Vue.config->app.config
config.production被删除
vue.compoent->app.component
行为扩展类api
vue.use->app.use