Vue组件之间通信,ref属性,动态组件,插槽,计算/监听属性

组件

  1. 组件有自己的html,css,js,数据,事件。

  2. 在组件中,this指当前组件。

  3. 父子组件的data是无法共享的

  4. 全局组件与局部组件的data()是个函数必须要返回值

一,组件间通信之父传子

子组件接收父组件需要在 子组件的props=[]注册

我们知道组件间的数据是不共享的,我们需要进行数据传递。

如何把父标签的变量给子标签使用,使用自定义属性的方式。

注意事项

"""
自定义属性名不能使用驼峰定义
不要和子组件的变量名冲突
"""
代码

<div id="app">
<child :myage="age"><child> # 就可以把根组件的变量age=19传给子组件。 赋值
<child myage="age"><child>  # 这样就是把字符串age传过去了
<child :myage="19"><child>  # 这是数字 
<child myage="19"><child>   # 这是字符串
</div>  
    
# 子(局部)组件
var child={
    template:`<div>
    <p>我是子组件的{{name}}</p>
    <p>我是父组件传过来的{{myage}}</p>
    </div>`,
    data(){
        return{
            name:'lxj',
        },
    },
    props:['myage'],  # 使用 props接收
}
# 根(父)组件
var vm = new Vue({
    el:'#app',
    data:{
        age:18
    },
    methods{},
    components:{
            child }  # 注册子组件
})

还可以通过属性验证限制传入的数据类型

# 子标签内
var child={
    template:`<div> 
    <p>我是子组件的{{name}}</p>
    <p>我是父组件传过来的{{myage}}</p>
    </div>`,
    data(){
        return{
            name:'lxj',
        },
    },
    props:[myage:Number,name:String],  # 使用 props接收并指定数据类型
}
"不按数据照类型传会报错但是页面会正常显示会在控制台中提示报错"

二,组件间通信之子传父

通过自定义事件子传父

在子组件内this.$emit('自定义事件名',需要传的参数)触发父组件定义的自定义事件。

<div id="app">
<p>子组件传过来的数据 {{mytext}}</p>
<hr>
<!--注意这个自定义事件是写在父组件中(handleEvent事件需要写在父组件中),因为这个页面是父组件的-->
<child @myevent="handleEvent"></child>
<hr>
</div>


# 子(局部)组件
var child={
    template:`<div>
    <input type='text' v-model="mutext">
    <!--子组件触发点击事件 -->
    <button @click="click">点我传递</button>
    </div>`,
    data(){
        return{
            mytext:'',
        },
    },
   methods:{
       click(){
          //在子组件的点击事件内 ,触发父组件的自定义事件
           this.$emit('myevent',this.mytext)
       }
   }
}
# 根(父)组件
var vm = new Vue({
    el:'#app',
    data:{
        mytext:'',
    },
    methods{
        // 传几个参数接收几个
        handleEvent(mytext){
            this.mytext = mytext
        },
    },
    components:{
            child }  # 指定子组件
})

三,ref属性

自定义属性与自定义事件可以使实现父子相互传值

Vue提供了更方便的方法实现父子通信

ref

1.放在普通标签上
<div id='app'>
<button @click="click">点我</button>
<input type="text" ref="myinput">
<div ref="mydiv">我是div</div> 
</div>


var vm = new Vue({
    el:'#app',
    data:{
        mytext:'',
    },
    methods{    
        click(){
          // 1 
         //通过this.refs 可以拿到所有携带ref属性的标签,是一个对象类型K值是属性名,value是标签对象
           // 可以修改input框的value值
          this.$refs.myinput.value = 'lxj'
          
          
        },
    },
    components:{
            child }  # 注册子组件
})
2.放在组件上 用的多
<div id='app'>
<button @click="click">点我</button> ---父的{{age}}

<br>
<child ref="mychild"></child>
<br>
</div>


# 子(局部)组件
var child={
    template:`<div>
		<h1>name--{{name}}||age--{{age}}</h1>
    <button @click='click'>点我弹出名字</button>
    </div>`,
    data(){
        return{
            name:'lxj',
            age:18,
        },
    },
   methods:{
       click(){
           alert('我是子组件点击事件')
       }
   }
}


var vm = new Vue({
    el:'#app',
    data:{
        age:999,
    },
    methods{    
        click(){
           // ref放在子组件上 就可以拿到子组件对象的属性和方法
          //  this.refs.mychild就是组件对象,可以点属性点方法
          // 把子标签的age赋值给父标签,反过来就是父传子
         this.age=this.refs.mychild.age
          // 还可以点子组件的方法,这样我点击父组件的点击事件也能触发到子标签的点击事件
            this.$refs.mychild.click
          
          
        },
    },
    components:{
            child }  # 注册子组件
})

四,动态组件

不使用动态组件展示点击标签切换到对应的页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <span @click="click('home')">首页</span>| <span @click="click('order')">订单</span>| <span @click="click('goods')">商品</span>
    <!--通过给点击事件传参数 修改变量在通过if判断来判断是哪个页面就展示哪个-->
    <home v-if="chooseType=='home'"></home>
    <order v-else-if="chooseType=='order'"></order>
    <goods v-else></goods>
</div>
</body>
<script>
    var home = {
        template: `
        <div>
        <h1>home页面</h1>
        </div>       `
                    }
    var order = {
        template:`
        <div>
        <h1>order页面</h1>
            </div>`
                }
    var goods = {
        template: `
                <div>
                <h1>goods页面</h1>
                </div>`
    }


    var vm = new Vue({
        el:'#app',
        data:{
            chooseType:'home'
        },
        methods:{
            click(type){
                console.log(type)
                // 通过点击事件把当前的想要展示页面的关键字传过来修改变量
                this.chooseType = type
            }
        },
        components:{
            home,order,goods
        }
    })
</script>
</html>
1,动态组件 component标签

与上面的区别在于不需要使用if进行判断

缺点在于我们在某一个标签里输入的操作并不会随着我们切换页面保留下次回来还有。 只要切换页面那个页面就被销毁了
<div id="app">
    <span @click="click('home')">首页</span>| <span @click="click('order')">订单</span>| <span @click="click('goods')">商品</span>
    <!--component 需要动态使用 :is=绑定变量 is判断是哪个组件就是用哪个组件 -->
        <component :is="who"></component> # 这里
</div>

而内部的变量修改成who就行了,其实变量名随便,还用上边那个也行。不过要改的话点击事件与变量都要改
 <component :is="chooseType"></component> 

2,动态组件 keep-alive

保持组件在切换组件时 不被销毁。

keep-alive 标签包裹

<div id="app">
    <span @click="click('home')">首页</span>| <span @click="click('order')">订单</span>| <span @click="click('goods')">商品</span>
    <!--keep-alive切换组件时原组件不会被销毁 -->
    <keep-alive>
        <component :is="who"></component>
        </keep-alive>
</div>

五,插槽

通常情况下我们编写完一个组件后如果想要添加组件的数据,只能到组件里去改,扩展性太差。

插槽 就是为了改善上面的情况。

只需要在组件中添加<slot></slot> 预留就可以在组件页面中添加内容。

使用方法

匿名插槽
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <hr>
    <home>
        // 这个div就会被替换到slot标签
        <div>
            <img src="https://img1.baidu.com/it/u=273892741,1142580910&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500" alt="">
        </div>
    </home>
</div>
</body>
<script>
     var home = {
        template: `
        <div>
        <h1>home页面</h1>
        <slot></slot>
        </div>       `
                    }
      var vm = new Vue({
        el:'#app',
        data:{},
        components:{
            home
        }})
</script>
</html>
具名插槽
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <hr>
    <home>
        <div slot="a">
            <img src="https://img1.baidu.com/it/u=273892741,1142580910&fm=253&fmt=auto&app=138&f=JPEG?w=800&h=500" alt="">
        </div>
        <div slot="b"><p>我是来替换b slot的</p></div>
    </home>
</div>
</body>
<script>
     var home = {
        template: `
        <div>
        <h1>home页面</h1>
        <slot name="a"></slot>
        <h2>b slot的替换</h2>
        <slot name="b"></slot>
        </div>       `
                    }
      var vm = new Vue({
        el:'#app',
        data:{},
        components:{
            home
        }})
</script>
</html>

六,计算属性 computed

slice(开始索引,结束索引可不填) 按索引位切分

toUpperCase转大写

image

可以发现没有使用计算属性的时候只要数据有变化那么就会触发函数

使用计算属性computed 来写方法,可以延缓计算,跟他关联的变量在有变化时才会重新计算。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">
    <input type="text" v-model="mytext">----->{{newtext}}

    <br>
    <input type="text" v-model="age">----》{{age}}
</div>
</body>
<script>

    var vm = new Vue({
        el: '#app',
        data: {
            mytext: '',
            age:1,
        },
        computed:{
            newtext(){
                console.log('计算了')
                return this.mytext.slice(0, 1).toUpperCase() +  this.mytext.slice(1)
            },
        }

    })
</script>
</html>

image

用计算属性优化过滤案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>

    <script src="js/vue.js"></script>
</head>
<body>
<div id="app">

    <h2>过滤案例</h2>
    <p><input type="text" v-model="myText" >搜索</p>
        <ul>
        <li v-for="item in newDataList">{{item}}</li>
        </ul>
</div>
</body>

<script>
    var vm = new Vue({
        el: '#app',
        data: {
            myText:'',
            datalist:['今天', '今天去打鱼', '今天去看海', '鱼叉在哪买?', '怎么在海边抓鱼', '在海边烤鱼'],


        },
        methods: {  },
        computed: {
            // 每次 mytext 发生变化都会重新计算,所以每次计算都是一个原始datalist
            newDataList() {
                return this.datalist.filter(item => item.indexOf(this.myText) >= 0)
            }
        }
    })

</script>
</html>

七,监听属性watch

在data中定义变量,变量只要发生变化就执行一个函数

排序案例

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
    <script src="js/vue.js"></script>
</head>
<body>
 <div id="app">
     <span @click="course_type='1'">python</span>  |   <span @click="course_type='2'">Linux</span>
    <div>很多课程点击上面的标签完成过滤</div>
 </div>
</body>
<script>
    var vm = new Vue({
        el:'#app',
        data:{
            course_type:'0',
        },
        created(){
            // 产生实例时调用函数
             this.getData()
        },
        methods:{
            getData(){
                // 发送ajax 获取所有课程
                // 通过course_type 的值过滤
            }
        },
        // 监听
        watch:{
            // 这个属性只要发生变化就会调用函数
            course_type(){
                console.log('动了')
                this.getData()
            }
        }
    })
</script>
</html>

八,node环境搭建

  1. Vue-CLI 又称vue脚手架,可以创建Vue项目

  2. vue脚手架必须安装nodejs(一门后端语言)

  3. 一帮大神基于谷歌的v8引擎(js解释器就是浏览器的检查) 使它能够运行在操作系统上加了一些功能文件操作,网络操作,数据库操作组合成了nodejs

下载地址

http://nodejs.cn/

安装修改路径,一直下一步

直接打开cmd操作

node 进入解释器环境
npm  像pip一样的安装包的工具
npm install 装模块
posted @ 2023-02-17 14:45  李阿鸡  阅读(115)  评论(0编辑  收藏  举报
Title