您的位置:首页 > Web前端 > Vue.js

前端学习----vue及其.vue文件的一些知识点及使用递归组件完成树形结构

2020-06-29 04:24 771 查看

前端学习----使用vue递归组件完成树形结构

  • 递归组件
  • 展开效果
  • 1.初步认知

    近期整理以前杂乱的代码,发现有些还有点乱,就开始梳理并尝试用Vue来代替以前纯js和css制作导航栏之类树形结构,顺便梳理一下Vue的知识

    1.1MVVM和MVC

    首先讲一下相关的两个模式,
    一是MVVM相信很多旁友都有听过,简言之就是M(Model 模型层)可以理解为一堆数据,V(view视图层)也就是我们直观即毫无关键数据的界面,VM(ViewModel 逻辑层)即解析数据用的
    二是MVC,其中的M,V跟上述一样,C(control 控制层)即MV交互的中介
    M即数据,例如我们从数据库或者文件中读取的数据,这一层不会对数据进行处理
    V即视图,通俗的讲可以说就是我们用HTML和CSS构造的界面
    C即管理,他负责让MV交互数据,例如用js代码来获取某个标签的值,又或者为某个标签赋值,这里即可理解为C层,但要注意的是并不会对数据处理

    所以,从以上看,MVVM模式也同样包含C层,但是,由于太懒散即只负责跟MV说说话,交互数据,所有其他解析工作,对数据处理,诸如我们要对数据筛选或者转换,检查等其他操作都由VM来负责,这也是MVVM和MVC的区别,VM实现一些可重复性使用的业务逻辑,

    MVVM基本含有了MVC功能分离的特点,同时具有数据绑定的功能,即在VM进行验证和解析等操作初始化或者修改数据后,最小化C层(操纵MV)的过程甚至隐藏,简言之就是V绑定了M,当VM对M进行操作时,V也会随之变动,C谦虚的完成了这个传递过程然后继续当吃瓜群众,我想这应该是MVVM里没有提到C的原因之一

    1.2VUE的一些知识点

    为啥子要废话上面那么多呢?因为,Vue的核心知识就是MVVM,我想也正因为有这一些特殊性才设置vue-cli脚手架来构建项目
    先来看看一些属性

    new Vue({
    el: //挂载目标,选择的DOM元素
    props://父组件传递过来的数据,要注意子组件不能对这个数据更改
    data: //数据
    component: //全局组件,要进行全局注册,能在页面任何位置使用
    components: //局部组件,只能在挂载位置使用
    methods: //方法,可改变数据
    computed: //属性,可以提取数据进行计算然后保存但不能改变数据
    created: //初始化
    mounted://后续操作,即整个页面完成后的操作
    router://使用的路由
    watch://监听器
    })

    再来看看.Vue文件(一般用来构造组件,当然代码也可以放在HTML文档里)

    <template>
    </template>
    <script>
    </script>
    <style >
    </style>

    再来联立MVVM模式来进行理解,M数据即上面的data里,V视图就是下面的template和style里实现的界面,然后VM就是script里created或者method等对data数据进行的解析验证计算等操作,C层细节并没有明示出来,也就是隐式的进行了数据绑定,一旦我们对data进行修改,联动下来的子元素里的data数据也会进行改变,也就是C哥在背后默默的付出,而我们不用知道

    递归组件

    在会用构建完项目后自定义组件,新建文件名为test.vue文件,先放数据

    var dtest = [{
    name: '1',
    next: [{
    name: '1-2'
    },
    {
    name: '1-3'
    },
    {
    name: '1-4'
    },
    {
    name: '1-5'
    },
    {
    name: '1-6'
    }
    ]
    }, {
    name: '2'
    }, {
    name: '3',
    next: [{
    name: '3-1'
    },
    {
    name: '3-2'
    }
    ]
    }
    ]

    以及定义的组件

    <template>
    <div>
    <ul>
    <li v-for = "(val,index) in menu" :key = " index">
    {{val.name}}
    <test :menu='val.next'></test>
    </li>
    </ul>
    </div>
    </template>
    
    <script>
    export default {
    name: 'test',
    props: ['menu', 'type']
    }
    </script>
    
    <!-- Add "scoped" attribute to limit CSS to this component only -->
    <style scoped>
    </style>

    在这里通过回调test组件来重复构建,当然可以重复嵌套实现,上下两个方法在只有两层时实现的效果是一样的

    <template>
    <div>
    <ul>
    <li v-for = "(val,index) in menu" :key = " index">
    {{val.name}}
    <div>
    <ul>
    <li v-for = "(val,index) in val.next" :key = " index">
    {{val.name}}
    <test :menu='val.next'></test>
    </li>
    </ul>
    </div>
    </li>
    </ul>
    </div>
    </template>

    当然要注意在HTML文档内调用并传数据,js里代码为

    import test from './components/test'
    Vue.component('test', test)//注册
    new Vue({
    el: '#app',
    data: {
    dtest: dtest
    },
    component: { test}
    })

    HTML里也要注意对应,并传送数据

    <div id="app">
    <test :menu='dtest'></test>//将data中的dtest传送给test中的menu
    </div>

    当然如果,数据层数不确定,例如文件目录那样的结构,那么前者自然更好
    最后的效果图

    展开效果

    现在在进一步来添加点击展开的效果,分支数量不同,单纯的一个Boolean监听状态显然不够,所以定义一个数组,来监听所有状态,并在li定义@click触发methods里的方法来改变值,
    同时要注意的是,

    **官方定义改变属性并不能改变视图**
    ,因为只有初始化对象进行双向数据绑定的时候,即修改Object.defineProperty()时添加set/get方法的时候,才会响应更新view。所以,直接修改属性并没有响应这个初始化的过程,也就不能更新,因此也提供方法this.$set方法来操作,简单代码如下:

    <template>
    <div>
    <ul>
    <li v-for = "(val,index) in menu" :key = " index" @click="changeshow(index)">
    {{val.name}}
    <test :menu='val.next' v-if="ifshow[index]"></test>
    </li>
    </ul>
    </div>
    </template>
    
    <script>
    export default {
    name: 'test',
    props: ['menu', 'type'],
    data () {
    return {
    ifshow: [false]
    }
    },
    methods: {
    changeshow (e) {
    this.$set(this.ifshow, e, !this.ifshow[e])
    }
    }
    }
    </script>
    
    <style scoped>
    </style>

    vue文件里scoped能够保证文档的CSS属性唯一,即只有在本组件中才会被响应,不怕跟外部其他的重名
    设置css之后可以实现下面非常常见的效果

    内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
    标签: