Vue自学笔记

vue介绍

vue是一个渐进式的JavaScript框架。渐进式:可插拔式、可扩展。

我们刚开始只需要使用最核心的核心库,后期可以自己去增加新库。

vue官网

vue引入

vue提供了非常详细的官方文档,我们完全可以通过官方文档来学习vue.vue官方文档

xx.vue文件组成结构:

<template>
</template>
<script>
    export default { 
    }
</script>
<style>
</style>

在chrome中安装vue开发工具

解压文件下载,或者参考网上的解决方案进行安装

该插件可以在chrome浏览器中充当vue的调试工具

mvvm简介

mvvm

html使用vue

<script type="text/javascript">
    var vm = new Vue({
        el:'',
        data:{
        },
        methods:{
        },
        computed:{
        },
        directives:{
        },
        watch:{
		},
        components:{
        },
        filters:{
        }
    })
</script>
  1. var vm = new Vue({});

    创建一个vue的实例

    当我们导入包之后在浏览器的内存中,就多了一个Vue的构造函数

    注意:我们new出来的这个vm对象就是我们mvvm中的vm调度者

  2. el

    表示,当前我们 new的这个vue实例,要控制页面上的哪一个区域

  3. data

    data属性中,存放的时el中索要用到的数据,形式是采用key:value的形式

    这里的data 就是mvvm中的m,专门用来保存页面数据的

    通过 vue提供的指令,很方便的就能把数据渲染到页面上,程序员不需要手动操作dom元素了【前端的vue之类的框架,不提倡我们区手动操作dom元素了】

    data中定义的变量是全局变量,所有vue对象都可以使用

    computed中的返回值也作为data中的一部分

  4. methods

    定义方法

  5. computed

    • 进行计算,初始时自动加载,和变量是共享的(在data中定义的变量,就不能再在computed中定义)它中方法的返回值,也作为data变量存在:方法名就是变量名,返回值就是它的值。

    • 当data数据发生改变时也会执行。

    • computed中定义的data变量(类似方法的形式)只会被计算一次,之后会加入缓存中,之后在取值时,直接从缓存中获取。

      computed:{
          ageAndName(){
              return this.name+this.age;
          }
      

      }

  6. directives

    定义局部指令

  7. watch

    进行监听,将html中的数据放到data中(mvvm中 v–>m),当数据发生变化时,触发监听

    watch:{
        name:function(value){
            this.name1= value;
        }
    }
    
  8. components

    定义组件

  9. filters

    定义过滤器

  10. 生命周期的函数

语法

插值表达式 {{}}

显示内容,只会替换自己的这个占位符,不会吧整个元素的内容清空

<h1>{{name}}2222222</h1>

name:"helloword"

输出

helloword2222222

v-clock:

能够解决插值表达式闪烁的问题

出现的原因:跟生命周期有关

vue会先加载html文件,然后加载js文件,最后进行替换(vue数据)

解决方案:先将元素隐藏,当加载完毕之后在进行显示

  1. 定义

    <style>
        [v-clock] {
            display: none;
        }
    </style>
    
  2. 使用

    <p v-cloak>{{msg}}</p>
    

使用v-clock能够解决插值表达式闪烁的问题,当网络较慢的时候{{msg}}会显示在页面中

v-text:

显示内容,但是会覆盖元素中的原本内容

<h1 v-text="name">222222</h1>

name:"helloword"

输出

helloword

v-html:

带渲染的显示,节点操作

<h1 v-html="site"></h1>

site:"<a href='https://www.baidu.com'>百度</a>",

v-bind::

给html标签的属性绑定值

他的缩写是 :

<a v-bind:href="link">百度</a>
<a :href="link">百度</a>

v-on:@

事件的绑定

<button v-on:click="sayHello">sayHello</button>
<button @click="sayHello">sayHello</button>
<button @click="sayHelloName('ssss')">sayHelloName</button>

无参函数中的()可写可不写

有参函数需要传参的时候需要加上()

v-model

可以实现 表单元素和model中的数据实现双向绑定

用户名:<input type="text" v-model="name"/>

注意:

  • 将data中的数据传到html中 插值表达式 {{}}v-text:v-html:,等方式

  • 将html中的数据传到data中:

    1. 通过监听watch

    2. 通过vue对象

      vm.$watch('name', function(value){
          this.age= value;
      })
      

vue引入css

通过class

  1. 定义css

    <style>
        .mystyle1{
            background-color: blue ;
            width: 100px;
            height: 100px;
        }
    </style>
    
  2. css绑定到data

    css1 : 'mystyle1'
    
  3. html元素使用css

    <h3 :class="mystyle1">1111111</h3>
    

注意

  1. vue的css样式引入可以与传统的css样式引入共存

    <h3 class="mystyle3" :class="css1">info:{{info}}</h3>
    
  2. :class的值 是一个对象{k1:v1,k2:v2...}如果对象中的变量值true,则生效;否则不生效

    <h3 :class="{mystyle1:istrue, mystyle3:isfalse}"  >111111</h3>
    

    istrue和isfalse在data中定义,根据他们的值来判断样式是否生效,当istrue=true;isfalse=false;时,mystyle1生效,mystyle3不生效

    值可以同时为true或false

  3. 绑定数组 []

    <h3 :class="['mystyle1', 'mystyle3']">11111</h3>
    

    同时生效

  4. vue取值有一个特点:取的值是变量,变量名是在data中定义的。

通过style

语法:

:style={样式名:样式值(<从data中获取>),x:x,...}

<h3 :style="{backgroundColor:x,color:y}">info000000:{{info}}</h3>

    x:'lightgray' ,
    y:'purple',

注意:

属性的名字不能使用xxx-yyyy(中间使用-符号),而需要使用 xxxYyyy(驼峰命名)

条件渲染

v-ifv-else

<h3 v-if="istrue">1111</h3>  
<h3 v-else>222</h3>  

isture在data中定义,当为真时显示111,为假时显示222

v-show

<h3 v-show="isture">111</h3>  
<h3 v-show="!isture">222</h3>  

注意:v-ifv-show的区别

v-show可以在源码中追踪到隐藏的元素,即隐藏的元素可以在源码中找到;

v-if无法追踪,即隐藏的元素,在源码中找不到;

循环遍历

 <!-- 遍历一个具体对象  (一个对象有很多属性:name  age  )-->
<ul>
    <li v-for="(value,name) in students[2]" :key="name" >
            {{value}} --{{name}}
        </li>
    </li>

</ul>

value:对象属性的值

name:对象的属性名

students[2]:对象数组中的一个元素(即一个对象)

遍历对象

遍历对象数组

<ul>
    <li v-for="(s,index) in students" :key="index" >
        {{index}}   -  {{s.name}} -   {{s.age}}  
    </li>
</ul>

students: [ 
    {name:'zs', age:23},
    {name:'ls', age:24}, 
    {name:'ww', age:25},
    {name:'zl', age:26},  
    {name:'sq', age:27}   
]  //对象数组

s:数组的每一个元素

index:下标

students:数组

:key:唯一值

注意:想要获取data中的数据,需要通过this.来获取

删除数组元素:splice

//删除完毕后,数组元素 会自动重新排序
this.students.splice(index,1);

从下标index起删除1个

更新数组元素:splice

this.students.splice(index,1,stu);

将下标为index的数组元素更新为stu对象

筛选

组成:查询的条件,新数组

  1. 定义查询条件(即定义data中数据)

    queryname: “ //筛选条件

  2. 具体实现方法(在computed中定义,函数名就是变量,即新数组)

    //筛选后的新数组
    queryStuentsResult(){  
        // 新数组的值
        var queryStudents ;//s
        //筛选条件
        // var queryname =  data中定义的queryname  ;
        // var student2 = data中定义的数组students ;
        var {queryname,students} = this ;//this 就是data
        //根据查询条件,筛选出新数组
        queryStudents =  students.filter(
            stu=>stu.name .indexOf(queryname ) > -1
        )  
        return queryStudents ;
    }
    
    

排序

  1. 定义升降序变量(0:升序,1:降序)

     ordered: 0
    
  2. 对queryStudents对象数组中的元素,根据age属性进行排序

    //排序
    queryStudents.sort( function(s1,s2) {
            if(ordered ==0){//升序
                return s1.age - s2.age
            }{//降序
                return s2.age -s1.age   
            }
    })
    

    升序:第一个 - 第二个

    降序:第二个 - 第一个

    别忘了return

传播行为与事件

传参当前对象

<input type="button" value="按钮1"  @click="myclick" />

<!--错误行为-->
<!-- <input type="button" value="按钮"  @click="myclick()" /> -->    

<input type="button" value="按钮2"  @click="myclick2($event)" />

传当前对象时,要么不写,要么添加($event),不能只写()这样会报错

获取对象

myclick(event){
    alert( event.target.value ) 
},
myclick2(event){
    alert(event.target.value )
},

event.target:当前对象

注意:在vue中结尾符;可写可不写(要么都写,要么都不写)

事件的传播行为(propogation)

<div :class="css1" @click='myclick3()'>
    outer
    <div :class="css2" @click='myclick4()'>
        inner
    </div>
</div>

myclick4(){
    alert('inner' )
},
myclick5(){
    alert('link...' )
},

结果:

点击:inner时,会触发outer的点击事件

阻止行为:

<div :class="css1" @click='myclick3()'>
    outer
    <div :class="css2" @click.stop='myclick4()'>
        inner
    </div>
</div>

阻止默认行为

<a href="https://www.baidu.com"  @click.prevent='myclick5()'>百度</a>

myclick5(){
    alert('link...' )
},

注意:.xxx可以嵌套着使用

键盘点击事件

keydown

按键 按下事件

<input @keydown='myclick6'>

myclick6(event){
    //event.target :当前dom对象
    //event.keyCode:按键的值 a : 65
    alert(  event.keyCode  +'--'+ event.target.value   )
},

keyup

按键弹上去事件

指定按键触发事件

<input  @keyup.13='myclick6' >

指定的按键按下抬起时才触发的事件

每一个键盘的按键都对应着一个键码值

表单输入绑定

<form  action=""  @submit.prevent="mysubmit">
    用户名:<input type="text" v-model="user.username" ><br>
    密码:<input type="password" v-model="user.password" ><br>
    性别:
    <input type="radio" value="male"  v-model="user.password">男<br>
    <input type="radio" value="female"  v-model="user.password">女<br>
    兴趣:
    <input type="checkbox" value="football"   v-model="user.hobbies">足球,
    <input type="checkbox" value="basketball"  v-model="user.hobbies">篮球,
    <input type="checkbox" value="pingpang"  v-model="user.hobbies">乒乓球,
    城市:
    <select name="" id=""  v-model="user.city">
            <option :value="c.id" v-for="c in optionalCities">
                {{c.name}}
            </option>
    </select>

    <input type="submit" value="注册">

</form>

data:{
user:{ 
    username: '' ,
    passowrd: '' ,
    sex: 'male',
    hobbies: [] ,
    city: '' //选中
},
//可选
optionalCities: ["js","bj","sh"]
},

这里只列出了部分的用法详细的用法参考官网手册(http://doc.vue-js.com/v2/guide/forms.html)

意义:如果给后台传递一个form表单的数据,不用再 一个一个的获取每个input等元素的值;而可以一次性传递一个对象

生命周期

作用

生命周期的作用:某个动作 都有一个流程,当执行到该流程的某一个阶段时,会自动触发一些函数

注意:生命周期函数与methods和el等标签同级

详细的说明参见官方文档(https://cn.vuejs.org/v2/guide/instance.html#%E7%94%9F%E5%91%BD%E5%91%A8%E6%9C%9F%E5%9B%BE%E7%A4%BA)

动画效果

显示:Enter

隐藏:Leave

三个阶段:

初始阶段:

v-enter/v-leave

过渡阶段:

v-enter-active / v-leave-active

结束阶段:

v-enter-to/v-leave-to

v- 是这些类名的前缀。使用 <name="my-transition"> 可以重置前缀,比如 v-enter 替换为 my-transition-enter

过滤器

{{ message | filterA | filterB }}

{{msg | 过滤器1 | 过滤器2 }}

moment.js

时间格式化,去官网下载js文件

引入

注册过滤器

  //过滤:注册->使用  (西方日期 ->格式)    //es6:函数默认参数值
    Vue.filter('dateFilter' , function(value, dateFormat='YYYY-MM-DD HH:mm:ss' ){
           return  moment(value).format(dateFormat) ;
    })

使用过滤器

{{ now | dateFilter('YYYY-MM-DD')}}

自定义指令

v-text-upper

v-text-lower

定义指令的名字是v-是不需要我们写的,只需要写右边的部分即可

全局指令

var vm = new Vue({})同级(与全局变量定义类似)

  1. 注册全局指令

    Vue.directive('text-upper',function(el,binding){
        el.innerHTML= binding.value.toUpperCase();
    })
    
  2. 使用

    <p v-text-upper="myVariable"></p>
    
    myVariable : "Hello World",
    

局部指令

var vm = new Vue({})中定义 (与局部变量定义类似)

  1. 注册局部指令

    //注册局部指令
    directives:{
        'text-lower' :{
            bind(el,binding){
                el.innerHTML= binding.value.toLowerCase();
            }
        }
    }
    
  2. 使用

    <p v-text-upper="myVariable"></p>
    
    myVariable : "Hello World",
    

自定义插件

详细参见官方文档

开发插件

(function(){
  const MyPlugin = {} ;
MyPlugin.install = function (Vue, options) {
    // 1. 添加全局方法或属性
    Vue.myGlobalMethod = function () {
       alert('全局方法或属性');
    }
  
    // 2. 添加全局资源
    Vue.directive('my-directive', {//v-text-upper
      bind (el, binding, vnode, oldVnode) {
        // 逻辑...
      }
    })
  
    // 3. 注入组件选项  .每次实例vue对象中调用一次
    Vue.mixin({
      created: function () {
        // 逻辑...
        alert('mixin');
      }
    })
  
    // 4. 添加实例方法(局部)
    Vue.prototype.$myMethod = function (methodOptions) {
      // 逻辑...
      alert('局部') ;
    }
  }
  //将插件 暴露给外部使用
  window.MyPlugin = MyPlugin ;

})()

使用插件

  1. 引入(js文件)

  2. 使用插件

    Vue.use(MyPlugin);
    
    //全局:static   
    //类名.静态方法()
    Vue.myGlobalMethod();
    //对象.方法()
    vm.$myMethod();
    

vue脚手架开发

vue脚手架指的是vue-cli,它是一个专门为单页面应用快速搭建繁杂的脚手架,它可以轻松的创建新的应用程序而且可用于自动生成vue和webpack的项目模板。

安装

npm install -g vue-cli

下载模板

vue init webpack my_vue_cli

需要配置一些基本信息,不配置的话就一路回车

注意: 根据提示 安装附加组件,安装时输入项目名时不能包含大写字母。安装时,不要随意点鼠标,点击鼠标右键可以恢复。

根据提示

cd my_vue_cli
npm run dev

打包运行项目

  1. 生成dist目录

    npm run build
    
  2. 安装服务组件(静态服务)

    npm install -g serve

  3. 运行 serve dist

  4. 动态服务(tomcat)

    1. 配置webpack.prod.conf.js

      output: {
      ...  
      publicPath: '/myvue/'    -->配置访问时的项目名
      
    2. 打包成dist

    3. 将dist拷贝到tomcat/webapps中,并且再将dist修改成myvue

    4. 启动tomcat,运行

vuecli源码解读

npm run dev 触发了哪些文件

  1. dev ->package.json ->build/webpack.dev.conf.js ->./webpack.base.conf ->./src/main.js引用时的名字叫app

  2. 根据web基础知识可知: http://localhost:8080 实际是访问http://localhost:8080/index.html

    • index.html:

      <div id="app"></div> ->会被src/App.vue中的<div id="app">内容注入:

  3. src/App.vue中内容

    <router-view/> :路由,映射关系 localhost:8080/b–> xxx本项目的映射: localhost:8080/ –>HelloWorld.vue

    配置路由:<router-view/>: router/index.js 文件

小结

npm run dev -> main.js
localhost:8080 /   :index -> router -> HelloWorld.vue中的内容

app.vue中直接引入helloworld.vue

  1. 引入helloworld.vue

    <script>
        import HelloWorld from './components/HelloWorld'
    
  2. 将引入的文件打成一个组件

    export default{
        xxxxxx,
        components:{
            HelloWorld
        }
    }
    
  3. 使用组件

    以标签的形式使用

    <HelloWorld></HelloWorld>
    

ESlint

代码规范检查工具,官网

可以检测

  • 空格个数
  • 空行
  • 变量名
  • 代码是否未被使用

如果不规范,则警告 或报错

检测规则

  • “off” 或 0 - 关闭规则
  • “warn” 或 1 - 开启规则,使用警告级别的错误:warn (不会导致程序退出)
  • “error” 或 2 - 开启规则,使用错误级别的错误:error (当被触发的时候,程序会退出)

设置某些检查规则:.eslintrc.js文件

全局设置是否启用ESlint:.eslintignore文件

注意:

初学:关闭

真实的开发项目:打开,帮助规范代码的编写

vue文件

组成

<template>

<script>

<style>
export default {
     name: '名字' ,
     data(){
     return    msg: 'xxx'
     },
	 omputed:{},
	 methods:{},
 	 components:{//组件}
}   	  

vuex

Vuex 是一个专为 Vue.js 应用程序开发的状态管理模式。它采用集中式存储管理应用的所有组件的状态,并以相应的规则保证状态以一种可预测的方式发生变化。Vuex 也集成到 Vue 的官方调试工具 devtools extension,提供了诸如零配置的 time-travel 调试、状态快照导入导出等高级调试功能。 vuex中文官网

根据官网的流程图来理解Vuex

状态自管理应用包含以下几个部分:

  1. state, 驱动应用的数据源;
  2. view,以声明方式将state映射到视图;
  3. actions, 响应在view.上的用户输入导致的状态变化。

他们时单向不可逆的,我们已简单的数字自增来举例,在state中定义一个变量count,显示在view组件上,通过actions来操作state,state变化后,view中也随之改变。

但实际中vuex还有一个部分 mutations,根据官网的第二张图,我们发现action通过commit调用了Mutations,Mutations通过Mutate调用State,State通过Render来调用view,view通过dispatch来调用Action。此时就有点像mvc模式,actions和Mutations的关系就像service和dao的关系一样,Mutations会执行一些原子性的操作,而actions会做一些带逻辑性的操作;如删除操作,Actions会先判断存不存在,当存在的时候在进行删除,而Mutations则只进行删除操作。

开发一个简单的状态管理

安装vuex依赖

npm install --save vux

新建./src/store.js文件

import Vue from 'vue'
import Vuex from 'vuex'
//使用vuex
Vue.use(Vuex)
//定义共享变量
const state = {
    count :0
}
//直接操作共享变量的对象
const mutations={
    mulincreases(state){
        state.count++;    
    }
}
//操作mutations的对象
const actions={
    actioncrease({commit}){
        commit('mulincreases');
    }
}
//将store.js中的对象暴漏给外界 ,用于其他组件的共享
export default new Vuex.Store({
    state,
    mutations,
    actions
})

封装对象

我们发现要想将对象暴漏给外界,当需要暴漏的对象太多的时候,就会很麻烦,因此我们可以将要暴漏的对象给封装起来。

在前面我们可知,程序在启动时会自动触发src/main.js文件。因此,思路:可以将store.js中暴露的多个对象,封装到main.js中。

例:


//引入准备封装的文件
import store from "./store"
new Vue({
    //xxxx
  store//注入store对象
})

此时我们需要引用需要暴漏的对象时只需要使用store.xxx即可使用。

新建组件使用变量

组件其实就是一个.vue的文件

我们在app.vue中使用变量

src/main.js -》store ->App.vue

程序的启动顺序,先main.js(store) ->App.vue 因此,在使用App.vue时,已经加载过了store,因此在App.vue中可以直接使用store,使用方式:$store

{{$store.state.count}}

通过这种方式使得变量count显示在页面上

    {{$store.state.count}}
    <button @click="countinc">+</button>
    <script>
    export default{
        methods:{
            countinc(){
            //注意$store是一个全局对象需要使用this来拿
            return  this.$store.dispatch('actioncrease')
            }
        }
    }
    </script>

通过this来获取$store对象

执行

npm run dev

异步实现自增 acioncrease

只需要添加并使用此方法

    //异步自增
    asyncincrease({commit}){
        setTimeout(()=>{
            commit('mulincreases')
        },2000)
    }

思维导图

两种取值方式

  1. {{$xxx}}方式

    {{$store.state.count}}
    

数据来自store.js–>getters–>isAudlt(){…}

  1. 方法取值

     <button @click="countinc">+</button>
    

数据来自:store.js–>actions–>actincrease({commit}){}

优化取值

直接使用isAudlt(){…}和actincrease({commit}){}进行取值

vuex中自带了两个对象

import {mapGetters,mapActions} from 'vuex'
  • mapGetters 可以获取getters中的方法
  • mapActions 可以获取Actions中的方法

computed:mapGetters({
  isAudlt : 'isAudlt'//将store.js中getters中的isAudlt()映射成isAudlt对象(前面的是属性,后面的是getters中的方法)
})


  methods:mapActions(['actioncrease','asyncincrease']),

使用

{{isAudlt}}

<button @click="actioncrease">同步+</button>
<button @click="asyncincrease">异步+</button>

思路:

以前需要通过$store获取store. js中的getter方法和actions方法现在可以直接通过mapGetters, mapActi ons获取store. js中的getter方法和actions方法

vue-resource的使用

官网 相当于ajax、axios

  • get(url, [config])

  • post(url, [body], [config])

请求的方式config的作用,当表单发送请求时,需要加上{emulateJSON:true},默认不加也行,但是为了防止某些特殊的情况建议还是加上。在前端,表单提交时一般加上:application/x-www.form-urlencoded,两者作用相似

body参数时传递的参数值;一般是采用对象的方式进行传参

this.$http.get("请求地址",{},{emulateJSON:true}).then(reponse=>{
    consolg.log(resoonse);
})
  • jsonp(url, [config])

支持跨域

如果前台和后台的地址、端口、协议不一致(只要任何一个不一致)就称为跨域请求。为了安全,浏览器一般都禁止跨域请求

解决:使用js技术替代了传统的http请求

使用node.js搭建服务器

const http =  require('http') 
const urlModule =  require('url')   
//localhost:8080/myrequest?cb=myshow
//localhost:8080/myrequest2
//创建服务
let server = http.createServer();
//servlet: doGet(request,resposne)
server.on('request',  function(req,res){
    console.log('abcc')
    const { pathname ,query }  =   urlModule.parse( req.url ,true)
   if( pathname == '/myrequest'){
        var data =  {
            id : 1,
            name :"zs",
            age :23 
        }
        //响应到哪里?
        //localhost:8080/myrequest?cb=myshow
        //myshow(data)   //data->json
        //响应到:myshow方法,并响应的数据:data
        var result = `${query.cb}( ${JSON.stringify(data)}  )` 
        res.end(result)  
   }
})
server.listen(8888,function(){
    console.log('sever running...')
})

客户端

<html>
    <head>
        <meta charset="utf-8">
        <title>111</title>
        <script src="./js/vue.js"></script>
        <script src="./js/vue-resource.js"></script>
        <script>
            function myshow(data){
                console.log(data)
            }
        </script>
        <script src="http://localhost:8888/myrequest?cb=myshow"></script>
    </head>
    <body>
    </body>
</html>

客户端仅仅是引入了一个文件并没有发送请求

Promise的使用

将嵌套方式变成链式写法

读取多个文件的嵌套写法

const fs = require('fs')
const path = require('path')

//读取文件的内容
function myReadFile(fpath,frsuccess,frerror){
    //读取文件时,如果由异常:err
    //数据正常保存data
    fs.readFile(fpath,"utf-8",(err,data)=>{
        if(err) return frerror(err)
        frsuccess(data)
    })
}
//调用  js/file1.txt
//先读取file1.txt,之后读取file2。txt
//读取file1.txt-->成功之后读取-->file2.txt
myReadFile(path.join(__dirname,'./file1.txt'),(data)=>{
    console.log(data)
    myReadFile(path.join(__dirname,'./file2.txt'),(data)=>{
        console.log(data)
    },(err)={})
    
},(err)=>{console.log(err.message)})

读取文件的链式写法

const fs = require('fs')
const path = require('path')
function myReadFile(fpath){

    return new Promise((resolve,reject)=>{
        fs.readFile(fpath,'utf-8',(err,data)=>{
            if(err) return reject(err)
            resolve(data)
        })
    })
}
//调用
// ./代表根目录
myReadFile('./js/file1.txt').then((data)=>{
    console.log(data)
    return  myReadFile('./js/file2.txt')
},(error)=>{
    console.log(error)
}).then((data)=>{
    console.log(data)
}).catch((e)=>{
    console.log(e)
})

.catch 可以统一处理错误

promise的核心:return+then跳出递归

vue组件

vue的三大组成部分

<template> html(组件)
<script> 存放js
<style> 存放css

官网使用手册

定义一个简单的组件

<html>		
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="./js/vue.js"></script>
	</head>
	<div id="myvue">
        <mycom></mycom>
	</div>
	<script>
        Vue.component('mycom',{template:"<h1>这是我的组件</h1>"})
        new Vue({
            el:'#myvue'
        });
	</script>
</html>

注意:

组件名不要使用驼峰命名法,如果使用,则使用该组件的时候使用-符号隔开

组件定义方式

  1. 官网方式

      Vue.component('mycom',{template:"<h1>这是我的组件</h1>"})
    
  2. 完整写法

        Vue.component('mycom',Vue.extend({template:"<h1>这是我的组件</h1>"})
    
  3. 官网方式的id引用的方式

    <template id="mytemp1">
        <h1>这是我的组件</h1>
    </template>
    
    Vue.component('mycom',{template:"#mytemp1"})
    
  4. 完整方式的id引用方式

    <template id="mytemp1">
        <h1>这是我的组件</h1>
    </template>
    
    Vue.component('mycom',Vue.extend({template:"#mytemp1"})
    

注意:定义组件时template:""的值和 <template></template>标签中的内容必须是标签,否则会出错

这种方式定义的组件是全局组件,在所有的Vue对象中都可以使用。

私有组件/局部组件:只能在选定的Vue对象中使用

new Vue({
    el:'#myvue2',
    components:{
        'mycom1':{template:"<h1>这是我的组件</h1>"}
    }
});

其它的创建方式如上

除了定义组件内容之外还可以在组件中定义数据,定义数据的方式如下:

data:function)(){
    return {
        count:0
    }
}

注意:定义的数据必须是function,因为function中定义的变量是局部变量,为了防止多个组件之间共享数据,从而使得定义的组件的数据是独立的。

特殊特性 is

vue中自带一个标签<component></component>是一个组件标签,占位符

<component :is="'comp'"></component>
<!-- 或 -->
<component :is="c"></component>

data:{
    c:'comp'
}

一般vue:xx=xxx值一般是变量,而我们定义的组件名是一个常量,要想将一个常量值变成一个变量值,只需要添加''即可。而变量值是在data中定义的,如果不加''只需要在data中定义变量,其值为组件名即可。

实现动态组件

只需要将:is绑定的值改变,就能实现动态组件。而:is中的值在data中定义,一次只需要改变data中变量的值即可。

<span @click="c='coma'">切换A</span>

<span @click="b()">切换A</span>

methods:{

    b(){
        this.c="comb"
    }
}

注意:行内写法不需要加this,而函数写法需要加this

什么时候加this

  1. 在Vue对象中除了data之外的所有区域使用data中的数据时,都需要使用this

  2. 在页面中使用{{}}data中值是可加this也可不加this

一般结论:大多数的情况下,只要获取data中的变量的时候都需要使用this,除了个别特殊的情况,如:行内式写法、

组件的过渡效果和参数传递的问题

  1. 将过度组件放入<transition></transition>标签中

  2. 编写样式在<style></style>标签中编写css样式

    <style>
        .v-enter,
        .v-leave-to{
            opacity: 0 ;
            transform: translateX(100px) ;
        }
        .v-enter-active,
        .v-leave-active{
                transition: all  1s  ease ;
        }
    </style>
    

    <transition>mode="out-in"属性可以设置出现的顺序,这样的话能避免重合。

传参

<coma :msg="aname"></coma>

Vue.component('coma', 
                { 
                    template:" <p>这是我的组件A  {{msg}}</p>",
                    props: ['msg']
                }
            )

data:{
    aname :"你好,世界"
}

:msg,msg是自己定义的属性名,他的值是一个变量aname,在data中定义。组件在使用msg属性的值的时候不能直接使用,需要借助props中转,然后进行使用。

注意:组件中参数引用的位置一定要在标签中,否组Vue不认识它。

组件的简化写法

  1. 公有组件

    var comc = {
                    template: '<p>这是组件C</p>'
                }
    Vue.component('comc',comc)
    
    <comc></comc>
    

    共有组件与Vue对象同级,在Vue对象的外面写

  2. 私有组件

    var mycomc = {
                    template: '<p>这是组件C</p>'
                }
    
    components:{
                        'mycomc': mycomc
                }
    
    <mycomc></mycomc>
    

注意:当组件名和变量名是同一个时可简化,只写组件名或变量民即可。

例上面可以简化为:

components:{
                  mycomc
             }

小结:简化的核心就是使用var变量保存组件,然后通过引用变量实现自定义组件。

调用组件内部的方法

普通的方法调用

<button @click="aa()">点击事件</button>
methods:{
    aa(){
        alert("hahahah")
    }
}

调用的方法时vue中的methods中定义的方法

定义的组件的方法的调用

组件常用的定义方式

  1. 定义组件内容

    <template id="mytempid">
            <button @click="myclick">方法调用</button>
    </template>
    
  2. 完善组件结构

    var com = {
            template : '#mytempid' ,
            data(){//局部变量 ,xx(){return {k:v}}
                return {
                    comdata:{
                        num:1 
                    }
                }
            },
            methods:{
                myclick(){
                    this.$emit('mycomclick',this.comdata.num)  //myshow(a)
                }
            }
        }
    
  3. 注册到Vue中

    • 公有组件

      Vue.component('com',com)
      
    • 私有组件

      components:{
                      //com:com 
                      com
                  }
              }
      
  4. 使用

    通过标签使用

    <com @mycomclick='myshow'></com>
    

组件中的单击事件调用的不是Vue中的Methods中定义的方法,而是组件中methods中定义的方法。

调用组件内部按钮中的方法:单击–>组件中的method–>vue中的method

小结:组件的单击事件<button @click="myclick">调用组件中的methods中定义的单击函数myclick;组件中定义的函数通过this.$emit触发组件自定义的事件 <com @mycomclick>, 组件的自定义事件调用Vue中定义的事件函数 myshow,从而实现事件的点击。

核心思路:

  1. 普通的Html对象:直接调用Vue中的Methods中定义的函数

  2. 如果是组件,则调用组件中methods定义的方法,接着通过组件中的methods调用Vue中的methods

  3. 细节:组件中传递方法时: 发:自定义事件 收:$emit

当函数需要传参时this.$emit('mycomclick','hello') hello就是第一个参数,传多个参数时,通过,隔开

this所在位置

当在组件中使用this时,代表当前组件,当需要使用data中的数据时需要通过this.comdata.xxx来获取变量

当在Vue中使用this代表当前Vue对象,想要使用data中的数据时,需要使用this.xxx来获取变量。

refs

相当于jquery中的选择器

在jquery中:

定义
id="myid"
使用
$("#myid")

在vue中:

定义
ref="myref"
使用
this.$refs.myref
<html>		
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="./js/vue.js"></script>
	</head>
	<div id="myvue">
			<!--普通元素-->
			<div ref="mydiv">
				这是div元素...
			</div>
			<!-- 组件-->
			<com ref="mycom"></com>

			<button @click='myVueShow'>调用vue中的方法</button>
	</div>
	<template id="mytempid">
			<div>普通组件...</div>
	</template>	
	<script>
	var com = {
		template : '#mytempid' ,
		data(){
			return {
				mymsg:'组件内部的数据'
			}
		},
		methods:{
			myComponentShow(){
				alert('这是组件中的方法...')
			}
		}
	}
const vm = new Vue({
			el : "#myvue",
			data:{
			},
			methods:{
				myVueShow(){
						//alert('myvueshow...');
						//alert(this.$refs.mydiv.innerText)
						//获取组件中定义的mymsg数据
						//alert(this.$refs.mycom.mymsg)
						//调用组件中定义的方法
						this.$refs.mycom.myComponentShow()
				}
			},
			components:{
				//com:com 
				com
			}
		}
	);
	</script>
</html>

refs的作用:获取某个元素、组件,调用组件中的属性、方法、数据等信息

render函数

把组件模板(template)渲染成html(替换之前的内容)

<html>		
	<head>
		<meta charset="utf-8" />
		<title></title>
		<script src="./js/vue.js"></script>
	</head>
	<div id="myvue">
			<div>
				这是div元素...
			</div>
	</div>
	<template id="mytempid">
			<span>普通组件...</span>
	</template>	
	<script>
	var com = {
		template : '#mytempid'
	}
const vm = new Vue({
			el : "#myvue",
			data:{
			},
			methods:{
			},
			render:function(createElements){
				return  createElements(com) //该方法的参数,就可以将组件渲染成html
			}
		}
	);
	</script>
</html>