常用Vue功能及语法

常用Vue功能及语法

因为自己工作中容易遗忘语法,只是用于快速查看。其他不常用的就不列举了。为了快速使用
Vue没有基础的建议学完该视频:https://www.bilibili.com/video/BV1Zy4y1K7SH?p=122&spm_id_from=pageDriver

一、计算属性-computed

方式一、全写方式

	computed:{
				
	 	fullName:{
		//get有什么作用?当有人读取fullName时,get就会被调用,且返回值就作为fullName的值
		//get什么时候调用?1.初次读取fullName时。2.所依赖的数据发生变化时。
			get(){
				console.log('get被调用了')
			 	return this.firstName + '-' + this.lastName
			},
				//set什么时候调用? 当fullName被修改时。
			set(value){
				console.log('set',value)
				const arr = value.split('-')
				this.firstName = arr[0]
				this.lastName = arr[1]
			}
		},

方式二、简写方式

	computed:{
		//简写
		fullName(){
			console.log('get被调用了')
				return this.firstName + '-' + this.lastName
			}
		}

二、监视属性-watch

	watch:{
				//监视多级结构中某个属性的变化
				 'numbers.a':{
					handler(){
						console.log('a被改变了')
					}
				}, 
				//监视多级结构中所有属性的变化
				numbers:{
					deep:true,
					handler(newValue,oldValue){
						console.log('numbers改变了')
					}
				}
			}

三、绑定样式

1.绑定class样式-- 字符串写法

适用于:样式的类名不确定,需要动态指定

<div class="basic" :class="mood" @click="changeMood">{{name}}</div>
changeMood(){
		const arr = ['happy','sad','normal']
		const index = Math.floor(Math.random()*3)
		this.mood = arr[index]
	}
.happy{
	....省略
	}
.sad{
	....省略
	}

2.绑定class样式–数组写法

适用于:要绑定的样式个数不确定、名字也不确定

<div class="basic" :class="classArr">{{name}}</div>
// Vue中
data:{
	classArr:['class1','class2','class3'],
}
.class1{
...省略
}
.class2{
...省略
}

3.绑定class样式–对象写法

适用于:要绑定的样式个数确定、名字也确定,但要动态决定用不用

<div :class="classObj">{{name}}</div>
// Vue中
data(){
	return{
		classObj:{
			class1:false,
			class2:false,
			},
	}
}
.class1{
...省略
}
.class2{
...省略
}

4.绑定style样式–对象写法

<div  :style="styleObj">{{name}}</div>
// Vue中
data:{
	styleObj:{
		fontSize: '40px',
		color:'red',
			}
}

4.绑定style样式–数组写法

<div :style="styleArr">{{name}}</div>
// Vue中
data:{
	styleArr:[
			{
				fontSize: '40px',
				color:'blue',
			},
			{
				backgroundColor:'gray'
			}
			]
}

5.绑定style样式-标签写法

<div  :style="[{'fontSize': '40px','color':'blue'}]">{{name}}</div>

四、过滤器

<!--方式一-->
<h3>现在是:{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
<!--方式二-->
<h3 :x="msg | mySlice"></h3>
//全局过滤器
Vue.filter('mySlice',function(value){
	return value.slice(0,4)
})
// vue属性中
new Vue({
	//局部过滤器
	filters:{
		timeFormater(value,str='YYYY年MM月DD日 HH:mm:ss'){
		// console.log('@',value)
		return dayjs(value).format(str)
		}
	}
})

五、Vue组件传值

1.父传子
<template>
	<!--父亲组件中-->
	<Student name="李四" sex="" :age="18" />
</template>
<script>
	import Student from './components/Student'
	export default {
		name:'App',
		components:{Student}
	}
</script>
<template>
	<div>
		<h1>{{msg}}</h1>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<h2>学生年龄:{{myAge+1}}</h2>
		<button @click="updateAge">尝试修改收到的年龄</button>
		<button @click="sendSchoolName">把学校名给App</button>
	</div>
</template>

<script>
	export default {
		name:'Student',
		data() {
			return {
				msg:'我是一个尚硅谷的学生',
				myAge:this.age
			}
		},
		methods: {
			sendSchoolName(){
				this.getSchoolName(this.name)
			},
			updateAge(){
				this.myAge++
			}
		},
		//简单声明接收
		// props:['name','age','sex','getSchoolName'] 

		//接收的同时对数据进行类型限制
		/* props:{
			name:String,
			age:Number,
			sex:String
		} */

		//接收的同时对数据:进行类型限制+默认值的指定+必要性的限制
		props:{
			name:{
				type:String, //name的类型是字符串
				required:true, //name是必要的
			},
			age:{
				type:Number,
				default:99 //默认值
			},
			sex:{
				type:String,
				required:true
			}
		}
	}
</script>

2.子传父
一、方式一 —— props

<template>
	<!--父亲组件中-->
	<Student :getSchoolName="getSchoolName"/>
</template>
<script>
	import Student from './components/Student'
	export default {
		name:'App',
		components:{Student},
		methods: {
			getSchoolName(name){
				console.log('App收到了学校名:',name)
			},
		}
	}
</script>
<template>
	<div>
		<h1>{{msg}}</h1>
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<h2>学生年龄:{{myAge+1}}</h2>
		<button @click="sendSchoolName">把学校名给App</button>
	</div>
</template>

<script>
	export default {
		name:'Student',
		//简单声明接收
		props:['getSchoolName'],
		data() {
			return {
				msg:'我是一个学生',
				myAge:this.age
			}
		},
		methods: {
			sendSchoolName(){
				this.getSchoolName(this.name)
			}
		}
	}
</script>

二、方式二 —— 绑定一个自定义事件(使用@或v-on

<template>
	<!--父亲组件中-->
	<Student @getSchoolName="getSchoolName"/>
</template>
<script>
	import Student from './components/Student'
	export default {
		name:'App',
		components:{Student},
		methods: {
			getSchoolName(name,...params){
				console.log('App收到了学校名:',name)
			},
		}
	}
</script>
<template>
	<!--子组件中-->
	<div class="student">
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<h2>当前求和为:{{number}}</h2>
		<button @click="sendStudentlName">把学生名给App</button>
	</div>
</template>

<script>
	export default {
		name:'Student',
		methods: {
			sendStudentlName(){
				//触发Student组件实例身上的getSchoolName事件
				this.$emit('getSchoolName',this.name,666,888,900)
			},
			unbind(){
				this.$off('getSchoolName') //解绑一个自定义事件
				// this.$off(['getSchoolName','demo']) //解绑多个自定义事件
				// this.$off() //解绑所有的自定义事件
			},
			death(){
				this.$destroy() //销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效。
			}
		},
	}
</script>

三、方式三 —— 绑定一个自定义事件(使用ref

<template>
	<!--父亲组件中-->
	<Student ref="student"/>
</template>
<script>
	import Student from './components/Student'
	export default {
		name:'App',
		components:{Student},
		methods: {
		getStudentName(name,...params){
				console.log('App收到了学生名:',name,params)
				this.studentName = name
			},
		},
		mounted() {
			this.$refs.student.$on('getStudentName',this.getStudentName) //绑定自定义事件
			// this.$refs.student.$once('getStudentName',this.getStudentName) //绑定自定义事件(一次性)
		},
	}
</script>
<template>
	<!--子组件中-->
	<div class="student">
		<h2>学生姓名:{{name}}</h2>
		<h2>学生性别:{{sex}}</h2>
		<h2>当前求和为:{{number}}</h2>
		<button @click="sendStudentlName">把学生名给App</button>
	</div>
</template>

<script>
	export default {
		name:'Student',
		methods: {
			sendStudentlName(){
				//触发Student组件实例身上的getSchoolName事件
				this.$emit('getSchoolName',this.name,666,888,900)
			},
			unbind(){
				this.$off('getSchoolName') //解绑一个自定义事件
				// this.$off(['getSchoolName','demo']) //解绑多个自定义事件
				// this.$off() //解绑所有的自定义事件
			},
			death(){
				this.$destroy() //销毁了当前Student组件的实例,销毁后所有Student实例的自定义事件全都不奏效。
			}
		},
	}
</script>
3.兄弟之间 - bus

首先在main.js中挂载出全局bus

//创建vm
new Vue({
	el:'#app',
	render: h => h(App),
	beforeCreate() {
		Vue.prototype.$bus = this //安装全局事件总线
	},
})

接下来使用如下:

<template>
	<div>
		<!--兄弟组件 一-->
		<button @click="sendStudentName">把学生名给School组件</button>
	</div>
</template>

<script>
	export default {
		name:'Student',
		data() {
			return {
				name:'张三'
			}
		},
		methods: {
			sendStudentName(){
				this.$bus.$emit('hello',this.name)
			}
		},
	}
</script>
<template>
		<!--兄弟组件 二-->
</template>

<script>
	export default {
		name:'School',
		data() {
			return {
				name:'张三'
			}
		},
		mounted() {
			// console.log('School',this)
			this.$bus.$on('hello',(data)=>{
				console.log('我是School组件,收到了数据',data)
			})
		},
		beforeDestroy() {
			this.$bus.$off('hello')  // 组件销毁卸载事件
		},
	}
</script>

六、配置代理服务器

建立vue.config.js

module.exports = {
  pages: {
    index: {
      //入口
      entry: 'src/main.js',
    },
  },
	lintOnSave:false, //关闭语法检查
	//开启代理服务器(方式一)
	/* devServer: {
    proxy: 'http://localhost:5000'
  }, */
	//开启代理服务器(方式二)
	devServer: {
    proxy: {
      '/atguigu': {
        target: 'http://localhost:5000',
          pathRewrite:{'^/atguigu':''},
        // ws: true, //用于支持websocket
        // changeOrigin: true //用于控制请求头中的host值
      },
      '/demo': {
        target: 'http://localhost:5001',
				pathRewrite:{'^/demo':''},
        // ws: true, //用于支持websocket
        // changeOrigin: true //用于控制请求头中的host值
      }
    }
  }
}

七、插槽

1.默认插槽
	<div class="category">
		<h3>{{title}}分类</h3>
		<!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
		<slot>我是一些默认值,当使用者没有传递具体结构时,我会出现</slot>
	</div>

使用如下

	<Category title="美食" >
			<img src="https://s3.ax1x.com/2021/01/16/srJlq0.jpg" alt="">
	</Category>

2.具名插槽

<div class="category">
	<h3>{{title}}分类</h3>
	<!-- 定义一个插槽(挖个坑,等着组件的使用者进行填充) -->
	<slot name="center">我是一些默认值,当使用者没有传递具体结构时,我会出现1</slot>
	<slot name="footer">我是一些默认值,当使用者没有传递具体结构时,我会出现2</slot>
</div>

使用如下

<Category title="美食" >
		<!--方式一-->
		<video slot="center" controls src="http://clips.vorwaerts-gmbh.de/big_buck_bunny.mp4"></video>
		<!--方式二-->
			<template v-slot:footer>
				<div class="foot">
					<a href="http://www.atguigu.com">经典</a>
					<a href="http://www.atguigu.com">热门</a>
					<a href="http://www.atguigu.com">推荐</a>
				</div>
				<h4>欢迎前来观影</h4>
			</template>
</Category>

3.作用域插槽

<div class="category">
		<!--category组件中绑定games:['红色警戒','穿越火线','劲舞团','超级玛丽']-->
		<h3>{{title}}分类</h3>
		<slot :games="games" msg="hello">我是默认的一些内容</slot>
</div>

使用如下

<div class="container">

		<Category title="游戏">
			<template scope="atguigu">
				<ul>
					<li v-for="(g,index) in atguigu.games" :key="index">{{g}}</li>
				</ul>
			</template>
		</Category>

		<Category title="游戏">
			<template scope="{games}">
				<ol>
					<li  v-for="(g,index) in games" :key="index">{{g}}</li>
				</ol>
			</template>
		</Category>

		<Category title="游戏">
			<template slot-scope="{games}">
				<h4 v-for="(g,index) in games" :key="index">{{g}}</h4>
			</template>
		</Category>

	</div>

八、vuex

[什么是Vuex?](https://vuex.vuejs.org/zh/#%E4%BB%80%E4%B9%88%E6%98%AF-%E7%8A%B6%E6%80%81%E7%AE%A1%E7%90%86%E6%A8%A1%E5%BC%8F)

Vuex状态流转
1、安装Vuex

安装命令如下:
npm install vuex --save
js中使用如下:
import Vue from ‘vue’
import Vuex from ‘vuex’
Vue.use(Vuex)

2.使用Vuex规范

state: 主要负责定义数据
action: 主要负责业务的逻辑处理,尽量不要直接对state处理,方法名尽量小写。接受参数(context,value)
mutations: 主要修改state中的值,不负责处理业务逻辑,方法名尽量大写。接受参数(state,value)
getters: 主要用于将state中的数据进行加工,与computed属性相似。接受参数(state)
.
流程如下:
组件中通过dispatch提交于action ——> action 中通过context.commit()提交 mutation ——> mutation 中对state进行修改 ——> Vue重新渲染组件

3.简单Vuex使用Demo

store定义如下:

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
//应用Vuex插件
Vue.use(Vuex)

//准备actions——用于响应组件中的动作
const 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——用于操作数据(state)
const mutations = {
	JIA(state,value){
		console.log('mutations中的JIA被调用了')
		state.sum += value
	},
	JIAN(state,value){
		console.log('mutations中的JIAN被调用了')
		state.sum -= value
	}
}
//准备state——用于存储数据
const state = {
	sum:0 //当前的和
}

//准备getters——用于将state中的数据进行加工
const getters = {
	bigSum(state){
		return state.sum*10
	}
}

//创建并暴露store
export default new Vuex.Store({
	actions,
	mutations,
	state,
	getters 
})

使用demo如下:

<template>
	<div>
		<h1>当前求和为:{{$store.state.sum}}</h1>
		<h3>当前求和放大10倍为:{{$store.getters.bigSum}}</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">+</button>
		<button @click="decrement">-</button>
		<button @click="incrementOdd">当前求和为奇数再加</button>
		<button @click="incrementWait">等一等再加</button>
	</div>
</template>

<script>
	export default {
		name:'Count',
		data() {
			return {
				n:1, //用户选择的数字
			}
		},
		methods: {
			increment(){
				// commit 用于提交 mutations
				this.$store.commit('JIA',this.n)
			},
			decrement(){
				this.$store.commit('JIAN',this.n)
			},
			incrementOdd(){
			 	// dispatch 用于提交 actions
				this.$store.dispatch('jiaOdd',this.n)
			},
			incrementWait(){
				this.$store.dispatch('jiaWait',this.n)
			},
		},
		mounted() {
			console.log('Count',this)
		},
	}
</script>
4.mapState,mapGetters,mapMutations,mapActions

基于上面的store,使用如下:

<template>
	<div>
		<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',
		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: {
			//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
			...mapMutations({increment:'JIA',decrement:'JIAN'}),

			//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(数组写法)
			// ...mapMutations(['JIA','JIAN']),

			/* ************************************************* */
			//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
			...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
			//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(数组写法)
			// ...mapActions(['jiaOdd','jiaWait'])
		},
	}
</script>
5.Vuex模块化编码

前提:store下存在count.jsperson.js两个文件。模块化编码namespaced:true必须编写

//该文件用于创建Vuex中最为核心的store
import Vue from 'vue'
//引入Vuex
import Vuex from 'vuex'
import countOptions from './count'		// count.js
import personOptions from './person'	// person.js
//应用Vuex插件
Vue.use(Vuex)

//创建并暴露store
export default new Vuex.Store({
	modules:{
		countAbout:countOptions,
		personAbout:personOptions
	}
})

方式一、使用 …map 的方式

代码如下:

<template>
	<div>
		<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',
		computed:{
			//借助mapState生成计算属性,从state中读取数据。(数组写法)
			...mapState('countAbout',['sum','school','subject']),
			...mapState('personAbout',['personList']),
			//借助mapGetters生成计算属性,从getters中读取数据。(数组写法)
			...mapGetters('countAbout',['bigSum'])
		},
		methods: {
			//借助mapMutations生成对应的方法,方法中会调用commit去联系mutations(对象写法)
			...mapMutations('countAbout',{increment:'JIA',decrement:'JIAN'}),
			//借助mapActions生成对应的方法,方法中会调用dispatch去联系actions(对象写法)
			...mapActions('countAbout',{incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
		}
	}
</script>

方式二、通过 $store 使用

使用如下:

<template>
	<div>
		<button @click="add">添加</button>
		<button @click="addWang">添加一个姓王的人</button>
		<button @click="addPersonServer">添加一个人,名字随机</button>
	</div>
</template>

<script>
	import {nanoid} from 'nanoid'
	export default {
		name:'Person',
		computed:{
			personList(){
				return this.$store.state.personAbout.personList
			},
			sum(){
				return this.$store.state.countAbout.sum
			},
			firstPersonName(){
				return this.$store.getters['personAbout/firstPersonName']
			}
		},
		methods: {
			add(){
				const personObj = {id:nanoid(),name:this.name}
				this.$store.commit('personAbout/ADD_PERSON',personObj)
			},
			addWang(){
				const personObj = {id:nanoid(),name:this.name}
				this.$store.dispatch('personAbout/addPersonWang',personObj)
			},
			addPersonServer(){
				this.$store.dispatch('personAbout/addPersonServer')
			}
		},
	}
</script>

九、Vue-Router

[Vue-Router官网](https://router.vuejs.org/zh/guide/essentials/dynamic-matching.html#%E5%93%8D%E5%BA%94%E8%B7%AF%E7%94%B1%E5%8F%82%E6%95%B0%E7%9A%84%E5%8F%98%E5%8C%96)

格式如下:

// 该文件专门用于创建整个应用的路由器
import VueRouter from 'vue-router'
//引入组件
import About from '../pages/About'
import Home from '../pages/Home'
import News from '../pages/News'
import Message from '../pages/Message'
import Detail from '../pages/Detail'

//创建并暴露一个路由器
export default new VueRouter({
	routes:[
		{
			name:'guanyu',
			path:'/about',
			component:About
		},
		{
			path:'/home',
			component:Home,
			children:[
				{
					path:'news',
					component:News,
				},
				{
					path:'message',
					component:Message,
					children:[
						{
							name:'xiangqing',
							path:'detail/:id/:title',
							component:Detail,
						}
					]
				}
			]
		}
	]
})

1.query参数

标签使用格式如下:

<!--字符串模板方法-->
<router-link :to="`/home/message/detail?id=${m.id}&title=${m.title}`">{{m.title</router-link>
<!--to的对象写法-->
<router-link :to="{
					name:'xiangqing'			// 指定的路由name,就不必写path那么长了
					// path:'/home/message/detail',
					query:{
						id:1,
						title:"你好"
					}
				}">

获取query参数,格式如下:

<li>消息编号:{{$route.query.id}}</li>
<li>消息标题:{{$route.query.title}}</li>

2.params参数

标签使用格式如下:
注坑:使用params时使用name属性,不要使用path属性,否则找不到页面

<!-- 跳转路由并携带params参数,to的字符串写法 -->
 <router-link :to="`/home/message/detail/${m.id}/${m.title}`">{{m.title}}</router-link>

<!-- 跳转路由并携带params参数,to的对象写法 -->
<router-link :to="{
		name:'xiangqing',
		params:{
				id:m.id,
				title:m.title
				}
		}">
				</router-link>

获取params参数,格式如下:

<li>消息编号:{{$route.params.id}}</li>
<li>消息标题:{{$route.params.title}}</li>

3.路由的props配置

router.js中写法如下:

	{
					path:'message',
					component:Message,
					children:[
						{
							name:'xiangqing',
							path:'detail',
							component:Detail,

							//props的第一种写法,值为对象,该对象中的所有key-value都会以props的形式传给Detail组件。
							// props:{a:1,b:'hello'}

							//props的第二种写法,值为布尔值,若布尔值为真,就会把该路由组件收到的所有params参数,以props的形式传给Detail组件。
							// props:true

							//props的第三种写法,值为函数
							// props({query:{id,title}})
							props($route){
								return {
									id:$route.query.id,
									title:$route.query.title,
									a:1,
									b:'hello'
								}
							}
						}
					]

组件中写法如下:

<template>
	<ul>
		<li>消息编号:{{id}}</li>
		<li>消息标题:{{title}}</li>
	</ul>
</template>

<script>
	export default {
		name:'Detail',
		props:['id','title'],
	}
</script>

4.编程式路由导航
1.query方式

this.$router.push({
		name:'xiangqing',
		query:{
			id:m.id,
			title:m.title
			}
})

2.replace方式

this.$router.replace({
		name:'xiangqing',
		query:{
			id:m.id,
			title:m.title
			}
})

3.params方式

this.$router.push({
		name:'xiangqing',
		params:{
			id:m.id,
			title:m.title
			}
})

4.后退前进

	this.$router.back()	// 后退
	this.$router.forward() // 前进
	this.$router.go(3) // 前进3步
	this.$router.go(-3) // 后退3步

5.缓存路由组件

<!-- 缓存一个路由组件News,该路由下的其他组件不缓存 -->
	<keep-alive include="News">
		<router-view></router-view>
	</keep-alive>

…未完待续

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值