vue3(一)
本文章主要概述了:
1、webpack和vite构建vue项目的区别
2、vue项目创建以及启动
3、vue官方在vscode中推荐的插件
4、vue项目目录解析
5、src目录解析
6、vue2的组合式API到vue3文件的格式
7、响应式数据ref和reactive
8、响应式解构toRefs
9、v-bind和v-model
10、computed
11、watch及监视的五种情况
12、watchEffect
1、webpack和vite构建vue项目的区别
webpack是先把所有东西准备好再启动服务,vite是先启动服务,再把需要的组件放到服务上。vue官方推荐使用vite构建vue项目。
2、vue项目创建以及启动
- 到项目目录输入
vue create vue@latest
,这是vue官方推荐的写法,但是我更推荐使用vue cli的自定义配置,里面可以选typescript,接下来按提示输入项目信息。到项目目录下,需要输入npm i
安装所有依赖 - 启动项目用何种命令,是看package.json文件中,如果scrips下是dev,那就用
npm run dev
,如果是serve,那就用npm run serve
3、vue官方在vscode中推荐的插件
(1)TypeScript Vue Plugin (2)Vue Language Features
4、vue项目目录解析
(1)public文件夹下面存储的favicon.ico叫做页签图标
(2)src是源代码文件
(3)node_modules是项目的依赖,有点像Java的jar包,如果没有这个文件夹,可以通过npm i
命令来安装所有依赖**
(4)env.d.ts,该文件用于声明所有你要用到的文件,使得项目能够认识它
(5)index.html是vue项目的入口
(6)package-lock.json 和 package.json是包的管理文件
(7)vite.config.ts是用来装插件或配置代理之类的
5、src目录解析
(1)main.ts文件
import { createApp } from 'vue'
//创建应用,相当于花盆
import App from './App.vue'
//引入组件,相当于根,以后你可能会写B.vue,C.vue,这些都是花的支叉。
createApp(App).mount('#app')
//创建应用,每个应用都有一个根组件,根组件就是APP,并把创建的成果挂载到#app的容器里,容器在index.html中就声明了。(在index。html中有这句代码<div id="app"></div>
)
(2)components文件夹
(3)App.vue文件是根
(4)assert文件夹存储图片或css样式
6、vue2的组合式API到vue3文件的格式
<script lang = "ts">
export default {
name: 'Person',
components: {
},
setup(){ // setup生命周期比beforeCreate()还要早
//数据
//方法 //setup里的this是undefined
return{
//要给template用的数据、方法放在这里交出去
}
}
}
</script>
<script lang = "ts" setup>
//这里面写的数据或方法会自动return出去
</script>
7、响应式数据ref和reactive
(1)ref修饰数据
(2)reactive修饰对象或数组
-
对于通过ref函数创建的响应式数据,我们可以通过.value属性来访问其实际值;而对于通过reactive函数创建的响应式对象,我们可以直接访问其属性或调用其方法。
-
ref主要是为了解决单一元素/数据的响应式问题,而reactive则是为了解决JavaScript对象和数组等复杂数据结构的响应式问题。
<script lang = "ts" setup name = "Person">
import { reactive } from 'vue'
let car = reactive({brand: '车1', price: 100})
</script>
8、响应式解构toRefs
let person = reactive({
name: 'zhangsan',
age: 18
})
let { name,age } = person; //普通解构
//上面这一行等价于:
let name = person.name;
let age = person.age;
//上面的name和age都不是响应式的,而下面这一行的name和age都是响应式的
let { name,age } = toRefs(person); //响应式解构,访问要用.value
9、v-bind和v-model
<li v-for="i in games" :key="g.id"></li>
<!-- "v-bind:"含义是把等于号后面的东西当成js表达式去解析 (这里的games是一个数组)-->
再举一个例子:
<input type="text" value="firstname"></input>
,这句代码的意思是写了一个输入框,输入框默认的内容是firstname。当firstname是script里的一个变量的时候要如何书写呢?
答案:<input type="text" v-bind:value="firstname"></input>
这时候,firstname就是一个变量了,但是v-bind不支持双向绑定,也就是说当输入框里的内容变化的时候,firstname这个变量的值是不变的,v-model可以很好的解决这个问题,这样书写:
<input type="text" v-model="firstname"></input>
10、computed
计算属性有一个特点,它是有缓存的,当要计算所依赖的数据只要发生变化,它就得重新计算
let firstName = ref('zhang');
let lastName = ref('san');
let fullName = computed(()=>{
return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' +lastName.value;
})
上面这段代码里的return是指把数据return给template中供它使用,而不是把值返回给方法,这也是computed是只读的原因,它并不会改变fullname的值。而接下来的这种写法,fullname是可读可写的
let firstName = ref('zhang');
let lastName = ref('san');
let fullName = computed(()=>{
get(){
return firstName.value.slice(0,1).toUpperCase() + firstName.value.slice(1) + '-' +lastName.value;
}
set(val){
const [str1,str2] = val.split('-'); //按‘-’拆分字符串
firstName.value = str1;
lastName.value = str2;
}
})
function changeFullName(){ //说明,一个事件绑定了本方法,触发了接下来的修改fullName操作
fullName.value = "li-si"; //本行代码会引起computed里的set调用
}
11、watch及监视的五种情况
vue官方指明,watch只能监视以下四种数据:
- ref定义的数据。
- reactive定义的数据。
- 一个函数,返回一个值
- 一个包含上述内容的数组
情况一:监视ref定义的基本类型数据
<script lang = "ts" setup name = "Person">
import { ref, watch } from 'vue';
//数据
let sum = ref(0);
//方法
function changeSum(){
sum.value += 1;
}
//监视 //格式:watch(谁?,回调函数)
watch(sum,(newValue,oldValue)=>{ //sum不需要.value,因为sum.value不属于上述四种中的一种
console.log('sum变化了',newValue,oldValue);
})
//在vue.js中watch这个函数的返回值是一个停止监视的函数。如果当sum大于10时要停止监视,watch要写成下面这种
const stopWatch = watch(sum,(newValue,oldValue)=>{
console.log('sum变化了',newValue,oldValue);
if(newValue >= 10){
stopWatch();
}
})
</script>
情况二:监视ref定义的对象类型数据
<script lang = "ts" setup name = "Person">
import { ref, watch } from 'vue';
let person = ref({
name: 'zhangsan',
age: 18
})
watch(person,(newValue,oldValue)=>{ //监视的是对象的地址值,要想监视对象内部属性的变化,需要手动开启深度监视
console.log("person变化了",newValue,oldValue)
},{deep: true, immediate: true}) // 加上“{deep: true}”表示开启深度监视
//加上“immediate: true”表示不论数据是否发生变化,都先执行这段监视代码
//当修改整个对象的时候newValue与oldValue值不同,当修改对象内部数据时,newValue等于oldValue的值,实际开发过程中,一般只写一个参数value
function changeName(){
person.value.name += '~'
}
function changeAge(){
person.value.age += 1;
}
function changePerson(){
let person = ref({name: "lisi",age: 90}) //这一行是修改整个人,删除原有对象并重新创建一个对象
//Object.assign(person,{name:'李四',age:90}) //这一行是批量修改属性,并不对原有对象的地址进行修改
}
</script>
情况三:监视reactive定义的对象类型数据
与ref不同的是,reactive是自动开启深度监视的,且不可关闭
情况四:只监视某一对象的某一属性
<script lang = "ts" setup name = "Person">
import { reactive, watch } from 'vue';
let person = reactive({name: 'zhangsan',age: 18})
watch(()=>{return person.name},()=>{
console.log("person.name变化了", newValue, oldValue);
})
function changeName(){
personName += '~';
}
function changeAge(){
personAge += 1;
}
function changePerson(){
let person = reactive({name: "lisi",age: 90})
}
</script>
情况五:监视上述的多个数据
<script lang = "ts" setup name = "Person">
import { reactive, watch } from 'vue';
let person = reactive({name: 'zhangsan',age: 18})
// 监视的对象可以是数组也可以是对象
watch([()=>{return person.name,person.car}],()=>{
console.log("person.name变化了", newValue, oldValue);
})
function changeName(){
personName += '~';
}
function changeAge(){
personAge += 1;
}
function changePerson(){
let person = reactive({name: "lisi",age: 90})
}
</script>
12、watchEffect
立即运行一个函数,提示响应式地追踪其依赖,并在依赖更改时重新执行该函数。
当有两个数据要监视时,可以写成下面这种
<script lang = "ts" setup name = "Person">
import { ref, watch } from 'vue';
let temperature = ref(0);
let height = ref(0)
watch([temperature,height],(val)=>{
//从value中获取最新的水温和水位
let [newTemp,newHeight] = val;
if(newTemp>=60 || newHeight>=80){
console.log("给服务器发请求")
}
})
function changeTemerature(){
temperature.value += 5;
}
function changeHeight(){
height.value += 1;
}
</script>
那当有1000个数据要监视时间,那数组里是不是要写1000个数据呢?为了解决这个问题,引入了watchEffect,它不明确指出要监视哪些属性,函数中要用到哪些属性,就监视哪些属性。
watchEffect(()=>{
if(newTemp>=60 || newHeight>=80){
console.log("给服务器发请求")
}
})