修改vue的默认配置
vue官网生态系统脚手架Vue CLI的配置参考,在根目录新建vue.config.js (之后重启项目)
vue3如何关闭检查
也是跟修改配置一样,新建一个文件夹vue.config.js,官网文档
ref属性
放在html标签上和id是差不多的,但是放在组件标签上会不同
id是获取到dom对象
props属性
子组件传值给父组件
父组件接收
props的值的直接存在了vue实例里面(this),直接打印this.name即可查看
原则上props的值不能更改,但是vue检测的比较浅,直接改变量会报错,如果是对象不会报错,因为是更改对象里面的一个值,vu检测不到
混合配置(js)
新建一个js,放共同配置
export const hunhe = {
methods: {
showName(){
alert(this.name)
}
},
mounted() {
console.log('你好啊!')
},
}
export const hunhe2 = {
data() {
return {
x:100,
y:200
}
},
}
直接安装less-loader报错
由于vue用的是4.46.0较为稳定版本(5.0以上还有待检验)
直接npm i less-loader是安装最新版本,最新版本8-9是为5.0安装的,所以需要降一个版本安装7的
查看各版本的命令:npm view less- loader versions
所以需要安装的是npm i less-loader@7,才不会报错,同样安装sass也是一样的,需要降低版本安装
父组件传递函数给子组件,子组件可以通过函数将信息传给父组件
遍历列表时虚拟DOM的作用
数据变化话会先将新虚拟DOM的内容与旧的进行对比,如果是一样的就从真实DOM里直接拿,不一样要将新虚拟DOM的内容转化成真实内容
以index作为key有时会出现问题(后面数据错位)
以数据里的id作为key才不会出现问题
一个字符串里面是包含空字符串的
'abcd'.indexOf('') ==0
'abcd'.indexOf('a') ==0
过滤
data:{
keyWord:'',
persons:[
{id:'001',name:'马冬梅',age:19,sex:'女'},
{id:'002',name:'周冬雨',age:20,sex:'女'},
{id:'003',name:'周杰伦',age:21,sex:'男'},
{id:'004',name:'温兆伦',age:22,sex:'男'}
],
filPerons:[]
},
//用watch进行过滤
watch:{
keyWord:{
immediate:true,//因为初始化的时候keyWord是空数组,一开始如果不先执行一下watch,会初始化无数据,随便写个数据删除之后可以显示所有数据(一个字符串里面是包含空字符串的)
handler(val){
this.filPerons = this.persons.filter((p)=>{
return p.name.indexOf(val) !== -1
})
}
}
}
//用computed进行过滤
computed: {
filPerons() {
return this.persons.filter((p) => {
return p.name.indexOf(this.keyWord) !== -1
})
}
}
可以对上面过滤到的数据进行筛选
data:{
keyWord:'',
sortType:0, //0原顺序 1降序 2升序
persons:[
{id:'001',name:'马冬梅',age:30,sex:'女'},
{id:'002',name:'周冬雨',age:31,sex:'女'},
{id:'003',name:'周杰伦',age:18,sex:'男'},
{id:'004',name:'温兆伦',age:19,sex:'男'}
]
},
computed:{
filPerons(){
const arr = this.persons.filter((p)=>{
return p.name.indexOf(this.keyWord) !== -1
})
//判断一下是否需要排序
if(this.sortType){
arr.sort((p1,p2)=>{
return this.sortType === 1 ? p2.age-p1.age : p1.age-p2.age
})
}
return arr
}
}
Vue监测数据改变的原理_数组
在Vue修改数组中的某个元素一定要用如下方法:
1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2.Vue.set() 或 vm.$set()
如果直接修改arr[0]='xxx’页面是无法更新的,内部数据更改了,但是vue检测不到,vue检测得到数据变化得数组使用那7个api
但是对数组整个进行更替是可以的。例如:arr=[‘a’,‘b’]
vue检测总结
对2.(1)对象中后追加的属性:可以添加,但是没有做响应式处理,后面没有set与get的方法
如果是使用2.(2)Vue.set(target,propertyName/index,value) 或 vm.$set(target,propertyName/index,value)使用了api
<!--
Vue监视数据的原理:
1. vue会监视data中所有层次的数据。
2. 如何监测对象中的数据?
通过setter实现监视,且要在new Vue时就传入要监测的数据。
(1).对象中后追加的属性,Vue默认不做响应式处理,可以添加属性,但是属性没有响应式
(2).如需给后添加的属性做响应式,请使用如下API:
Vue.set(target,propertyName/index,value) 或
vm.$set(target,propertyName/index,value)
3. 如何监测数组中的数据?
通过包裹数组更新元素的方法实现,本质就是做了两件事:
(1).调用原生对应的方法对数组进行更新。
(2).重新解析模板,进而更新页面。
4.在Vue修改数组中的某个元素一定要用如下方法:
1.使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、reverse()
2.Vue.set() 或 vm.$set()
特别注意:Vue.set() 和 vm.$set() 不能给vm 或 vm的根数据对象 添加属性!!!
-->
vm与vc
vm的Vue的实例对象(它们的this均是【Vue实例对象】),
vc是vue组件的实例对象(它们的this均是【VueComponent实例对象】)
一个重要的内置关系
1.一个重要的内置关系:VueComponent.prototype.proto === Vue.prototype
2.为什么要有这个关系:让组件实例对象(vc)可以访问到 Vue原型上的属性、方法。
例如:Vue.prototype.x = 99
在组件中可以用this.x直接访问到x
全局事件总线
任意组件间通信,所以要安装全局事件总线定义一个所有组件或都可以看见的
安装事件全局总线
new Vue({
......
beforeCreate() {
Vue.prototype.$bus = this //安装全局事件总线,$bus就是当前应用的vm
},
......
})
使用事件总线:
接收数据:School组件想接收student的数据,则在School组件中给$bus绑定自定义事件,事件的回调留在School组件自身。
//school组件
methods(){
demo(data){......}
}
mounted() {
this.$bus.$on('hello',(data)=>{
this.demo(data)
console.log('我是School组件,收到了数据',data)
})
}
//也可以这么写
mounted() {
this.$bus.$on('hello',this.demo)
}
student组件提供数据:this. b u s . bus. bus.emit(‘hello’,数据)
消息订阅与发布(pubsub)与全局事件总线很像
安装pubsub:npm i pubsub-js
引入: import pubsub from ‘pubsub-js’
接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件自身。
methods(){
demo(data){......}
}
......
mounted() {
this.pubId= pubsub.subscribe('xxx',this.demo) //订阅消息
}
beforeDestroy() {
pubsub.unsubscribe(this.pubId)
},
提供数据:pubsub.publish(‘xxx’,数据)
最好在beforeDestroy钩子中,用PubSub.unsubscribe(pid)去取消订阅。
nextTick
语法:this.$nextTick(回调函数)
作用:在下一次 DOM 更新结束后执行其指定的回调。
什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。
例如:
//编辑
handleEdit(todo){
if(todo.hasOwnProperty('isEdit')){
todo.isEdit = true //将这个列表的isEdit数据更改成true
}else{
// console.log('@')
this.$set(todo,'isEdit',true)
}
//如果不使用this.$nextTick等待DOM 更新结束后执行,会无效,因为dom要等模板都解析完再执行,页面还没有input你却让input标签聚焦,所以无效,要等执行完dom更新再回调
this.$nextTick(function(){
this.$refs.inputTitle.focus()
})
},
作用域插槽
理解:数据在组件的自身,但根据数据生成的结构需要组件的使用者来决定。(games数据在Category组件中,但使用数据所遍历出来的结构由App组件决定)
数据在子组件中,父组件想拿到
具体编码:
//父组件中:组件的使用者拿到组件插槽的数据,并且显示自定义的展示结构
<Category>
<template scope="scopeData">
<!-- 生成的是ul列表 -->
<ul>
<li v-for="g in scopeData.games" :key="g">{{g}}</li>
</ul>
</template>
</Category>
<Category>
<template slot-scope="scopeData">
<!-- 生成的是h4标题 -->
<h4 v-for="g in scopeData.games" :key="g">{{g}}</h4>
</template>
</Category>
//子组件中:将数据传给插槽 <slot :games="games"></slot>
<template>
<div>
<slot :games="games"></slot>
</div>
</template>
<script>
export default {
name:'Category',
props:['title'],
//数据在子组件自身
data() {
return {
games:['红色警戒','穿越火线','劲舞团','超级玛丽']
}
},
}
</script>
VUEX
1.搭建vuex环境:创建文件:src/store/index.js
//引入Vue核心库
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)
//准备actions对象——响应组件中用户的动作
const actions = {}
//准备mutations对象——修改state中的数据
const mutations = {}
//准备state对象——保存具体的数据
const state = {}
//创建并暴露store
export default new Vuex.Store({
actions,
mutations,
state
})
2.在main.js中创建vm时传入store配置项
......
//引入store
import store from './store'
......
//创建vm
new Vue({
el:'#app',
render: h => h(App),
store
})
3.基本使用
组件中读取vuex中的数据:$store.state.sum
组件中修改vuex中的数据:$store.dispatch(‘action中的方法名’,数据)
备注:若没有网络请求或其他业务逻辑,组件中也可以越过actions,即不写dispatch,直接编写commit($store.commit(‘mutations中的方法名’,数据))
例如用最简单的方法
methods: {
increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
},
incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
},
},
例如在组件中调用并且使用mapState等方法
<template>
<div>
<h1>当前求和为:{{sum}}</h1>
<h3>当前求和放大10倍为:{{bigSum}}</h3>
<h3>我在{{school}},学习{{subject}}</h3>
<select v-model.number="n">
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
</select>
<button @click="increment(n)">+</button>
<button @click="decrement(n)">-</button>
<button @click="incrementOdd(n)">当前求和为奇数再加</button>
<button @click="incrementWait(n)">等一等再加</button>
</div>
</template>
<script>
import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
export default {
name:'Count',
data() {
return {
n:1, //用户选择的数字
}
},
computed:{
//借助mapState生成计算属性,从state中读取数据。(对象写法)
// ...mapState({he:'sum',xuexiao:'school',xueke:'subject'}),
//借助mapState生成计算属性,从state中读取数据。(数组写法)
...mapState(['sum','school','subject']),
//借助mapGetters生成计算属性,从getters中读取数据。(对象写法)
// ...mapGetters({bigSum:'bigSum'})
//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
...mapGetters(['bigSum'])
},
methods: {
//程序员亲自写方法
/* increment(){
this.$store.commit('JIA',this.n)
},
decrement(){
this.$store.commit('JIAN',this.n)
}, */
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法),不需要传参是因为默认把 increment(n)里的n作为参数传递过去了,如果页面中increment方法没有传参的话会把(increment(event))中默认带的event作为参数传递过去
...mapMutations({increment:'JIA',decrement:'JIAN'}),
//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
// ...mapMutations(['JIA','JIAN']),
/* ************************************************* */
//程序员亲自写方法
/* incrementOdd(){
this.$store.dispatch('jiaOdd',this.n)
},
incrementWait(){
this.$store.dispatch('jiaWait',this.n)
}, */
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
// ...mapActions(['jiaOdd','jiaWait'])
},
mounted() {
const x = mapState({he:'sum',xuexiao:'school',xueke:'subject'})
console.log(x)
},
}
</script>
<style lang="css">
button{
margin-left: 5px;
}
</style>
export default {
namespaced:true,
actions:{
jiaOdd(context,value){
console.log('actions中的jiaOdd被调用了')
if(context.state.sum % 2){
context.commit('JIA',value)
}
},
jiaWait(context,value){
console.log('actions中的jiaWait被调用了')
setTimeout(()=>{
context.commit('JIA',value)
},500)
}
},
mutations:{
JIA(state,value){
console.log('mutations中的JIA被调用了')
state.sum += value
},
JIAN(state,value){
console.log('mutations中的JIAN被调用了')
state.sum -= value
},
},
state:{
sum:0, //当前的和
school:'尚硅谷',
subject:'前端',
},
getters:{
bigSum(state){
return state.sum*10
}
},
}
flex布局
参考博客链接
了解flex布局是几个属性
flex-direction :设置谁为主轴,子元素是根据主轴来排列的
justify-content:设置主轴上的子元素排列方式
flex-wrap:设置是否换行(默认不换行)
align-items 设置侧轴上的子元素排列方式(单行 )
align-content 设置侧轴上的子元素的排列方式(多行)