vue

本文详细介绍了Vue.js中的核心概念,包括MVVM架构、单页面应用(SPA)、计算属性与监听器的区别、插槽的使用以及路由管理。MVVM模式简化了数据与视图的交互,SPA提供了流畅的用户体验,计算属性与监听器用于响应数据变化,插槽用于组件内容的定制,路由则实现了页面间的导航。同时,文章还讨论了Vue组件间的数据传递和不同路由模式的应用。
摘要由CSDN通过智能技术生成

MVVM思想

M: 即Model 模型,包括数据和一些基本的操作
V: 即View视图,页面的结构,页面渲染
VM:即View-Model,模型与视图层的数据交换,即数据与页面间的双向操作

在MVVM中VM要做的就是,只要我们的Model中的数据发生了改变,View中就会显示改变后的数据,当修改了View的时候,Model中的数据也会发生改变,不在需要自己通过获取DOM元素来进行复杂的操作

封装组件 SPA

SPA单页面是只有一个主页面的应用,一开始就加载页面所需要的html css js ,所有的内容都包含在这个主页面中,但是在写的时候还是会写许多的模板,然后通过路由的方式动态载入,进行页面的跳转
优点:用户的体验好,在用户点击切换页面的时候速度快,减轻服务器的压力,
缺点:初次加载耗时多,页面不能前进后退,因为web应用在一个页面中显示所有的内容,所以不能使用浏览器的请进和后退
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>SPA页面</title>
    <script src="../js/vue.js"></script>
    <script src="../js/vue-router.js"></script>
</head>
<body>
    <div id="app">
        <router-link to="/login">登录</router-link>
        <router-link to="/register">注册</router-link>
        <router-view></router-view>
    </div>
    <script>
        var Login = {
            template:'<h1>这是登录组件</h1>'
        }
        var Register = {
            template:'<h1>这是注册组件</h1>'
        }
        var home = {
            template:'<h1>SPA首页</h1>'
        }
        var router = new VueRouter({
            routes: [
                // 从首页重定向到登录页
                // {path:'/',component:home,redirect:{path:'/login',component:Login}},
                {path:'/',component:home},
                {path:'/login',component:Login },
                {path:'/register',component:Register},
            ]
        })
        var vm = new Vue({
            el:'#app',
            router
        })
    </script>
</body>
</html>

computed和watch区别

计算属性computed:

computed会对data对象中的数据做计算处理,并且它会把计算结果进行缓存,在页面刷新的时候不会重新进行计算,只有当data对象中的数据发生变化的时候才会重新计算,计算属性中虽然以方法的形式进行定义,但是在使用的时候会以属性的方式使用

<body>
    <div id="app">
       <h1>{{get}}</h1>
    </div>
    <script>
        var vm = new Vue({
            el:'#app',
            data:{
                msg1 :'first',
                msg2:'last'
            },
            computed:{
                get(){
                    return this.msg1 +'-'+ this.msg2 ;
                }
            }
        })
    </script>
</body>
watch监听

watch是监听某个值的变化,然后去执行相对应的函数,如果需要在某个值发生变化的时候做什么事情,这时候使用watch来监听这个数据的变化。

watch中的函数名称必须要和data中的属性名保持一致,因为watch是监听data中的属性,当data中的属性发生变化时,想对应的函数才会执行

watch中的函数有两个参数,第一个是新传的值(newvalue),第二个为之前的旧值(oldval)

<body>
    <div id="app">
       <h1>{{msg1}}</h1>
       <h1>{{msg2}}</h1>
       <h1>{{msg3}}</h1>
    </div>
    <script>
        var vm = new Vue({
            el:'#app',
            data:{
                msg1 :'first',
                msg2:'last',
                msg3:"fff"
            },
            watch:{
                msg1:function(newval,oldval){
                    this.msg2 = oldval + this.msg3 ;
                },
                msg2:function(newval,oldvalue){
                    this.msg3 = newval + this.msg1 ;
                }
            }
        })
    </script>
</body>
测试结果:
hh
firstfff
firstfffhh
测试方法:在控制台测试
vm.msg1='hh'
"hh"
区别:computed是在多条数据发生变化的时候使用computed来进行计算(一个属性受多个属性的影响 常用于购物车总价的计算),watch是监听data中的某一条数据的变化的(一条数据的变化影响多条数据 常用于搜索框)

vue中的插槽的理解

插槽用来定义,插槽就是在定义子组件的时候起到了一个占位的作用,当父组件在用这个子组件的时候,想要在里面添加自己的html或者组件时,添加的内容就会添加到定义的标签里面进行替换

插槽分为匿名插槽,具名插槽,和作用域插槽

具名插槽和匿名插槽
<body>
    <div id="app">
       <com>
           <ul slot='ul'>
               <li v-for="(item , index) in list" :key='index'>{{item}}</li>
           </ul>
           <!-- 此时的span标签不被执行,缺少名字 -->
           <span>hhh</span>
           <span slot="span">这是具名插槽</span>
        </com>
    </div>
    <script>
        var vm = new Vue({
            el:'#app',
            data:{
                list:['java','javascript','jQuery']
            },
            components:{
                com:{
                    template:`
                    <div>
                        <slot name="ul">插槽</slot>
                        <slot name="span">插槽</slot>
                    </div>
                    `
                }
            }
        })
    </script>
</body>
作用域插槽:在子组件的slot上面绑定数据的插槽

作用域插槽在使用的时候,在自定义组件里面要使用template包裹,template有一个属性slot-scope携带子组件传递过来的值,父组件只需要做的就是样式的变化。

          <template slot-scope='change'>
                <li>{{change.items}}</li>
            </template>
       </con>
       <con>
            <template slot-scope='change'>
                <span style="margin-left: 20px;">{{change.items}}</span>
            </template>
       </con>
    </div>
    <script>
         Vue.component('con',{
            template:`
            <div>
                <ul>
                    <slot v-for = 'item in list' :items = item>{{item}}</slot>    
                </ul>    
            </div>
            `,
            data(){
                return {
                    list:['java','c++','php','javascript','c#']
                }
            }
        })
        var vm = new Vue({
            el:'#app',
            data:{
            }
        })
    </script>
</body>

v-if和v-show的区别,适合那种情境

这两个都是用来控制元素的显示与隐藏的。

v-show是通过使用css的display:none来控制元素的显示与隐藏的。

v-if是vue通过操作虚拟DOM树来删除和创建真实的DOM树来达到元素的显示和隐藏

如果需要频繁的显示和隐藏元素选择v-show

什么是vuex,在什么场景下使用

vuex是一个为vuejs提供的状态管理模式,如果一个状态需要在多个组件中使用,就需要将这个状态集中管理到store中,方便组件之间的共享,一般管理登录状态,购物车等需要在多个页面中用的的状态

vuex的结构 
vuex使用:先引入->在Vue.use(Vuex)中挂载->在生成store对象->将store对象在全局的vue实例中注册
const store = new Vuex.Store({
  state:{},//state中存储数据,在组件中使用this.$store.state
  mutations:{},//mutations是唯一可以修改state中数据的对象,里面的每个方法都有一个回调函数,回调函数有一个形参state就是state中的数据,在组件中通过this.$store.commit('mutations中定义的方法名',参数(也可以是对象))触发mutations中的方法
  actions:{},//actions中定义异步方法来修改state的状态值,异步方法接收两个参数(context,payload)但是不能直接修改,只能通过context.commit('mutations中的方法名',参数)来修改state中的状态值   在组件中使用this.$store.dispath('actions中的方法名',参数)来触发actions中的方法
  getters:{},//getters类似于计算属性 可以针对state中的数据做一些逻辑计算,  在组件中使用this.$store.getter.方法名访问

  modules: {
    a: moduleA
  }
})
modulA = {  // vuex允许我们将store分割成多个store模块
  state: {},
  mutations: {},
  getters: {},
  actions: {},
  modules:{}
}
Vuex的工作流程:
在vue的组件中通过dispath来调用actions中的异步方法,在actions中通过commit来调用Mutations中的方法,在mutations中可以直接操作state中的数据,只要state中的数据发生改变就会立即响应到组件中
Vuex的store仓库中对象的操作方式
import Vue from 'vue'
import Vuex from 'vuex'

Vue.use(Vuex)

const moduleA = {
  state: {
    name: 'zhangsan'
  },
  mutations: {
    updateName(state, payload) {
      state.name = payload
    }
  },
  getters: {
    fullname(state) {
      return state.name + '11111'
    },
    fullname2(state, getters) {
      return getters.fullname + '2222'
    },
    fullname3(state, getters, rootState) { // rootState访问跟上state中的数据
      return getters.fullname2 + rootState.counter
    }
  },
  actions: {
    aUpdateName(context) {
      console.log(context);
      setTimeout(() => {
        context.commit('updateName', 'wangwu')
      }, 1000)
    }
  }
}

const store = new Vuex.Store({
  state: {
    counter: 1000,
    students: [
      {id: 1, name: 'zs', age: 16},
      {id: 2, name: 'ls', age: 17},
      {id: 3, name: 'ww', age: 18},
      {id: 4 name: 'zl', age: 19}
    ],
    info: {
      name: 'zhangsanfen',
      age: 20,
      height: 1.76
    }
  },
  mutations: {
    decrement(state) {
      state.counter--
    },
    incrementCount(state, payload) {
      state.counter += payload.count
    },
    addStudent(state, stu) { //stu接收组件中传递过来的对象
      state.students.push(stu)
    },
    updateInfo(state) {
      state.info.name = 'zhaosi'
    }
  },
  actions: {
    aUpdateInfo(context, payload) {
      return new Promise((resolve, reject) => {
        setTimeout(() => {
          context.commit('updateInfo');
          console.log(payload);
          resolve('1111111')
        }, 1000)
      })
    }
  },
  getters: {
    powerCounter(state) {
      return state.counter * state.counter
    },
    more20stu(state) {
      return state.students.filter(s => s.age > 20)
    },
    more20stuLength(state, getters) {
      return getters.more20stu.length
    },
    moreAgeStu(state) {
      return age => {
        return state.students.filter(s => s.age > age)
      }
    }
  },

  modules: {
    a: moduleA
  }
})

路由使用的步骤

1、下载路由模块 npm install vue-router -S

2、在router.js中引入路由 import VueRouter from ‘vue-router’

3、通过Vue.use(VueRouter)在vue全局注册使用

4、接着创建路由对象并导出 export detault touter = new VueRouter({routes:[]})

5、在main.js全局的vue实例中进行注册,然后就能在全局中通过this.$router进行操作了

常用的组件

渲染一个元组件为动态组件。绑定is来决定哪个组件被渲染

元素作为单个元素/组件的过渡效果,只会把过渡效果用到其包裹的内容上面,而不会额外渲染元素,也不会出现在可被检查的组件层级中。

元素作为多个元素/组件的过渡效果。<transition-group> 渲染一个真实的 DOM 元素。默认渲染 <span>,可以通过 tag =‘标签名’ 配置哪个元素应该被渲染。

组价包裹着的组件能够被缓存,当页面切换的时候不会持续的创建和销毁组件,它里面有三个属性

。include 值是一个字符串或者正则表达式。只有名称匹配的组件才会被缓存

。exclude 值是一个字符串或者正则表达式。任何名称匹配的组价都不会被缓存 exclude 的优先级高于 include的优先级

。max 值是数字 最多可以缓存多少组件实例

<!-- 逗号分隔字符串 -->
<keep-alive include="a,b">
  <view-router></view-router>
</keep-alive>

<!-- 正则表达式 (使用 `v-bind`) -->
<keep-alive :include="/a|b/">
  <view-router></view-router>
</keep-alive>

<!-- 数组 (使用 `v-bind`) -->
<keep-alive :include="['a', 'b']">
  <view-router></view-router>
</keep-alive>

<keep-alive :max="10">
  <view-router></view-router>
</keep-alive>
keep-alive相对应的两个生命周期钩子 activated 和deactivated

当组件在 <keep-alive> 内被切换,它的 activated(活跃的钩子) 和 deactivated(不活跃的钩子) 这两个生命周期钩子函数将会被对应执行。

vue的生命周期

生命周期就是一个组件从创建、数据初始化、挂载、更新、销毁的这么一个阶段每个周期都有相对应的钩子函数来进行处理

beforeCreate :在实例创建之后,数据和方法初始化之前进行调用,此时获取不到this. e l ( 受 控 区 域 ) 和 t h i s . el(受控区域) 和 this. el()this.data(实例中的数据)

Create:实例创建完成,此时可以操作data中的数据,但是受控区域还未绑定

beforeMount:el挂载之前,此时获取不到dom元素

mounted:此时是给vue实例对象添加$el成员,并且替换掉挂载的DOM元素

beforeUpdata:当vue发现data中的数据发生了改变,会触发对应组件的重新渲染,渲染前调用beforeUpdata,还未同步到页面

Updated:当vue发现data中的数据发生了改变,会触发对应组件的重新渲染,渲染后调用updata

beforeDestroy:在实例销毁之前调用。在这一步,实例仍然完全可用。

destroyed:在Vue 实例销毁后调用。调用后,Vue 实例指示的所有东西都会解绑定,所有的事件监听器会被移除,所有的子实例也会被销毁。

组件中的data为什么必须是一个函数

因为一个组件被创建后会被用到多个地方,如果data还是一个对象的话,就会造成在一个地方修改了data中的数据其它地方的数据也会被修改,因为这个js本身 对象没有作用域的特点造成的,如果将data定义为一个函数的话它就会有自己的作用域,相当于每个地方调用的时候都会实例化一个对象,然后各自操作各自作用域里面的属性。

vue中的组件传值实现的各种方式

父子组件之间的传值
父向子传值:
父组件通过属性绑定的方式获取父组件的值(:item = ‘message’),然后传递到子组件中的props:[‘item’]中/props:{

​ item:{type:string , detault:'默认值 '}

}

通过this.$children[0]拿到子组件中的值

使用this.$refs获取指定的组件

子向父传值:

使用this.$emit(‘事件’,参数) 传递事件给父组件,父组件监听该事件来进行传值

使用this.$parent获取父组件中的对象

非父子组件之间的传值

使用数据总线的方式,用来触发和接收事件,来起到父子组件之间的通信

Vue.prototype.bus = new Vue()

给其中一个组件中绑定事件触发一个方法,改方法中通过this.bus. e m i t ( ′ f u n ′ , 参 数 ) 的 形 式 将 数 据 传 出 , 在 接 收 数 据 的 那 个 组 件 中 使 用 t h i s . b u s . emit('fun',参数)的形式将数据传出,在接收数据的那个组件中使用this.bus. emit(fun,)使this.bus.on(‘fun’(参数)=>{})来达到传值

<body>
    <div id="app">
        <com></com>
        <con></con>
    </div>
    <script>
        Vue.prototype.bus = new Vue() ;
        Vue.component ('com',{
                template:`
                <div>
                    <button @click='getDate'>点击com组件</button>    
                </div>
                `,
                data() {
                    return {
                        msg:'com组件中的值'
                    }
                },
                methods: {
                   getDate(){
                       this.bus.$emit('fun',this.msg) ;
                   }
                },
        }) 
        Vue.component ('con',{
                template:`
                <div>
                    <h1>这是con组件----{{msgg}}</h1>  
                </div>
                `,
                data() {
                    return {
                        msgg:''
                    }
                },
                // mounted是vue中的一个钩子函数,一般在初始化页面完成后,再对dom节点进行相关操作。
                mounted() {
                       this.bus.$on('fun',(msg)=>{
                           console.log(msg)
                           this.msgg = msg ;
                       }) ;
                },
        }) 
        var vm = new Vue({
            el:'#app',
            data:{
            }
        })
    </script>
</body>

vue中有几种路由模式

vue路由中有hash和history两种路由模式,默认使用hash模式,hash模式在URL地址中会出现一个#号,而history模式的url是正常url的结构。

如果想要将hash模式转换为history模式需要在路由实例中加mode:'history’来改变

hash值是由前端路由处理,所以改变hash时不会刷新页面,也不会向服务器发送请求

history是整个地址都要加载,可以保存历史记录,方便前进和后退

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
图像识别技术在病虫害检测中的应用是一个快速发展的领域,它结合了计算机视觉和机器学习算法来自动识别和分类植物上的病虫害。以下是这一技术的一些关键步骤和组成部分: 1. **数据收集**:首先需要收集大量的植物图像数据,这些数据包括健康植物的图像以及受不同病虫害影响的植物图像。 2. **图像预处理**:对收集到的图像进行处理,以提高后续分析的准确性。这可能包括调整亮度、对比度、去噪、裁剪、缩放等。 3. **特征提取**:从图像中提取有助于识别病虫害的特征。这些特征可能包括颜色、纹理、形状、边缘等。 4. **模型训练**:使用机器学习算法(如支持向量机、随机森林、卷积神经网络等)来训练模型。训练过程中,算法会学习如何根据提取的特征来识别不同的病虫害。 5. **模型验证和测试**:在独立的测试集上验证模型的性能,以确保其准确性和泛化能力。 6. **部署和应用**:将训练好的模型部署到实际的病虫害检测系统中,可以是移动应用、网页服务或集成到智能农业设备中。 7. **实时监测**:在实际应用中,系统可以实时接收植物图像,并快速给出病虫害的检测结果。 8. **持续学习**:随着时间的推移,系统可以不断学习新的病虫害样本,以提高其识别能力。 9. **用户界面**:为了方便用户使用,通常会有一个用户友好的界面,显示检测结果,并提供进一步的指导或建议。 这项技术的优势在于它可以快速、准确地识别出病虫害,甚至在早期阶段就能发现问题,从而及时采取措施。此外,它还可以减少对化学农药的依赖,支持可持续农业发展。随着技术的不断进步,图像识别在病虫害检测中的应用将越来越广泛。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值