preface
- I guess you’re probably more of a
React
developers - I think you probably felt it a lot
Hooks
theLogic reuse, responsive programming
The convenience of - I guess you might be deeply dependent
Typescript
And like it very muchJSX
The power of expression - I think it’s for your company
Vue2
Although outVue3
Can use the above benefits; But you have to maintain itVue2
The old project - I bet you’re upset and you want to learn
Vue3
Bring in new features and want to refactor existing onesVue2
Project but the cost is too big - I estimate you again so go on, may be want to run away all ~ π»
- .
- purposeThis article is from
React
User view takes you to unlockVue2
In the openComposition API
π and useTSX
π development mode π - Hope this article can help you πͺ don’t panic, you can continue treatment π
The target
- use
Vue2
Adding project TemplatesComposition API
The plug-in - open
.ts
,.tsx
support
Initialize the project
A little ~
Add the Composition API plugin
- Add the dependent
yarn add @vue/composition-api
Copy the code
Enable the TS and TSX support
[email protected] used for this project
- Add the dependent
yarn add -D @vue/babel-preset-jsx @vue/babel-helper-vue-jsx-merge-props @babel/plugin-transform-typescript
Copy the code
- Modifying a Configuration File
- Changing the root Directory
babel.config.js
module.exports = {
presets: [
'@vue/cli-plugin-babel/preset',
+ ['@vue/ babel-jsx ', {compositionAPI: true}], // Preset to start JSX].+ plugins: [
+ ['@babel/plugin-transform-typescript', { isTSX: true }], // εΌε― typescript
+],
}
Copy the code
- Root Directory Creation
vue.config.js
+ const path = require('path')
+ module.exports = {
+ configureWebpack: {
+ resolve: {
+ alias: {
+ '@': path.resolve(__dirname, './src'),
+},
+ extensions: ['.ts', '.tsx'],
+},
+ module: {
+ rules: [
+ {
+ test: /\.(jsx|tsx|ts)$/,
+ loader: 'babel-loader',
+},
+],
+},
+},
+}
Copy the code
- Root Directory Creation
tsconfig.json
+ {
+ "compilerOptions": {
+ "target": "ES2017",
+ "module": "UMD",
+ "allowJs": true,
+ "jsx": "preserve",
+ "moduleResolution": "Node",
+ "allowSyntheticDefaultImports": true,
+ "importHelpers": true,
+ "baseUrl": "./",
+ "paths": {
+ "@/*": ["src/*"]
+}
+}
+}
Copy the code
Modify app.vue -> app.tsx
.vue
Files and.tsx
Can be regarded as equivalent, can be directly used; Pay attention tojsx
The first letter of the component label must be capitalized..png
Static resource usage is directly imported and underpassedurl-loader
Processing; @vue/ CLI integrates static resource configuration
import { defineComponent, onMounted } from '@vue/composition-api'
import HelloWorld from './components/HelloWorld.vue'
import logo from '@/assets/logo.png'
export default defineComponent({
setup() {
onMounted(() = >{})},render() {
return (
<div class="app">
<img alt="Vue logo" src={logo} />
<HelloWorld msg="Welcome to Your Vue.js App"/>
</div>)}})Copy the code
- Attention!
setup
Setup does not support thistsx
, must be written inrender
δΈ - Start the project to see the effect ~ π
yarn serve
Copy the code
Notes
- Full Demo stamp github
- The Demo using API
https://api.github.com/users
- User is defined as follows
export interface User {
avatar_url: string
events_url: string
followers_url: string
following_url: string
gists_url: string
gravatar_id: string
html_url: string
id: number
login: string
node_id: string
organizations_url: string
received_events_url: string
repos_url: string
site_admin: boolean
starred_url: string
subscriptions_url: string
type: string
url: string
}
Copy the code
Write a Component
import { Row, Col, Image } from 'vant'
export default defineComponent({
props: {
users: {
type: Array as { (): User[] }, // Provide the type push to where the call is made
default: [].}},render() {
return (
<Row class="img-box">
{this.users.map((user, idx) => (
<Col
class="img-item"
key={idx}
span={8}
// onclickYou can use both uppercase and lowercaseVue2The built-in $emitthanReactIt's a little easieronclick={()= > this.$emit('click', user)}
>
<Image src={user.avatar_url} />
<div>{user.login}</div>
</Col>
))}
</Row>)}})Copy the code
Write a Hooks
- If you’ve written React Hooks then you already have a rough idea of how to write
- It looks like a regular one
functional
Component, the generic functional component returnsVNode
Hooks, returnstate
// React Hooks
import { useState, useEffect } from 'react'
export function useRequestWithReact() {
const [users, setUsers] = useState([])
useEffect(() = > {
fetch('https://api.github.com/users')
.then(_= > _.json())
.then(data= > {
setUsers(users)
})
}, [])
return { users }
}
// usage
export default() = > {const { users } = useRequestWithReact()
return users.map(user= >
<div key={user.id}>{user.login}</div>)}Copy the code
// Vue2 Composition API
import { ref } from '@vue/composition-api'
export function useRequestWithVue2() {
const users = ref([])
fetch('https://api.github.com/users')
.then(_= > _.json())
.then(data= > {
users.value = data
})
return { users }
}
// usage
export default() = > {const { users } = useRequestWithVue2()
return users.map(user= >
<div key={user.id}>{user.login}</div>)}Copy the code
- The Hooks/Composition API design for both frameworks is really similar, as it is now
Android
εiOS
System π
Contrast with React Hooks
More intuitive with JavaScript overall; Can be called conditionally without restriction of call order; It does not cause engine optimization or GC stress by constantly creating a large number of inline functions during subsequent updates; You don't always need to use useCallback to cache callbacks to child components to prevent overupdating; You don't need to worry about to send the wrong depend on the array to useEffect/useMemo useCallback leading to use outdated values in the callback - Vue rely on tracking is fully automatic.Copy the code
Write a Hooks with Component
How and why?
-
Imagine writing a Component
- Benefits: Reusable UI presentation, internal logic, state
- Disadvantages: Internal logic and state communication need to be handled by certain means, such as Vue and React
-
Imagine that we wrote an Hooks
- Benefits: Provides logic reuse, automatic state update at invocation
-
Can you put Hooks, Component benefits together? (adult world options are π) Function Component, Hooks just return values that look different; What if we “return both”?
- Benefits: Reusable UI presentation, internal logic, state
- With responsive design, the internal state is automatically spit out
- Instead of using various communication methods of components to manually fish out the internal state
-
Design a useCalendar based on Vant
// src/hooks/useCalendar.tsx
import { ref } from '@vue/composition-api'
import { Calendar } from 'vant'
export default function () {
const visble = ref(false)
const date = ref()
const onConfirm = (val) = > {
visble.value = false
date.value = val
}
// This must be wrapped in a function
// The h function cannot be used in setup
// Component needs to be called in dome. TSX's render, which can use the h function with the correct this pointer
// The purpose of not using the arrow function is also to point this correctly
/ /!!!!!!
// React is simpler and easier to understand
// After all, this is a plug-in for vue2, and there are some limitations
/ /!!!!!!
const component = function () {
return <Calendar
vModel={visble.value}
onConfirm={onConfirm}
/>
}
return {
visble,
date,
component,
}
}
// src/views/dome.tsx
import { defineComponent, watch, computed } from '@vue/composition-api'
import { Button } from 'vant'
export default defineComponent({
setup() {
const { date, visble, component } = useCalendar()
watch(date, => {
// Always execute wath's callback automatically after selecting a date
// Instead of manually pulling it out by means of communication
console.log('The date you have chosen is :', date)
})
// ζθ
computed(() => date -> do something...)
return {
visble,
component,
}
},
render() {
return (
<div>
<Button onclick={()= >This.visble = true}> Click to evoke the date</Button>
<hr/>
{this.component()}
</div>)}})Copy the code
- In addition to logic reuse, Hooks also implement UI reuse. You are sure that this is the package for some of the scenarios in your work
Component
orHooks
There will be a new reference at π
Personal opinion on Vue Composition API
- Design closer
Responsive programming
Just as it had beenoperator
ηrxjs
; There’s a smell Ref, reactive
The data source forObservable object;The template
,component
,watch
These can be considered subscribersWatch, watchEffect
The design andmobx
In theReaction, autorun
Basically the same behavior
React Hooks
- React-hooks repeatedly call the current component (function) after setState. UseEffect and useMemo are executed in the current component and deps are used to determine whether to respond. Responsive design is simulated
- A quote from the official website ~ (in case you haven’t noticed)
CSS modular
Vue Cli
It’s already built inxxxx.module.(css|less|sass|scss|styl)
ηwebpack loader
Configuration; Used to openstyle-loader
The modular
// foo.module.less
.foo {
color: aliceblue;
:global {
.bar {
color: skyblue; }}}Copy the code
// foo.tsx
import { defineComponent } from '@vue/composition-api'
import styles from './foo.module.less'
export default defineComponent({
render() {
return (
<div class={styles.foo}>
Foo Component.
<div class="bar">
Bar Component.
</div>
</div>)}})Copy the code
VSCode configuration
emmet
generateclass
Rather thanclassName
{
"emmet.includeLanguages": {
"javascriptreact": "html"."typescriptreact": "html"}}Copy the code
Refer to the article
- Vue 2 plug-in for providing a composite API
- Configurable preset for Vue JSX plugins
- Correct posture for using JSX in Vue