组件传值 混入 订阅与发布

组件传值 混入 订阅与发布

1. props

用于父组件给子组件传递数据

父组件

<template>
 <div>
     //必须写引号 加冒号才能传数字
  <Student name="李四" sex="女" :age="18"/>
 </div>
</template>

<script>
 import Student from './components/Student'

 export default {
  name:'App',
  components:{Student}
 }
</script>

子组件

<template>
	<div>
		<h1></h1>
		<h2>学生姓名:</h2>
		<h2>学生性别:</h2>
		<h2>学生年龄:</h2>
		<button @click="updateAge">尝试修改收到的年龄</button>
	</div>
</template>

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

		//接收的同时对数据进行类型限制
		/* 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.mixin

混合,提取多个组件共有的提取到一起,分成局部混入和全局混入

局部混入

<template>
	<div>
		<h2 @click="showName">学校名称:</h2>
		<h2>学校地址:</h2>
	</div>
</template>

<script>
	//引入一个hunhe
	import {hunhe,hunhe2} from '../mixin'

	export default {
		name:'School',
		data() {
			return {
				name:'尚硅谷',
				address:'北京',
				x:666 //覆盖了100
			}
		},
		mixins:[hunhe,hunhe2],
	}
</script>

mixin.js

export const hunhe = {
   methods: {
      showName(){
         alert(this.name)
      }
   },
   mounted() {
      console.log('你好啊!')
   },
}
export const hunhe2 = {
   data() {
      return {
         x:100,
         y:200
      }
   },
}

全局混入

在main.js写入 则所有的vc都有该混入

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
import {hunhe,hunhe2} from './mixin'
//关闭Vue的生产提示
Vue.config.productionTip = false

Vue.mixin(hunhe)
Vue.mixin(hunhe2)


//创建vm
new Vue({
	el:'#app',
	render: h => h(App)
})

3.插件

main.js引入插件

//引入Vue
import Vue from 'vue'
//引入App
import App from './App.vue'
//引入插件
import plugins from './plugins'
//关闭Vue的生产提示
Vue.config.productionTip = false

//应用(使用)插件
Vue.use(plugins,1,2,3)
//创建vm
new Vue({
	el:'#app',
	render: h => h(App)
})

plugin.js

export default {
    //传入的其实是vue的构造函数,就是传给插件一个根对象,x,y,z对应上面的1,2,3
   install(Vue,x,y,z){
      console.log(x,y,z)
      //全局过滤器
      Vue.filter('mySlice',function(value){
         return value.slice(0,4)
      })

      //定义全局指令
      Vue.directive('fbind',{
         //指令与元素成功绑定时(一上来)
         bind(element,binding){
            element.value = binding.value
         },
         //指令所在元素被插入页面时
         inserted(element,binding){
            element.focus()
         },
         //指令所在的模板被重新解析时
         update(element,binding){
            element.value = binding.value
         }
      })

      //定义混入
      Vue.mixin({
          //直接可以在组件中使用如插值语法访问
         data() {
            return {
               x:100,
               y:200
            }
         },
      })

      //给Vue原型上添加一个方法(vm和vc就都能用了)
      Vue.prototype.hello = ()=>{alert('你好啊')}
   }
}

使用该自定义插件

<template>
 <div>
     <!-- 过滤器 -->
  <h2>学校名称:</h2>
  <h2>学校地址:</h2>
  <button @click="test">点我测试一个hello方法</button>
     
    <h2>学校名:</h2>
	<input type="text" v-fbind:value="name">
 </div>
</template>

<script>
 export default {
  name:'School',
  data() {
   return {
    name:'尚硅谷atguigu',
    address:'北京',
   }
  },
  methods: {
   test(){
    this.hello()
   }
  },
 }
</script>

4.scoped

设置样式在当前组件使用

<style scoped>
 .demo{
  background-color: skyblue;
 }
</style>

5.浏览器本地存储

localStorage

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <title>localStorage</title>
   </head>
   <body>
      <h2>localStorage</h2>
      <button onclick="saveData()">点我保存一个数据</button>
      <button onclick="readData()">点我读取一个数据</button>
      <button onclick="deleteData()">点我删除一个数据</button>
      <button onclick="deleteAllData()">点我清空一个数据</button>

      <script type="text/javascript" >
         let p = {name:'张三',age:18}
		//存储键值对
         function saveData(){
            localStorage.setItem('msg','hello!!!')
            localStorage.setItem('msg2',666)
             //对象形式的
            localStorage.setItem('person',JSON.stringify(p))
         }
         function readData(){
            console.log(localStorage.getItem('msg'))
            console.log(localStorage.getItem('msg2'))

            const result = localStorage.getItem('person')
            console.log(JSON.parse(result))

            // console.log(localStorage.getItem('msg3'))
         }
         function deleteData(){
            localStorage.removeItem('msg2')
         }
         function deleteAllData(){
            localStorage.clear()
         }
      </script>
   </body>
</html>

sessionStorage

<!DOCTYPE html>
<html>
   <head>
      <meta charset="UTF-8" />
      <title>sessionStorage</title>
   </head>
   <body>
      <h2>sessionStorage</h2>
      <button onclick="saveData()">点我保存一个数据</button>
      <button onclick="readData()">点我读取一个数据</button>
      <button onclick="deleteData()">点我删除一个数据</button>
      <button onclick="deleteAllData()">点我清空一个数据</button>

      <script type="text/javascript" >
         let p = {name:'张三',age:18}

         function saveData(){
            sessionStorage.setItem('msg','hello!!!')
            sessionStorage.setItem('msg2',666)
            sessionStorage.setItem('person',JSON.stringify(p))
         }
         function readData(){
            console.log(sessionStorage.getItem('msg'))
            console.log(sessionStorage.getItem('msg2'))

            const result = sessionStorage.getItem('person')
            console.log(JSON.parse(result))

            // console.log(sessionStorage.getItem('msg3'))
         }
         function deleteData(){
            sessionStorage.removeItem('msg2')
         }
         function deleteAllData(){
            sessionStorage.clear()
         }
      </script>
   </body>
</html>

6.组件自定义事件

通过父组件给子组件传递函数类型的props实现:子给父传递数据

父组件

<template>
  <div id="App">
<!--    通过props让子组件给父组件传值-->
    <School :SendMsgToApp="getMsg"></School>
    <button></button>
  </div>
</template>

<script>
import School from "./src/School";
export default {
  name: "App",
  components: {School},
  data(){
    return{
      getmsg:'',
    }
  },
  methods:{
    getMsg(msg){
      this.getmsg=msg;
      console.log(msg)
    },
  }

}
</script>

<style scoped>

</style>

子组件

<template>
  <div>
    <p></p>
    <button @click="SendMsg">点击获取</button>
  </div>
</template>

<script>
export default {
  name: "school",
  props:['SendMsgToApp'],
  data(){
    return{
      sendmsg:"hhaha",
    }
  },
  methods:{
    SendMsg(){
      this.SendMsgToApp(this.sendmsg)
    },
  }
}
</script>

<style scoped>

</style>

通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on)

父组件

<template>
  <div id="App">
<!--    通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一种写法,使用@或v-on)-->
    <School @test="testget"></School>
  </div>
</template>

<script>
import School from "./src/School";
export default {
  name: "App",
  components: {School},
  data(){
    return{
      getmsg:'',
    }
  },
  methods:{
    //school传来的参数
    testget(name,...params){
      console.log('App收到了学生名:',name,params)
      this.studentName = name
    }
  }

}
</script>

<style scoped>

</style>

子组件

![$emit子传父](../images/front/vue/$emit子传父.png)<template>
  <div>
    <p></p>
    <button @click="SendMsg">点击获取</button>

    <p>点击出发@test把子组件数据传给父组件</p>
    <button @click="testT">test</button>
  </div>
</template>

<script>
export default {
  name: "school",
  data(){
    return{ 
      name:'soup',
    }
  },
  methods:{
    //通过点击@click后触发该函数,获取该组件vc对象即可传递到该使用该组件自定义事件传的值
    testT(){
      this.$emit("test",this.name,666,888,900)
    }

  }
}
</script>

<style scoped>

</style>

采用$refs的方式让子组件传递数据给父组件

7.全局事件总线

就是一个组件想要获取某个事件,自己定义一个key如hello,并且设置回调函数获取值,

this.$bus.$on('hello',(data)=>{
 console.log('我是School组件,收到了数据',data)
})

其它组件可以通过this.$bus.$emit('hello',this.name)

8.消息订阅与发布

也是实现任意组件通信 使用pubsub-js

  1. 引入 npm i pubsub-js

  2. 在消息接收者和发布者组件引入 import pubsub from “pubsub-js”

  3. 消息接收者写接收消息

  mounted(){
      //右边是回调函数,第一个参数是消息名,第二个是回传数据
      pubsub.subscribe('hello',(msgName,data)=>{
      console.log(this)
      console.log('有人发布了hello消息,hello消息的回调执行了',msgName,data)
  })
  }
  1. 发送者发布消息
  methods: {
   //<button @click="sendStudentName">把学生名给School组件</button>
   sendStudentName(){
    pubsub.publish('hello',666)
   }
  },
  1. 最好在接收消息的组件销毁前取消订阅
  beforeDestroy() {
      //this.pubId = pubsub.subscribe
  	pubsub.unsubscribe(this.pubId)
  },

9.集成第三方动画库

10.解决axios跨域

前端端口8080要访问后端端口9550,会产生跨域问题,可以采用代理服务器(该服务器端口和前端一致)

采用cors跨域,后端配置添加跨域响应头即可

package com.anjiplus.template.gaea.business.filter;

import org.springframework.core.Ordered;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import javax.servlet.*;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by raodeming on 2021/6/24.
 */
/**
@Author soup
@Date 2022/11/15
@Description 设置跨域所有请求都会经过它
*/
@Component
@Order(Ordered.HIGHEST_PRECEDENCE) //代表这个过滤器在众多过滤器中级别最高,也就是过滤的时候最先执行
public class CorsFilter implements Filter {

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
            throws IOException, ServletException {
        HttpServletRequest req = (HttpServletRequest) request;
        HttpServletResponse res = (HttpServletResponse) response;
        //允许跨域携带cookie(跨域请求要携带cookie必须设置为true)
        res.addHeader("Access-Control-Allow-Credentials", "true");
        // 允许http://www.xxx.com域(自行设置,这里只做示例)发起跨域请求
        res.addHeader("Access-Control-Allow-Origin", req.getHeader("Origin"));
        // 设置允许跨域请求的方法
        res.addHeader("Access-Control-Allow-Methods", "*");
        // 允许跨域请求包含content-type
        res.addHeader("Access-Control-Allow-Headers", "*");
        res.addHeader("Access-Control-Expose-Headers", "*");
        //放行
        chain.doFilter(req, res);
    }

    @Override
    public void destroy() {
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {
    }
}

采用代理服务器如nginx

或者采用vue-cli 在vue.config.js文件下

module.exports = {
  pages: {
    index: {
      //入口
      entry: '17_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值
      }
    }
  }
}

打赏一个呗

取消

感谢您的支持,我会继续努力的!

扫码支持
扫码支持
扫码打赏,你说多少就多少

打开支付宝扫一扫,即可进行扫码打赏哦