Vue 笔记

文章目录

01 Vue的基本指令

03 动态绑定

1. v-bind的基本使用

一般形式:v-bind:属性名="值"
简写形式::属性名="值"
如:

<img v-bind:src="imgUrl" alt="">

2. v-bind绑定class属性

3. v-bind绑定style属性

04 计算属性computed

计算属性, 就是用来进行属性的组合利用的
例如我们有一个firstName , 和一个lastName , 此时可以使用插值表达式 {{firstName + ’ ’ + lastName }} 来进行组合, 但是这么做的可读性与重复利用性又十分糟糕
但是我们可以利用methods方法来进行属性的组合, 但是这么做会带来一定额外的开销, 并且我们可以注意到我们对firstName 和lastName的操作不会涉及到其他任何属性, 就好像他们是一个属性一样, 所以就有了计算属性

1. 实现属性的组合的三种方法

实现属性组合有三种方法

  1. 插值表达式中直接写
    如: {{firstName }} {{lastName}}
  2. 在methods中写getXXX方法 , 然后利用mastache语法 {{getXXX()}}调用, 注意这里需要加括号

使用: {{getFullName()}}

methods: {
getFullName(){return this.firstName+this.lastName}
}
  1. 第三种方式就是, 定义computed 属性(本质是一个属性)

计算属性的本质是一个属性, 详情请看本节的 2. , 因此使用时与methods不同 , computed属性不需加()

2. 计算属性基本使用

data , methods, el 属性相同, computed 属性定义在Vue对象中, 可以使用一个函数来给他的属性赋值, 如下

const app = new Vue(){
	el: "#app",
	data: {
	fristName: "A",
	lastName: "B"
	}	,
	//------------------
	computed:{
	fullName: function(){
	return firstName + " " + lastName
}
	//-------------------
	}

}

3. 计算属性的本质

其实计算属性的完整写法如下 , 也就是说, 计算属性本质上是一个对象属性

computed: {
	fullName: {
		get : function(){
		
		},
		set: function(){
		}
	}
}

但是我们一般不希望别人去set, 所以我们一般不会定义set方法

computed: {
	fullName: {
		get : function(){
		
		}
	}
}

但是这么 写有有些麻烦, 所以就有了简便写法

computed: {
fullName: function(){}
}

4. computed 和 methods的区别

computed 和 methods 都能够实现属性的组合, 他们的区别在于computed会对属性值进行缓存, 每次调用computed属性, 他只会调用一次get方法, 而methods会被调用多次

考虑下面的代码, 在chrome 开发者工具中多次调用, 可以看到如上讨论的结果

    computed: {
      //computed只会被调用一次
      fullName:function(){
        console.log("computed called")
        return this.firstName + this.lastName
      }

    },
    methods:{
      //methods会被调用多次
      getFullName(){
        console.log("method called")
        return this.firstName + this.lastName
      }

在这里插入图片描述

练习1-获取和设置姓名

假设data中有以下数据
data:{
familyName : “张”, //姓
lastName: “三” , //名
}

写 fullName 的set 和 get方法(假设姓只有一个字并且总是字符串第一个字符), 利用 Google chrome 调试工具, app.name = “张三” , 来设置一个姓名, 利用app.name来获取姓名进行调试
如:
app.fullName // 显示 张三
app.fullName = “李四”
//设置 familyName 于 lastName

05 Vue中的事件监听v-on

1. v-on的基本使用

  1. v-on指令的一般语法是
v-on:事件名="函数名[(参数1,参数2,...]"

如:

<h1 v-on:click="cleack">v-on非简写</h1>
  1. v-on指令有语法糖@, 即
@事件名="函数名[参数1,参数2,...]"

如:

<h1 @click="cleack">v-on简写</h1>

v-on语法糖:@指令

.stop: 停止冒泡事件
.prevent: 阻止默认事件
.key: 按下某个键

2. v-on参数传递

  1. 调用不加括号时, 默认函数参数第一个为event事件对象
<!--不加参数时, 函数的第一个参数为event 对象, 其他(如果有的话)为undefined-->
  <button @click="btn1Click">不加参数</button>
  1. 调用加括号时, 按指定传入, 如果想要事件对象, 需要在参数列表中写$event
<!--  加参数时, 如果不需要添加event对象, 直接再括号中写参数列表即可-->
  <button @click="btn2Click('dslkjflsdkfj', 234)">加参数不要event对象</button>
<!--  加参数时, 如果想添加event对象, 则需要在括号中写$event-->
  <button @click="btn3Click('str', $event , 12345)">加参数要Event对象</button>

3. v-on修饰符

常用修饰符如下

  • @事件.stop: 阻止冒泡事件
  • @事件.prevent: 阻止默认事件
  • @keyUp/keyDown.键位名称: 监听键盘事件
    示例如下:

<!--  利用.stop来取消冒泡事件-->
  <div @click="div1Click">
    <button @click.stop="btn1Click">不冒泡</button>
    <button @click="btn1Click">冒泡</button>
  </div>

<!--2. 利用prevent来取消默认事件, 如提交按钮的提交事件-->
  <form action="www.baidu.com">
    <input type="submit"  @click.prevent="mySubmit" value="取消提交默认事件" >
    <input type="submit" value="不取消的提交">

<!-- 3.@keyUp.enter 来监听回车事件-->

    <input type="text"  @keyup.enter="keyupEnter">

  </form>

注意: keyUp这种键盘监听事件一般只能在input中使用

06 条件判断

1.v-if/ v-else/v-else-if 的基本使用

vue条件判断的基本语法是:

  1. v-if="布尔表达式"
  2. v-else-if="布尔表达式"
  3. v-else
    示例如下
<div id="app">
<!--  1. v-if/v-else-if="布尔表达式"/v-else-->
  <h1 v-if="score>=90">优秀</h1>
  <h1 v-else-if="score>=80">良好</h1>
  <h1 v-else-if="score>=60">及格</h1>
  <h1 v-else>不及格</h1>
</div>

2. vue中的DOM渲染机制及Key指令

看下面的案例, 在点击切换时, input框明明不是同一个, 切换后的内容却相同
切换前:
切换前

切换后:
切换后

<div id="app">
  <span  id="username" v-if="username">
    <span>用户账号</span>
    <input type="text" placeholder="用户账号">
  </span>
  <span  id="email" v-if="email">
    <span>用户邮箱</span>
    <input type="text" placeholder="用户邮箱">
  </span>
<!--点击切换后发现, input框明明不是同一个, 内容却相同, 原因是vue内部为了节省性能, 会尽可能的复用DOM元素-->
  <button @click="toggleType">切换类型</button>
</div>

究其根本, 是因为vue内部为了节省性能资源, 会尽可能的渲染元素

官方文档: 虚拟DOM

解决方案:

添加key指令, 作为DOM唯一标识, 就不会再复用

<div id="app">
  <span  id="username" v-if="username">
    <span>用户账号</span>
    <input type="text" placeholder="用户账号" key="username">
  </span>
  <span  id="email" v-if="email">
    <span>用户邮箱</span>
    <input type="text" placeholder="用户邮箱" key="email">
  </span>
<!--点击切换后发现, input框明明不是同一个, 内容却相同, 原因是vue内部为了节省性能, 会尽可能的复用DOM元素-->
  <button @click="toggleType">切换类型</button>
</div>

这里涉及到virtualDOM底层问题, 目前我们不需过度深究

3. v-show 与 v-if

v-show指令与v-if指令语法相同 , 并且可以使用v-else与v-else-if

<div id="app">
  <!--  1. v-show="布尔表达式"-->
  <h1 v-show="score>=90">优秀</h1>
  <h1 v-else-if="score>=80">良好</h1>
  <h1 v-else-if="score>=60">及格</h1>
  <h1 v-else>不及格</h1>
</div>

区别在于

  • 当使用v-show时, 若条件为false仅仅只是将元素的display属性设置为none
  • 而当使用v-if时, 如果条件为false元素的DOM根本不会存在
    根据以上的特点
  • 当一个元素需要频繁的在显示和隐藏直接切换时, 就用v-show
  • 当一个元素只需要渲染一次或少次的时候就用v-if

★注意:上面的案例中的v-else-if/v-elsev-if一样, 如果为false不会存在

07 v-for循环遍历

1. v-for遍历数组

v-for 遍历数组有两种方法:

  1. item in 数组名: 得到的是值
  2. (item , index ) in 数组名: 得到的是值和索引
<div id="app">
  <ul>
<!--    1. 如果只拿一个拿的是值-->
    <li v-for="item in movies">{{item}}</li>
<!--    2. 括号获取索引-->
    <li v-for="(item , index) in movies">{{index + '.'+item }}</li>
  </ul>
</div>

2. v-for遍历对象

v-for遍历对象有三种语法:

  1. value in 对象名 : 获取每个对象的值
  2. (value , key) in 对象名: 获取每个对象的值和键
  3. (value, key , index) in 对象名: 获取每个对象的值、键、索引

示例如下:

<div id="app">
  <ul>
    <!--    1. 如果只拿一个拿的是值-->
    <li v-for="item in obj">{{item}}</li>
    <!--    2. 两个参数获取值和键-->
    <li v-for="(value , key) in obj">{{key + ":"+value }}</li>
    <!--    3. 三个参数获取值、键、索引-->
    <li v-for="(value , key,index) in obj">{{index + '.'+key + ":"+value }}</li>
  </ul>
</div>

3. v-for与key

key属性的作用就是提高DOM渲染的速率, 要尽量保证元素key的唯一

vue官方建议: 在使用v-for时, 最好给每个元素添加一个key属性

4. 数组中哪些方法为响应式

不是所有的 JavaScript 数组方法都是响应式的, 如利用数组索引改变元素就不会更新浏览器的DOM

  • push: 在数组末尾插入元素
  • pop: 在数组末尾删除元素
  • shift: 在数组开头删除元素
  • unshift: 在数组开头插入元素
  • sort: 对数组进行排序
  • reverse: 对数组进行逆序
  • splice(a1,a2,a3): 在a1位置删除a2个元素并且插入a3元素

08-Javascript高阶函数

1. 数组的遍历

数组的高阶遍历有两种方式:

  1. Let …in …: 索引遍历
  2. let …of …元素遍历
      //1. 方式1
      let totalPrice = 0;
      for(let i in this.books){
        totalPrice += this.books[i].price * this.books[i].count;
      }
      //方式2
      let totalPrice2 = 0;
      for (let book of this.books){
        totalPrice2 += book.price * book.count
      }

2. filter函数

filter(Function): 用来获得掉符合Function条件的内容, Function为返回布尔值的函数

如过滤n大于100的数字, 获得n<100的数字

      let nums = [1,1244,192,93,34,19042,24,194]
      nums.filter(function(n){
        return n < 100
      })

可以直接利用Lambda表达式

let newNums1 = nums.filter(n => n < 100)

3. map函数

map(Function(n)): map用来根据Function生成新的数组, 它会对数组中每一个元素进行遍历, n为输入的每个元素, 随后对n进行更改, 更改的值为返回值

如将数组中每个元素乘2

let newNums1 =newNums.map(n => n*2)

4. reduce函数

reduce(Function(preValue, n), initPreValue): reduce会对数组中的每个元素进行遍历

  • preValue: 上次Function 的返回值
  • n: 每次遍历时数组的元素
  • initPreValue: 初始时preValue的值

如计算数组的和

let total = newNums1.reduce( (preValue, n)=> preValue + n, 0 )

上面三个函数可以写在一行直接得到:

nums.filter(n => n < 100).map(n => n*2).reduce( (preValue , n ) => preValue + n, 0 );

09 v-model

01-v-model基本使用

v-model指令用来进行数据的双向绑定

<!--  1. v-model="表达式" 实现数据的双向绑定-->
  <input type="text" v-model="message">
  {{message}}

当文本框内容更改时, message的内容也进行更改
在这里插入图片描述

02-v-model的本质

v-model的本质其实就是v-onv-bind的结合, 如我们可以利用 v-on:input事件与v-bind指令来实现数据的双向绑定

  <!--  1. v-model 本质是两个指令的结合:v-on 和 v-bind -->
  <input type="text" :value="message" v-on:input="message = $event.target.value">
  {{message}}

03-v-model与radio

v-model中的值为true时代表选中

<!--  name让radio变为单选-->
<!--  value与v-model变量相同代表选中-->
  <label for="">
    <input type="radio" id="male" name="sex" value="" v-model="sex"></label>
  <label for="">
    <input type="radio" id="female" name="sex" value="" v-model="sex"></label>

04-v-model结合checkbox类型

单选: v-model中填true代表选中
多选: v-model中填数组, input中要有value值
- 当数据元素中存在对应value 的元素时代表选中

<!--1. checkbox单选框对应布尔值, 当v-model中的变量值为true时表示选中-->
<div id="app">
  <label for="license">
    <input type="checkbox" id="license" v-model="isAgree">同意XXX协议
<!--    button的disabled表示不可点击-->
    <div><button :disabled="!isAgree">下一步</button></div>
  </label>


<!--2. checkbox单选框对应数组-->
<!--  当选中时, value值添加到数组中-->
<!--  当value值存在在数组中时表示选中-->
    <label for="">
      <input class="hobbies" type="checkbox" value="篮球"  v-model="hobbies">篮球
      <input class="hobbies" type="checkbox" value="足球"  v-model="hobbies">足球
      <input class="hobbies" type="checkbox" value="羽毛球"  v-model="hobbies">羽毛球
      <input class="hobbies" type="checkbox" value="乒乓球"  v-model="hobbies">乒乓球
      <!--    button的disabled表示不可点击-->
      <div >您的爱好是{{hobbies}}</div>
    </label>
<!-- 3. 我们可以利用v-bind绑定的形式来写多选的checkbox等-->
  <label v-for="item in allHobbies" for="item">
    <input type="checkbox" :value="item" id="item" v-model="hobbies">{{item}}
  </label>

</div>

05-v-model结合select类型

select类型与checkbox类似, 同样的, 多选时, option标签中要有能与数组对应的value属性

<!--  1. select 单选-->
<!--  当value值与变量相同时表示选中-->
  <select name="abc" v-model="fruit">
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="葡萄">葡萄</option>
    <option value="橘子">橘子</option>
  </select>
  <div>选中: {{fruit}}</div>

<!--  2. select多选-->
<!--  当数组中存在与value相同的元素时表示选中-->

  <select  v-model="fruits" multiple>
    <option value="苹果">苹果</option>
    <option value="香蕉">香蕉</option>
    <option value="葡萄">葡萄</option>
    <option value="橘子">橘子</option>
  </select>
  <div>选中: {{fruits}}</div>
</div>

06-v-model结合v-for

<!-- 3. 我们可以利用v-bind绑定的形式来写多选的checkbox等-->
  <label v-for="item in allHobbies" for="item">
    <input type="checkbox" :value="item" id="item" v-model="hobbies">{{item}}
  </label>

07-v-model修饰符的使用

添加修饰符的一般语法: v-model.修饰符=""
常用修饰符如下
在这里插入图片描述


<div id="app">
  <!-- 1. lazy:懒加载, 使得当输入失去焦点或者按下回车时才进行数据的绑定-->
  <input type="text" v-model.lazy="message">
  <div>{{message}}</div>

  <input type="text" v-model.number="num">
  <div>{{num}}类型: {{typeof  num}}</div>

  <!-- 3. trim: 去除前后的空格-->
<!--  通过console查看, 未去除前后空格-->
<!--  <input type="text" v-model="strTrim">-->
  <!--  通过console查看, 的确去除前后空格s-->
  <input type="text" v-model.trim="strTrim">
  <div>{{strTrim}}</div>

</div>

10 组件化-组件的创建

01-组件化实现和使用步骤

组件化分为三个步骤

  1. 利用Vue.extend(options)创建组件构造器对象
  2. 注册组件, 有两种方法
    • 全局组件: 利用Vue.component('标签名' , 构造器对象)注册组件
    • 局部组件: 在Vue实例中使用template属性来进行注册
      Vue({
      template:{
      标签名:组件构造器
      }
      })
      
  3. 使用组件

注意:

  1. 组件只能在Vue实例中使用
  2. 组件的模板必须只能拥有一个根元素

下面写法正确✔

<template id="counter">
   <h2>当前计数:{{count}}</h2>
</template>

下面写法 错误:X

<template id="counter">
   <h2>当前计数:{{count}}</h2>
   <h2>当前计数:{{count}}</h2>
</template>

实例代码如下

//1. 创建组件构造器对象
  const cpn = Vue.extend({
    template:`
    <div>
      <h1>我是组件</h1>
      <p>我是组件的内容</p>
    </div>
    `
  })

  //2. 注册组件(全局组件, 在任何Vue实例中都可以使用)
  Vue.component("mcpn" , cpn)

02-全局组件与局部组件

全局组件: 能在所有Vue实例中使用的组件, 使用Vue.component注册的组件为全局组件
局部组件: 只能在注册的Vue实例中使用的组件, 在components属性中进行注册

局部组件的注册:

  //2. 注册组件(全局组件, 在任何Vue实例中都可以使用)
  // Vue.component("mcpn" , cpn)

  const app = new Vue({
    el:"#app",
    data:{
      counter: 0,
      message: "你好啊",
      movies:["movie1" ,"movie2", "movie3", "movie4"]
    },
    methods:{
    },
    components:{
      //注册局部组件:  标签名:组件构造器对象
      mcpn:cpn
    }
  })

03-父子组件与root组件

我们可以将组件在另外一个组件中注册,该组件称为父组件,被注册的组件称为子组件, Vue实例称为根组件

Notes:
在父组件中注册的组件只能在父组件中使用, 无法在其他组件(包括root组件)中使用

  const cpnC1 = Vue.extend({
    template:`
          <div>
      <h1>我是子组件</h1>
      <p>我是子组件的内容</p>
    </div>
    `
  })

  const cpnC2 = Vue.extend({
    template:`
          <div>
      <h1>我是父组件</h1>
      <p>我是父组件的内容</p>
        <cpn1></cpn1>
          </div>
    `,
    components:{
      cpn1:cpnC1
    }
  })


  Vue.component("cpn2" ,cpnC2)

04-组件创建的语法糖写法

  // 1. Vue2.0之后, 提供组件的语法糖写法, 省去了创建组件构造器对象的步骤(官方推荐这种写法)
  Vue.component("cpn1", {
    template:`
          <div>
      <h1>我是子组件</h1>
      <p>我是子组件的内容</p>
    </div>
    `
  })

05-组件模板的抽离写法

在javascript带代码中写过多的html代码会让代码看起来十分混乱, 因此我们采取模板抽离的写法, 有两种实现方式

  1. script标签
  2. template标签

在对应标签中都需要填写id属性, 之后注册时写 template:'#id'

示例代码:


<div id="app">
  <cpn1></cpn1>
  <cpn2></cpn2>
</div>

<script src="../js/vue.js"></script>

<!--1. 方式一: script标签-->
<script type="text/x-template" id="cpn1">
  <div>
    <h1>script模板抽离</h1>
  </div>
</script>

<!--方式二: template标签-->
<template id="cpn2">
  <div>
    <h1>template标签模板抽离</h1>
  </div>
</template>

<script>
Vue.component("cpn1", {
  template: "#cpn1"
})

Vue.component("cpn2" ,{
  template:"#cpn2"
})


    const app = new Vue({
        el:"#app",
        data:{
            counter: 0,
            message: "你好啊",
            movies:["movie1" ,"movie2", "movie3", "movie4"]
        },
        methods:{

        },
      components:{
      }
    })
</script>

06-组件中的data()属性

组件中无法使用Vue实例中的数据, 实际上, 组件可以有自己的数据, 数据的保存使用函数进行保存

采用函数进行保存的原因:

我们可能建立多个组件的实例, 如果使用对象保存, 那么所有组件的对象都是同一个对象, 因此使用函数进行保存, 使得每个实例拥有不同的data对象

<body>


<div id="app">
  <counter></counter>
  <counter></counter>
  <counter></counter>
</div>

<template id="counter">
  <div>
    <h2>当前计数:{{count}}</h2>
    <button @click="increment">+</button>
    <button @click="decrement">-</button>
  </div>
</template>


<script src="../js/vue.js"></script>
<script>

  Vue.component("counter", {
    template:"#counter",
    data(){
      return {
        count :0
      }
    },
    methods:{
      increment(){
        this.count++
      },
      decrement(){
        this.count--
      }
    }
  })


    const app = new Vue({
        el:"#app",
        data:{
            counter: 0,
            message: "你好啊",
            movies:["movie1" ,"movie2", "movie3", "movie4"]
        },
        methods:{


        }
    })
</script>
</body>

11 组件化-组件的通信

01-组件通信-父传子-props属性

父组件传递给子组件数据利用的是子组件的props属性, 有两种方法

  1. 数组写法: [‘变量名1’ , ‘变量名2’ ,…]
    1. props: ['变量名1' , '变量名2' ,...]
    2. 在组件标签中利用父组件变量赋值 (利用v-bind:指令)
    <cpn :cmovies="movies"></cpn>
    

    如果变量名使用了驼峰形式如cMovies, 那么在v-bind: 绑定时要写为:c-movies

    1. 在子组件中使用即可
  2. 对象写法:
    1. 指定类型, 默认值

    注意, 对于数组与对象的默认值, 必须是一个函数:

         props: {
           cmovies:{
             type: Array,
             default(){
              return []
            }
          }
        }
    
    1. 在组件标签中利用父组件变量赋值 (利用v-bind:指令)
    <cpn :cmovies="movies"></cpn>
    
    1. 在子组件中使用即可

注意:不要在子组件中修改prop属性中的值, 不推荐这么做(因为值和父组件值绑定), 并且会报错

示例代码如下


<div id="app">
<!--  2. 在组件标签中赋值-->
  <cpn :cmovies="movies"></cpn>
  <cpn1 :cmovies="movies"></cpn1>
</div>

<script src="../js/vue.js"></script>


<template id="cpn">
  <div>
    <h2>我是子组件</h2>
    <ul>
<!--      3.使用 -->
      <li v-for="(item,index) in  cmovies"> {{item}}</li>
    </ul>
  </div>
</template>

<script>
    const app = new Vue({
        el:"#app",
        data:{
            counter: 0,
            message: "我是父组件",
            movies:["movie1" ,"movie2", "movie3", "movie4"]
        },
        methods:{

        },
      components:{
        cpn:{
          template:"#cpn",
          //1. props数组写法, ['变量名1' , '变量名2' ,...]
          props:[ "cmovies" ]
        },
        cpn1:{
          template:"#cpn",
          //2.对象写法:
          props: {
            cmovies:{
              type: Array,
              default(){
                return []
              }
            }
          }
        }
      }
    })
</script>

02-组件通信-子传父-自定义事件与$emit

子传父只能通过事件进行传递

  1. 在子组件中定义事件
  2. 事件触发时执行this.$emit(‘自定义事件名’ , 参数1,参数2)
  3. 在子组件标签中写 @自定义事件名="方法/js代码"
  1. 中方法不需要填写参数, 参数会自动传递
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>


<div id="app">
  <!--  @自定义事件名="执行方法"-->
  <cpn @itemclick="itemclick"></cpn>
</div>

<script src="../js/vue.js"></script>


<template id="cpn">
  <div>
    <h2>我是子组件</h2>
    <ul>
      <li v-for="(item,index) in  books">
        <button @click="btnClick(item)">{{item.name}}</button></li>
    </ul>
  </div>
</template>

<script>
  const app = new Vue({
    el:"#app",
    data:{
      counter: 0,
      message: "我是父组件",
      movies:["movie1" ,"movie2", "movie3", "movie4"]
    },
    methods:{
      itemclick(item){
        //自定义事件
        console.log(item)
      }
    },
    components:{
      cpn:{
        template:"#cpn",
        data(){
          return {
            books:[
              {id:1, name:"计算机原理"},
              {id:2, name:"操作系统原理"},
              {id:3, name:"C++ Primer中文版"},
            ]
          }
        },
        methods:{
          btnClick(item){
            this.$emit("itemclick" , item)
          }
        }
      },

    }
  })
</script>

</body>
</html>

03子组件自实现父组件双向绑定

自实现绑定, 使得子组件父组件的两个data与子属性中的props属性双向绑定

数据的绑定不能使用props中的变量,会导致混乱 必须使用data中的变量

不要在子组件中修改prop属性中的值, 不推荐这么做(因为值和父组件值绑定), 并且会报错

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<!--子组件父组件数据绑定(props , data), input改变时跟着改变-->





<div id="app">
  <div>pnum1:{{pnum1}}</div>
   <cpn :number1="pnum1" :number2="pnum2"
        @num1change="num1Change" @num2change="num2Change"
   ></cpn>
  <div>pnum2:{{pnum2}}</div>
</div>

<script src="../js/vue.js"></script>

<template id="cpn">
  <div>
    <div>num1: props:{{number1}}</div>
    <div>num2: data:{{num1}}</div>
    <input type="text" @input="num1Input">
    <div>num2: props:{{number2}}</div>
    <div>num2: data:{{num2}}</div>
    <input type="text" @input="num2Input">
  </div>
</template>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            counter: 0,
            message: "你好啊",
            movies:["movie1" ,"movie2", "movie3", "movie4"],
          pnum1:1,
          pnum2:2
        },
        methods:{
          num1Change(value){
            this.pnum1 = value * 1 //转化为int
          },
          num2Change(value){
            this.pnum2 =  value * 1
          }
        },
        components:{
          cpn:{
            template:"#cpn",
            data(){
              return {
                num1:this.number1,
                num2:this.number2
              }
            },
            props:{
              number1:{
                type:Number,
                default() {
                  return 0;
                }
              },
              number2:{
                type:Number,
                default() {
                  return 0;
                }
              }
            },
            methods:{
              num1Input(event){
                this.num1 =event.target.value
                this.$emit('num1change', this.num1)
              },
              num2Input(event){
                this.num2 = event.target.value
                //不要在子组件中修改prop属性中的值, 不推荐这么做(因为值和父组件值绑定), 并且会报错
                this.$emit('num2change', this.num2)
              }
            }

          }
        }
    })
</script>


</body>
</html>

04-父组件访问子组件

父访问子组件实例有两种方法:

  1. this.$children:父组件可以直接访问到所有的子组件示例, 子组件示例会添加到this.$children数组中
  2. this.$ref: 与$children不同, $ref 默认是空对象
    1. 给子组件实例添加ref='引用名'属性, 来添加子组件的引用
    2. 父组件中通过this.$ref['引用名']来进行引用

一般不会通过$children拿子组件, 而是通过$ref, $ref用的非常多

代码示例如下

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Title</title>
</head>
<body>
<!--父访问子有两种方式: $children, $ref-->


<div id="app">
<!--  1. 通过$children拿到值-->
  <cpn name="第0个组件"></cpn>
  <cpn name="第1个组件"></cpn>
  <button @click="btnClick">Click me</button>
<!-- 2. 通过ref-->
  <cpn name="用ref绑定的组件" ref="cpn3"></cpn>
  <button @click="refClick">refClick</button>
</div>

<template id="cpn">
  <div>
    <p>{{this.name}}</p>
  </div>

</template>

<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            counter: 0,
            message: "你好啊",
            movies:["movie1" ,"movie2", "movie3", "movie4"]
        },
        methods:{
          btnClick(){
            console.log(this.$children)
          },
          refClick(){
            console.log(this.$refs)
            console.log(this.$refs["cpn3"])
          }

        },
      components:{
          cpn:{
            template:'#cpn',
            props:{
              name:{
                type:String ,
                default:'第0个组件'
              }
            }
          }
      }
    })
</script>

</body>
</html>

05-子组件访问父组件

$parent:访问使用该子组件示例的父组件示例
$root:访问Vue实例

若父组件为Vue实例, 那么$parent访问的就是Vue实例

parent使用的非常少

下面示例通过点击按钮来测试$parent$root


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


<div id="app">
  <cpn>
  </cpn>

</div>

<template id="cpn">
  <div>
    <button @click="btnClick">子组件</button>
    <ccpn></ccpn>
  </div>
</template>

<template id="ccpn">
  <div>
    <button @click="btnClick">子组件</button>
  </div>
</template>
<script src="../js/vue.js"></script>
<script>
    const app = new Vue({
        el:"#app",
        data:{
            counter: 0,
            message: "你好啊",
            movies:["movie1" ,"movie2", "movie3", "movie4"]
        },
        methods:{


        },
      components:{
          cpn:{
            template:"#cpn",
            methods: {
              btnClick(){
                console.log(this.$parent)
              }
            },

            components:{
              ccpn:{
                template:"#ccpn",
                methods:{
                  btnClick(){
                    console.log(this.$parent)

                    console.log(this.$root)
                  }
                }
              }


            }

          }
      }
    })
</script>
</body>
</html>

11 slot插槽

01-无名插槽的使用slot

我们可以给模板指定插槽, 来让父组件决定要插入的内容

  1. 在模板中添加slot标签

    可以在 slot标签中内嵌内容作为默认内容

  2. 在组件实例化标签内部嵌入要插入的内容

如下

  1. 在模板中添加slot标签
<tempalte id="cpn">
  <div>
    <h1></h1>
    <slot>
    默认内容
    </slot>
  </div>
</tempalte>
  1. 在组件实例化标签内部嵌入要插入的内容
<div id="app">
<!--子组件实例中使用-->
  <cpn>
    <div>Anonymous Slot Here</div>
  </cpn>
</div>

02-具名插槽的使用

  1. 定义: 在模板的slot标签中添加name属性
  2. 使用: 在子组件实例中带有slot='name属性值' 的标签, 使用该名的插槽
<template id="cpn">
  <div>
<!--    1. 在模板中定义-->
    <slot name="content">
      默认内容
    </slot>
  </div>
</template>

<div id="app">
  <cpn>
<!--    2. 在子组件实例中使用-->
    <div slot="content">名为content的插槽</div>
  </cpn>
</div>

不填名字使用无名插槽

03-编译作用域

到底是哪个变量取决于使用变量的位置, 变量在哪个组件的模板中使用, 就优先使用哪个组件的变量

如下面的cpn组件,这里的模板是父组件的模板, isShow使用的是父组件即Vue实例app中的isShow

<div id="app">
    <h1>{{message}}</h1>
<!--变量是在父组件中的模板使用的, 因此使用父组件中的变量-->
  <cpn v-show="isShow"></cpn>
</div>

04-作用域插槽(暂留: depreceted)

在父组件中使用组件时可以拿到子组件的数据, 父组件替换插槽的标签, 但是内容由子组件来提供

12 模块化开发

01-ES5的模块化开发

02-CommonJS的模块化开发

模块化开发规范:AMD, CommonJS, ES6, CMD

导出:module.exports = {值1, 值2,...}
导入: const {值1, 值2} = require('文件');
导出: export const 变量=值
导入: import {1,2,3,..} from "文件"

03-webpack与安装

webpack为了可以正常运行, 必须依赖node环境, 利用npm工具可以用来安装webpack
输入下面命令进行全局安装

npm install webpack@3.6.0 -g

为什么全局安装后, 还需要局部安装呢?

  • 在终端直接执行webpack命令, 使用的是全局的webpack
  • package.json中定义了scripts时, 其中包含了webpack命令, 那么使用的是webpack

04-webpack起步

webpack 是一个而现代的JavaScript引用的静态模块化打包工具
核心概念是: 模块与打包

ES6, sass等制作的文件没办法直接放到服务器上, 肯定是要通过打包,编译工具编译成ES5等绝大多数浏览器能够识别的格式, grunt, gulp, webpack

05-webpack的基本使用

  1. 建立distsrc文件夹
    1. dist文件夹存放打包后的bundle.js
    2. src文件夹存放源码
  2. src中编写代码
  3. webpack

打包:

$ webpack js文件 打包的位置

05-webpack的config.js与Package.json配置

安装path包
npm init
meetwebpack

06-loader的使用

07-webpack vue

  1. 安装vue
npm install vue --save

开发环境与生产环境都要用, 就不要 --save-dev 了

  1. js代码中引入vue
//导入vue
import  Vue from 'vue'

const app = new Vue({
    el: '#app',
    data:{
        message : "hello world"
    }
})
  1. webpack .config.js添加 resolve
const path = require('path');

module.exports = {
    entry: './src/main.js',
    output: {
        filename: 'Bundle.js',
        path: path.resolve(__dirname, 'dist'),
    },
    resolve: {
        alias: {
            'vue$': 'vue/dist/vue.esm.js'
        }

    }
};

08 plugin

vue-template 源码

程序的入口?

  1. 程序启动的命令为:
vue-cli-server serve
  1. vue-cli-server 为 基于 webpack-dev-server 的构建的服务器, 在 vue.config.js的 devServer项中配置

  • babel:

vue-cli

https://cli.vuejs.org/guide/cli-service.html

https://cli.vuejs.org/guide/cli-service.html
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值