串讲
第1章 MVVM
MVVM框架分为三个部分:分别是M(Model,模型层 ),V(View,视图层),VM(ViewModel,V与M连接的桥梁,也可以看作为控制器)
- M:模型层,主要负责业务数据相关;
- V:视图层,顾名思义,负责视图相关,细分下来就是html+css层;
- VM:V与M沟通的桥梁,负责监听M或者V的修改,是实现MVVM双向绑定的要点;主要通过创建vue实例来实现
第2章 指令
-
v-text:更新元素的innerText {{}}
-
v-html:更新元素的innerHTML
3.v-bind: 简写成冒号: 控制属性例:
:class
:src
:to -
v-model 双向绑定 v-m互相影响
5.v-on 简写成 @ @click 事件绑定
6.event.preventDefault() 阻止浏览器默认行为
event.stopPropagation() 阻止事件冒泡
事件修饰符<div class="div1" @click="divEvent1" @contextmenu.prevent>
<div class="div2" @click.stop="divEvent2"></div>
</div>
3.分支和循环指定
v-if
v-else-if
v-else
v-show
*** v-show v-if两者的不同: ***
- v-if是真正的条件渲染,因为它会确保在切换过程中条件块内的事件监听器和子组件适当地被销毁和重建。v-if是在DOM层面控制,v-show是控制display属性
- v-if是惰性的,只有当条件为true时才会渲染,如果条件为false则什么都不做
- v-if有很高的切换开销,适用于条件不太容易改变的时候
- v-show不管条件是true还是false都会进行渲染。并且只是简单地基于 CSS 进行切换
- v-show有很高的初始渲染开销,适用于非常频繁地切换
v-for
循环json对象
user: {
userId: 1,
userName: '张三',
userSex: '男'
}
<p v-for="(value,key,index) in user">{{index}}:{{key}}:{{value}}</p>
遍历数组:
userArr: [{
userId: 1,
userName: '张三',
userSex: '男'
}, {
userId: 2,
userName: '李四',
userSex: '女'
}, {
userId: 3,
userName: '王五',
userSex: '男'
}]
<div id="app">
<ul v-for="user in users" :key="user.userId">
<li>{{user.userName}} {{user.password}}</li>
</ul>
<ul v-for="(user,index) in users" :key="user.userId">
<li>{{index}} {{user.userName}} {{user.password}}</li>
</ul>
</div>
上面实例中存在一个问题:当更改数组中某一个元素时,Vue会对整个数组进行重新渲染。在实际开发中,这样的代码是不被允许的,在数据量很多的时候,它会严重降低页面的性能。
这时,你可以加唯一性key值,增加后vue就会辨认出哪些内容被渲染后并没有变化,而只渲染新变化的内容。
第三章 Vue进阶
计算属性 监听器 方法
在vue中处理复杂的逻辑的时候,我们经常使用计算属性、方法及监听器。
- methods:方法:它们是挂载在Vue对象上的函数,通常用于做事件处理函数,或自己封装的自定义函数。
- computed:计算属性:在Vue中,我们可以定义一个计算属性,这个计算属性的值,可以依赖于某个data中的数据。或者说:计算属性是对数据的再加工处理。
- watch:监听器:如果我们想要在数据发生改变时做一些业务处理,或者响应某个特定的变化,我们就可以通过监听器,监听数据的变化,从而做出相应的反应。
计算属性是进行缓存的。计算属性只有在它的相关依赖发生改变的时候才会重新求值,这就意味着只要message还没有发生改变,多次访问reversedMessage计算属性立即返回的是之前计算的结果,而不会再次执行计算函数。
而对于methods方法,只要发生重新渲染,methods调用总会执行该函数。
如果某个computed需要的遍历一个极大的数组和做大量的计算,可以减小性能开销,如果不希望有缓存,则用methods。
计算属性:
{{reversedMsg}}
computed: {
reversedMsg() {
return this.msg.split('').reverse().join('');
}
}
watch:新值在前,旧值在后
深度监听虽然可以监听对象数据变化,但获取不到旧值,可以通过json转换来完成监听对象
watch:{
quantity(newVal,oldVal){
console.log(newVal,oldVal);
this.quantity = newVal<=0?oldVal:newVal
}
}
监听对象(计算属性+监听器+ json转换)
computed:{
goodsStr(){ //这里新添加一个计算属性,将对象转变为字符串
return JSON.stringify(this.goods);
}
},
watch:{
goodsStr(newVal,oldVal){ //这里不再监听对象,而是监听字符串
let newGoods = JSON.parse(newVal);
let oldGoods = JSON.parse(oldVal);
this.goods.quantity = newGoods.quantity<=0?oldGoods.quantity:newGoods.quantity;
}
}
v-mode实现表单绑定
data() {
return {
myForm: {
username: '',
password: '',
...
}
}
}
<form>
用户名:<input type="text" v-model="myForm.username" /><br>
密码:<input type="password" v-model="myForm.password" /><br>
确认密码:<input type="password" v-model="myForm.beginpassword" /><br>
</form>
v-model中还可以使用一些修饰符来实现某些功能:
- v-model.lazy 只有在input输入框发生一个blur时才触发,也就是延迟同步到失去焦点时。
- v-model.trim 将用户输入的前后的空格去掉。
- v-model.number 将用户输入的字符串转换成number。
第四章组件
组件传参
子组件给父组件传 this. $emit(事件名,1-n个参数)
父组件给子组件传 props
父组件向子组件传递数据是单向的(只读)。也就是说:子组件可以接收并使用父组件传递过来的数据,但子组件不能修改此数据。
多级组件通信 inject(孙子) provide(爷爷)
provide(){
return{
param1:"爷爷给你的"
}
},
inject:['param1']
第五章 路由和路由传参
router.js 里配置嵌套路由 children:[{},{}]
父组件指定路由出口 <router-view/>
-- params传参
<router-link :to="{name:'newslist2', params: {id:45678,msg:'登录'}}">新闻params传参</router-link>
this.$router.push({ name: 'user', params: { id: 123 }})
this.$route.params.id {{$route.params.id}}
-- query传参
<router-link :to="{path:'newslist2',query:{id:8907777}}">query2</router-link>
this.$router.push({ path: 'user', query: { id: 123 }})
this.$route.query.id {{ $route.query.id }}
- query方式:类似于get方式,参数会在路由中显示,可以用做刷新后仍然存在的参数。利用路由规则中的path跳转。
- params方式:类似于post方式,参数不会在路由中显示,页面刷新后参数将不存在。利用路由规则中的name跳转。
-- 动态路由传参
restful 在路径里携带参数
{
path: '/newslist/:userId/',
name: 'newslist',
component: newslist
}
<router-link to="/newslist/123">美国新冠肺炎确诊病例升至50206例 死亡606例</router-link>
第6章生命周期
7.8是vue2和vue3区别
vue3.0
- beforeCreate: 实例创建之前(setup里没有)
- created:实例创建完毕(setup里没有)
- beforeMount:DOM挂载之前
- mounted:DOM挂载完毕
- beforeUpdate:数据更新之前
- updated:数据更新完毕
- beforeUnmount:解除DOM挂载之前
- unmounted:解除DOM挂载完毕
vue2.0
- beforeCreate:组件实例创建之前
- created:组件实例创建完毕
- beforeMount:组件DOM挂载之前
- mounted:组件DOM挂载完毕
- beforeUpate:组件数据更新之前
- updated:组件数据更新完毕
- beforeDestroy:组件实例销毁之前
- destroyed:组件实例销毁完毕
第8章Vuex
Vuex中有五个默认的基本对象:
● state: state就是Vuex中的公共的状态, 可以将state看作是全局唯一的共享数据仓库。
类似Vue中的data。(state是所以组件共享的;data是某个组件独有的。)
● getters: state 的计算属性,类似Vue中的computed 计算属性。
● mutations:声明方法,用于修改state。类似Vue中的mothods方法。(只能修改同步数据)。
● actions:声明方法,用于修改state。类似Vue中的mothods方法。(可以修改异步数据)。比如调用api接口都在这里完成。
● modules:store的子模块,只在开发大型项目的时候会用的上。
mutations: {
addMethod(state,param){
state.num += param;
}
}
this.$store.commit('addMethod',6);
actions: {
addMethod(state,param){
//这里使用setTimeout模拟异步方法
setTimeout(()=>{
state.commit('addMethod',param);
},3000);
}
}
this.$store.dispatch('addMethod',6);
总结:
1. state:存放全局共享数据。使用形式:store.getters.newnum
3. mutations:处理同步数据的方法。使用形式:store.dispatch('addMethod',6);
○ 先使用 $store.dispatch('addMethod',6); 的方式调用Vuex中的actions。
○ actions再使用commit方法调用Vuex中的mutations;
axios##
get 两种
axios.get('http://api.tianapi.com/txapi/ncovcity/index?key=自己的key')
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
axios.get('http://api.tianapi.com/txapi/ncovcity/index',{params:{key:value}})
.then(function(response) {
console.log(response);
})
.catch(function(error) {
console.log(error);
});
post:两种方式
1)this.form=>相当于传json到后台去,将来会
axios.post("/weather/query", this.form)
.then((response)=>{
console.log(response.data)
state.res=response.data.result;
})
2)post对象到后台 用qs处理 key=value&key=value
axios.post("/weather/query", qs.stringify(this.form))
.then((response)=>{
console.log(response.data)
state.res=response.data.result;
})
跨域
1‘前端跨域,vue.config.js设置代理proxy
proxy: {
'/weather': {
target: 'http://apis.juhe.cn/simpleWeather', //需要跨域的url
ws: true, //代理webSocket
changeOrigin: true, //允许跨域
pathRewrite: {
'^/weather': '' //重写路径
}
},
'/jztk': {
target: 'http://v.juhe.cn/jztk', //需要跨域的url
ws: true, //代理webSocket
changeOrigin: true, //允许跨域
pathRewrite: {
'^/jztk': '' //重写路径
}
}
}
组合式api
● reactive:用于定义引用类型。只能修改数据,不能改变其引用。
● ref:用于定义基本类型和引用类型。可以修改数据,也可以改变其引用。
○ 在方法中修改数据时需要使用 value属性。因为,Ref的本质是通过Reactive创建的,Ref(10) 就相当于:Reactive({value:10});
○ 在视图模板调用可以省略value属性的书写。
doubleCount: computed(() => { //使用computed函数
return state.count * 2;
})
watch(state,(newValue, oldValue) => {
console.log(newValue, oldValue);
}
)
*** 组件传参 ***
父子组件,setup() 函数有两个参数:props 和 context。
setup(props, context) {
console.log(props.msg)
function send() {
context.emit("childmsg", "hello world!");
}
},
props:[]
祖孙
import { inject } from "vue";
setup(props, context) {
console.log(inject('msg'))
return {};
}
import { provide } from "vue";
setup() {
provide('msg','hello');
}
选项式API setup () 内部调用生命周期钩子
beforeCreate() setup()
created() setup()
beforeMount() onBeforeMount()
mounted() onMounted()
beforeUpdate() onBeforeUpdate()
updated() onUpdated()
beforeUnmount() onBeforeUnmount()
unmounted() onUnmounted()
import { useRouter } from "vue-router";
setup() {
const router = useRouter();
function toHome(){
router.push('/');
}
function toAbout(){
router.push({path:'/about',query:{name:'zhangsan'}});
}
return {
toHome,
toAbout
}
}
语法糖方式
1、<script setup>
2、引入的组件不必注册,可以直接使用。
3、const myProps = defineProps(['msg','num'])
4、const emit = defineEmits(['childmsg']);
const send = () => {
emit('childmsg','子组件向父组件传的值');
}