Today, I finished the first VUE3 project, which was relatively complete and independently completed by me from the beginning to the end, using vue3.2 and other relatively new technology stack, so I think it is necessary to record it
First Composition API
Script Setup is officially supported in VUE3 3.2, which greatly simplifies the code for components and reduces the amount of repetitive operations. I think you should use this as the default when writing VUE3. Prior to vue3.2, it was common to write this.
<script> export default {setup(props, CTX){const a = ref(0) // Return {a}}} </script>Copy the code
So now we can write it this way, and compare how many lines of code we saved
<script setup>
const a = ref(0)
</script>
Copy the code
PS: I’m going to omit script setup for the rest of the code, which is under the Script setup tag by default.
You might think this is easier, but on the contrary, the CompositionAPI requires you to be more aware of logic handling and more demanding on encapsulation, otherwise you’ll end up writing uglier code than ever before. Such as:
const a = ref(0) const b = ref('') const c = ref(true) const d = reactive({}) const actionA = ()=>{a.value++} const actionC = ()=>{c.value=! c.value} const actionB = ()=>{b.value += 'test' } const actiond = async ( )=> { const res = await ajax(`url`) d.a = res.a d.b = res.b d.c = res.c } const resetD = ()=>{ Object.keys(d).forEach(key=>delete d[key]) }Copy the code
This is a bunch of code that you write straight out without thinking about logic, without thinking about encapsulation, is it really any better to read than optionsApi? Of course not. It’s a little bit messier here, it’s hard to tell at a glance what variables a function is using, it’s out of order, you need to wrap it, you need to combine it, and that’s one of the things that CompositionAPI is all about.
//usePage.js export default ()=>{ const a = ref(0) const b = ref('') const c = ref(true) const actionA = ()=>{a.value++} const actionC = ()=>{c.value=! C.value} const actionB = ()=>{b.value += 'test'} // return return {a,actionA, b,actionB, c,actionC } } // usePageD.js export default ()=>{ const d = reactive({}) const actionD = async ( )=> { const res = await ajax(`url`) d.a = res.a d.b = res.b d.c = res.c } const resetD = ()=>{ Object.keys(d).forEach(key=>delete d[key]) } return { d,actionD,resetD } }Copy the code
At this point, when we use it in different components, we can use it on demand, assuming we now have two components, A and D
From './usePage' const {A,actionA} = usePage() // D import usePage from './usePageD' const {actionD,resetD} = usePageD()Copy the code
Both of these, naturally, are easier to read when packaged together. Conveniently, he has more playful uses. My current project is a mixed iOS development, which requires the use of jsBridge. Due to the limitations of iOS native, all callbacks are received through other functions. For example, below is the code when I call the native A method
//jsBridge.js
const callBridge = (msg)=>{
try {
window.webkit.xxxHandler.postMessage(msg)
}catch(e){
console.log(msg)
}
}
export const bridgeA = (id,cb='')=>{
const msg = {
func:'A',
params:{id},
cb
}
callBridge(msg)
}
Copy the code
Native will tell me the result (this is pseudocode, I don’t know iOS after all)
evaluateJavaScript(cb(data))
Copy the code
When I use it, I have this logic
// app.vue const store = useStore() window.test = function(data){store.mit ('saveA',data)} // Const handleClick from other components = ()=>{ bridgeA('123','test') }Copy the code
Now, I don’t have to go through vuex. Doesn’t it smell good?
//useBridgeA.js
export default ()=>{
const id = ref('')
const saved = reactive({})
window.test = function(data){
save.data = data
}
const handleClick = ()=>{
bridgeA('123','test')
}
onBeforeUnmount(()=>{window.test = null})
return {saved,handleClick}
}
Copy the code
Best of all, I can register callbacks when I’m using them, remove them when I’m not using them, communicate with Reactive, and I can hide the callback methods. All I need is the result, I don’t have to have all the code in the outer layer.
When I write components, the code will be simpler
<template>
<input v-model="id" />
<button @click="handleClick">
Action A
</button>
</template>
<script setup>
import useBridgeA from './useBridgeA'
const {id,handleClick} = useBridgeA()
</script>
Copy the code
Here I’ve actually established some of the ways I write my VUE3.
The combination is not only the combination of function points, but also some highly correlated methods and variables together.
In the example above, we could have pulled the callback method out and put it in a separate file, and I could have imported it again, but that would have made the project file more and more, and each time we looked up more and more files.
Think about the setup
Very few people think about why this new life cycle is called setup, setup means created, does it just mean when the App is created, so created is a little bit easier to understand.
Setup, I think, is a link, a bridge between the data and template, hence the verb. It’s not a lifecycle per se, it’s an action, it’s where we connect the data to the Vue.
I compare your webApp to a machine, setup is like a power cord, you put your variable, logic, into the power cord, and the machine starts.
The most common problem is forgetting to write.value
In fact, IN VUe3, I prefer ref, because ref has a simple structure and a more reliable and convenient response. For example, when we need to declare a responsive object, you can write these two ways
const a = shallowRef({})
const b = reactive({})
Copy the code
But what happens when you need to replace the entire object? For variables, just change value.
a.value = {c:1}
Copy the code
For variable B, that’s a problem. If you have a simple Object hierarchy, the best I can think of is object.assign
Object.assign(b,{c:1})
Copy the code
If you just delete this c property, for variable A, that’s easy
a.value = {}
Copy the code
What about variable B, the one that uses Reactive, it’s more of a hassle
B = reactive ({}) / / an errorCopy the code
Can I just write it like that? No, that’s an error, because b is a const. So if you think about it a little bit, change const to let
let b = reactive({})
b.c = 1
b = reactive({})
Copy the code
Theoretically that’s fine, as long as B doesn’t depend on anything else or is dependent on anything else. In a way, you lose responsiveness. You can only do that, that’s why I wrote reset earlier, right
Key (b).foreach (key=>delete b[key])Copy the code
In fact, the above points are easy to be ignored, which is why I recommend ref more, but it has both advantages and disadvantages. The biggest problem of ref is that it is easy to forget to write. Value
Const a= ref(0) a=1 const a= ref(0) a=1Copy the code
In this case, I recommend that you use unref, the if judgment above should be written like this
const a = ref(0)
if(unref(a)>0){
// do sth
} else {
// do another
}
Copy the code
You can use unref without mental stress, even if the variable is not ref
Pros and cons of Style V-bind
Style V-bind may not be familiar to many, but I call this a Vue hack on CSS variables. I also occasionally use CSS variables in my projects.
Variable specific CSS tutorial, you can take a look at this link www.ruanyifeng.com/blog/2017/0…
<template>
<p>123</p>
</template>
<style scoped>
p{
color:var(--pcolor)
}
</style>
Copy the code
This is pure native CSS writing, vue help us do a hack. Note that v-bind in style is a string.
<template>
<p>123</p>
</template>
<script setup>
const pcolor = ref('#000')
</script>
<style scoped>
p{
color:v-bind('pcolor')
}
</style>
Copy the code
But I found a problem, in some cases the content attribute in the pseudo element doesn’t seem to work, it’s still the same template, I’ll write a few more p’s
<template> <div> <p>123</p> <p>123</p> <p>123</p> <p>123</p> </div> </template> <script setup> const text = ref('hello') </script> <style scoped> div p:first-of-type:before{ content:v-bind('text') } </style>Copy the code
V-bind doesn’t seem to be working, it’s not showing up, I don’t know if it’s a bug or something, so I suggest you write it like this, right
<template>
<div>
<p :data-text="text">123</p>
<p>123</p>
<p>123</p>
<p>123</p>
</div>
</template>
<script setup>
const text = ref('hello')
</script>
<style scoped>
div p:first-of-type:before{
content:attr('data-text')
}
</style>
Copy the code
pinia or not
Pinia is approximately equal to vuex5, and is used slightly differently from Vuex, which IS how I used it in my project
// store/user.js defines the specific store
export const UserStore = defineStore('user', {
state:() = >({
name:' '.id:' '
})
getters: {nameId:state= >`${state.name}_${state.id}`
}
actions: {async getUserInfo(){}}})//store/index.js
// The advantage of this is that later references can be made directly from '@/store', and when there are too many files, they can be handled automatically via webpack require.context or vite import blob
export {UserStore} from './user'
Copy the code
There is one mutation less than vuex, but it can not be said that there is no mutation, but it is replaced by $patch function, which is more flexible to use
import UserStore from '@/store'
const user = UserStore()
user.name = 'test'
//or
user.$patch({
name:'test',
id:123
})
//or
user.$patch(state =>{
state.name = 'test'
state.id = 123
})
Copy the code
The problem is that Webstorm doesn’t seem to have code prompts in js?
Fully upgrade your project dependencies
Since vuE3 is already used, it means that you are not compatible with IE8, IE9, etc., what can you upgrade your dependency completion to ES8, ES9, and use fetch, without reservation? .,?? These latest syntax, for a better programming experience.