当前位置:   article > 正文

vue2.0

vue2.0

 Vue是一套用于构建用户界面的渐进式JavaScript框架。

渐进式:Vue可以自底向上逐层的应用;

简单应用:只需要一个轻量小巧的核心库;

复杂应用:可以引入各式各样的Vue插件;

Vue特点:

1、采用组件化模式,提高复用率,更利于维护;

2、声明式编码,让编码人员无需直接操作DOM,提高效率;

Vue开发环境搭建:

安装上对应vue的扩展,在导入vue.js后,阻止弹出一个安装版本提示。

  1. <script>
  2. Vue.config.productionTip = false;
  3. </script>

Vue小案例——hello

小结:1、想让Vue工作,必须创建一个Vue实例,且要传入一个配置对象;

        2、root容器里的代码依然符合html规范,只不过混入了一些特殊的Vue语法;

        3、root容器里的代码被称为:VUE模板(vue模板只能使用实例化的vue对象中的数据);

        4、Vue实例和容器是一一对应的;

        5、真是开发中只有一个Vue实例,并且会配合组件一起使用;

        6、{{***}}中的参数要写js表达式,且参数可以自动读取到data中所有属性;

        7、一旦data中的数据发生改变,则模板中的用刀该数据的地方会自动更新;

容器里边可以使用实例之外的参数属性,但是可以使用表达式;

1、表达式:一个表达式会产生一个值,可以放在任何一个需要值的地方;

例如:a、a+b、demo(1)、x===y?'a':'b'

2、js语句

实例:1、if(){}

        2、for(){}

(注意:区分js表达式js代码

  1. <body>
  2. <div id = "root">
  3. <h1>Hello,{{name}}<h1>
  4. </div>
  5. <script type = "text/javascript">
  6. Vue.config.productionTip = false; //阻止Vue在启动后产生提示;
  7. new Vue({
  8. el:'#root'; //指定当前Vue实例为哪个容器服务,值通常为css选择器字符串;
  9. data:{
  10. name:"尚硅谷"; //data中用于存储数据,数据el所指定的容器去使用
  11. }
  12. })
  13. </script>
  14. </body>

一个容器里边只能对应一个实例的参数:一对一关系;

  1. <body>
  2. <div id = "root1">
  3. <h1>hello,{{name}},{{address}}</h1>
  4. </div>
  5. <div id = "root2">
  6. <h1>hello,{{name}},{{address}}</h1>
  7. </div>
  8. <script type = 'text/javascript'>
  9. Vue.config.productionTip = false;
  10. new Vue({
  11. el:'#root1',
  12. data:{
  13. name:'姓名',
  14. address:'地址';
  15. }
  16. })
  17. new Vue({
  18. el:'#root2';
  19. data:{
  20. name:'尚硅谷',
  21. address:'地址';
  22. }
  23. })
  24. </script>
  25. </body>

Vue模板语法

指令语法:

v-bind:"v-"(Vue的特有的指令方式),为绑定的意思,这个指定可以简化为:" "

小结:

1、差值语法:

功能:用于解析标签体内容;

 写法:{{***}}是js表达式,且可以直接读取到data中的所有属性;

2、指令语法:

功能:用于解析标签(包括:标签属性、标签内容、绑定事件...)

举例:v-bind:href='***'或简写为 :href='***' ,***同样要写js表达式,且可以直接读取到data中的所有属性。

备注:Vue中很多指定,形式都是以:v-???

  1. <body>
  2. <div id = "root">
  3. <h1>差值语法</h1>
  4. <h3>你好,{{name}}</h3> //读取是jack
  5. <hr/>
  6. <h1>指令语法</h1>
  7. <a v-bind:href="school.url.toUpperCase()">学习vue框架,名字{{school.name}}</a> //输出的是“尚硅谷”
  8. </div>
  9. </body>
  10. <script>
  11. Vue.config.productionTip = false; //阻止vue启动时弹出的生产提示
  12. new Vue({
  13. el:'#root',
  14. data:{
  15. name:'jack',
  16. school:{
  17. name:'尚硅谷',
  18. url:'http://www.baidu.com',
  19. }
  20. }
  21. })
  22. </script>

执行结果是:

 Vue——数据绑定

Vue中有2种数据绑定方式:

        1、单向绑定(v-bind):数据只能从data流向页面;

        2、双向绑定(v-model):数据不仅可以从data流向页面,还可以从页面流向data;

                备注:

                        (1)双向绑定一般都应用在表单元素上(如:input,select等);

                        (2)v-model:value 可以简写为v-model,因此v-model默认收集的就是value值;

  1. <body>
  2. <div id="root">
  3. 单向数据绑定:<input type = 'text' v-bind:value='name'><br/>
  4. 双向数据绑定:<input type = 'text' v-model:value='name'><br/>
  5. </div>
  6. </body>
  7. <script type='text/javascript'>
  8. Vue.config.productionTip=false;
  9. new Vue({
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷'
  13. }
  14. })
  15. </script>

 简写:

  1. <body>
  2. <div id="root">
  3. 单向数据绑定:<input type = 'text' :value='name'><br/>
  4. 双向数据绑定:<input type = 'text' v-model='name'><br/>
  5. </div>
  6. </body>

el 和 data 的两种写法:

一、el的两种写法:

(1)、el:"#root";

(2)、v.$mount("#root");

  1. <body>
  2. <div id="root">
  3. 单向数据绑定:<input type = 'text' v-bind:value='name'><br/>
  4. 双向数据绑定:<input type = 'text' v-model:value='name'><br/>
  5. </div>
  6. </body>
  7. <script type='text/javascript'>
  8. Vue.config.productionTip=false;
  9. const v = new Vue({
  10. // el:'#root',第一种写法
  11. data:{
  12. name:'尚硅谷'
  13. }
  14. })
  15. ocnsole.log(v);
  16. v.$mount("#root"); //第二种写法
  17. </script>

二、data的两种写法

data的第一种写法:对象式

  1. <body>
  2. <div id="root">
  3. 单向数据绑定:<input type = 'text' v-bind:value='name'><br/>
  4. 双向数据绑定:<input type = 'text' v-model:value='name'><br/>
  5. </div>
  6. </body>
  7. <script type='text/javascript'>
  8. Vue.config.productionTip=false;
  9. new Vue({
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷',
  13. age:'20'
  14. }
  15. })
  16. </script>

第二种写法:函数式

console.log(this);指向的是Vue对象;

  1. <body>
  2. <div id="root">
  3. 单向数据绑定:<input type = 'text' v-bind:value='name'><br/>
  4. 双向数据绑定:<input type = 'text' v-model:value='name'><br/>
  5. </div>
  6. </body>
  7. <script type='text/javascript'>
  8. Vue.config.productionTip=false;
  9. new Vue({
  10. el:'#root',
  11. data:function(){
  12. return{
  13. name:'尚硅谷',
  14. age:'20'
  15. }
  16. }
  17. })
  18. </script>

小结:

el有两种写法:

        1、new Vue时候配置el属性。(1)、el:"#root";

        2、先创建Vue实例,随后再通过"实例".$mount('#root')指定el的值。(2)、v.$mount("#root");

data的两种写法:

        1、对象式;

        2、函数式;

(学习组件时只能有函数式)

(注:Vue管理的函数,一定不能使用箭头函数,因为箭头函数this指向Window)

Vue——MVVM模型

1、M:模型(Model):对应data中的数据;

2、V:视图(View):模板;

3、VM:视图模型(ViewModel):Vue的实例对象;

 

Vue——数据代理

语法:Object.defineProperty(obj,prop,descriptor)

参数一:必须,目标对象;

参数二:必须,需要定义或修改的属性的名字;

参数三:必须,目标属性所拥有的特性——(1、这个属性用大括号括起来{};2、value设置属性的值,默认为underfined; 3、writetable是否可以重写(默认false); 4、enumerable目标属性是否可以被枚举(默认false); 5、configurable目标属性是否可以被删除或再次修改descriptor的这几个特性(默认false));

  1. <body>
  2. <script>
  3. let number = 18;
  4. let person = {
  5. name:'姓名',
  6. sex:'性别',
  7. }
  8. Object.defineProperty(person,'age',{
  9. get:function(){
  10. console.log("有人读取数据");
  11. return number;
  12. },
  13. set:function(value){
  14. console.log("有人修改了age属性值为:",value);
  15. number = value;
  16. }
  17. })
  18. console.log(person );
  19. </script>
  20. </body>

可以将get:function(){}set:function()进行简化:

  1. <body>
  2. <script>
  3. let number = 18
  4. let person = {
  5. name:'张三',
  6. sex:'男',
  7. }
  8. Object.defineProperty(person,'age',{
  9. get(){
  10. console.log("有人读取了age属性");
  11. return number;
  12. },
  13. set(value){
  14. console.log("修改了age属性,值:",value);
  15. number = value;
  16. }
  17. })
  18. </script>
  19. </body>

数据代理:示例通过一个对象代理对另一个对象中属性的操作(读/写)

  1. <body>
  2. <script>
  3. let obj = {x:100};
  4. let obj2 = {y:200};
  5. Object.defineProperty('obj2','x',{
  6. get(){
  7. console.log("读取属性");
  8. return obj.x;
  9. }
  10. set(value){
  11. console.log("修改属性");
  12. obj.x = value;
  13. }
  14. })
  15. </script>
  16. </body>

Vue中的数据代理

小结:

1、Vue中数据代理:通过vm对象来代理data对象中属性的操作(读/写);
2、Vue中数据代理的好处:更方便操作data中的数据;

3、基本原理:通过Object.defineProperty()把data对象中所有属性添加到vm上。为每一个添加到vm上的属性,都指定一个getter、setter。在getter、setter内部去操作(读/写)data中对应的属性。

  1. <body>
  2. <div id="root">
  3. <h2>学校名称+{{name}}</h2>
  4. <h2>学校地址+{{address}}</h2>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config=productionTip=false;
  9. const vm =new Vue({
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷',
  13. address:'科技园'
  14. }
  15. })
  16. </script>

 Vue——事件处理

 小结:1、使用v-on:***@xxx绑定事件,其中xxx是事件名;

        2、事件的回调需要配置在methods对象中,最终会在vm中;

        3、methods中配置的函数,不要使用箭头函数!否则this就不指向vm了;

        4、methods中配置的函数,都是被Vue所管理的函数,this的指向是vm或组件实例对象;

        5、@click=‘demo’ @click="demo($event)"效果一样,但后者可以传参;

(event:目标对象)

  1. <body>
  2. <div id ='root'>
  3. <h2>欢迎来到{{name}}学习</h2>
  4. <button v-on:click='showInfo'>点击提示信息</button>
  5. </div>
  6. </body>
  7. <script type="text/javascript">
  8. Vue.config.productionTip= false; //阻止Vue弹出生成提示;
  9. const vm = new Vue(
  10. el:"#root",
  11. data:{
  12. name:'尚硅谷'
  13. },
  14. methods:{
  15. showInfo(event){
  16. console.log(event);
  17. alert("同学你好");
  18. }
  19. showInfo(number,$event){
  20. console.log($event);
  21. console.log(number);
  22. }
  23. }
  24. )
  25. </script>

Vue——事件修饰符

Vue中的事件修饰符:

1、prevent,阻止默认事件(preventDefault)

  1. <body>
  2. <div id="root">
  3. <h2>欢迎来到{{name}}学习</h2>
  4. <a href="http://www.baidu.com" @click.prevent="showInfo">点击提示信息</a>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false; //阻止提示vue生成提示
  9. new Vue(
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷',
  13. },
  14. methods:{
  15. showInfo(e){
  16. //e.preventDefault();
  17. alert(同学你好);
  18. }
  19. }
  20. )
  21. </script>

2、stop,阻止事件冒泡;

  1. <body>
  2. <div id='root'>
  3. <h2>欢迎来到{{name}}</h2>
  4. <div class='demo1' @click='showInfo'>
  5. <div class="demo2" @click.stop="showInfo">点击弹出信息</div>
  6. </div>
  7. </div>
  8. </body>
  9. <script>
  10. Vue.config.productionTip=false;
  11. new Vue(
  12. el:'#root',
  13. data:{
  14. name:"尚硅谷"
  15. }
  16. methods:{
  17. showInfo(){
  18. alert("弹出信息");
  19. }
  20. }
  21. )
  22. </script>

3、once,事件只触发一次;

  1. <body>
  2. <div id="root">
  3. <h2></h2>
  4. <a href='http://www.baidu.com'@click.prevent='showInfo'>点击提示信息</a>
  5. <button @click.once='showInfo'>点击提示信息<>
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. new Vue({
  11. el:'#root',
  12. data:{
  13. name:'尚硅谷',
  14. }
  15. })
  16. </script>

4、capture,使用事件的描述模式;

再捕获阶段直接处理,先执行1,再执行2;

  1. <body>
  2. <div id='root'>
  3. <div @click.capture='showInfo'>点击提示信息1
  4. <div @click=showInfo>点击提示信息2</div>
  5. </div>
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. new Vue({
  11. el:'#root',
  12. data:{
  13. name:'尚硅谷',
  14. }
  15. })
  16. </script>

5、self,只有event.target是当前操作的元素时才触发事件;

6、passive:事件的默认行为立刻执行,无需等待事件回调执行完毕;

wheel为鼠标滚轮滚动事件;

scroll是滚动条滚动事件;

使用wheel时,若不使用passive命令则会等循环执行完后再滚动默认行为;使用后则会立刻执行,通知循环也执行。

  1. <body>
  2. <ul @wheel.passive='demo' class='list'>
  3. <li>1</li>
  4. <li>2</li>
  5. <li>3</li>
  6. </ul>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. new Vue({
  11. el:'#root',
  12. data:{
  13. name:'尚硅谷'
  14. }
  15. methods:{
  16. demo(){
  17. for(let i =0;i<1000;i++){
  18. console.log('#');
  19. }
  20. console.log('打印完了');
  21. }
  22. }
  23. })
  24. </script>

Vue——键盘事件

1、Vue中常用的按键别名:

回车= >enter                                                                     上= >up

删除= >delete(捕获“删除”和“退格”)                           下= >down

退出= >esc                                                                        左= >left

换行= >tab (特殊,必须配合keydown去使用)        右= >right

2、Vue未提供别名的按键,可以使用按键原始的key值去绑定,但要注意把组合单词变为这种形式:caps-locks;

3、系统修饰键(用法特殊):ctrl、alt、shift、meta

        (1)需要配合keyup使用,按下修饰键的同时,再按下其他键,随后释放其他键,时间被触发;

         (2)配合keydown使用,正常触发事件。

4、也可以使用keyCode去指定具体按键(不推荐);

5、可以自定义按 键名:Vue.config.keyCodes.自动以键名=键码,可以去定制按键别名

  1. <body>
  2. <div id='root'>
  3. <h2>欢迎来到{{name}}学习</h2>
  4. <input type='text'placeholder='按下回车提示输入'@keydown.enter='showInfo'>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. new Vue({
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷',
  13. }
  14. methods:{
  15. showInfo(e){
  16. console.log(e.keyCode);
  17. }
  18. }
  19. })
  20. </script>

 事件总结:

事件修饰符后边可以跟其他的修饰符:

  1. <body>
  2. <div>
  3. <a href='http://www.baidu.com' @click.stop.prevent='showInfo'>点击提示信息</a>
  4. </div>
  5. </body>

系统修饰键后边可以跟具体的键:

  1. <body>
  2. <h2></h2>
  3. <input type="text" placeholder="按下回车提示输入" @keyup.ctrl.y="showInfo">
  4. </body>

姓名案例:

只要data中数据发生变化就会重新执行,解析模板。

  1. <body>
  2. <div id="root">
  3. 姓:<input type="text" v-model="firstName"><br/>
  4. 名:<input type="text" v-model="lastName"><br/>
  5. 全称:<span>{{fullName()}}</span> //加上括号在方法中表示调用方法的执行结果;在声明事件时,加不加括号都可以。
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. new vue({
  11. el:'#root',
  12. data:{
  13. firstName:'张',
  14. lastName:'三'
  15. },
  16. methods:{
  17. fullName(){ //普通函数在Vue中的this指向Vue实例
  18. return this.firstName+'-'+this.lastName;
  19. }
  20. }
  21. })
  22. </script>

 Vue——计算属性(computed)

小结:

1、定义:要用的属性不存在,要通过已有的属性计算得出;

2、原理:底层借助了Object.defineproperty方法提供的getter和setter;

3、get函数什么时候执行?

        (1)初次读取时会执行一次;

        (2)当依赖的数据发生改变时会被再次调用;

4、优势:与methods相比,内部会有缓存机制(复用)效率高,调试方便;

5、备注:

        (1)计算属性最终会出现在vm上,直接读取使用即可;

        (2)如果计算属性要修改,那必须写set函数去相应修改,且set中要引起计算时依赖的数据的变化;

  1. <body>
  2. <div id="root">
  3. 姓:<input type="text" v-model="firstName"><br/>
  4. 名:<input type="text" v-model="lastName"><br/>
  5. 全名:<span>{{fullName}}</span>
  6. 全名:<span>{{fullName}}</span>
  7. </div>
  8. </body>
  9. <script>
  10. Vue.config.productionTip=false;
  11. const vm= new Vue({
  12. el:'#root',
  13. data:{
  14. firstName:'张',
  15. lastName:'三'
  16. },
  17. computed:{
  18. //通过计算得的数据给fullName
  19. fullName:{
  20. //get作用:当获取了fullName时,get就会调用,且返回值作为fullName值;
  21. // get什么时候调用? 1.当初次调用fullName时;2、所依赖的数据发生变化时;
  22. get(){
  23. console.log("get被调用了");
  24. return this.firstName+'-'+this.lastName;
  25. },
  26. set(value){
  27. console.log("set被调用");
  28. const arr = value.split('-'); //通过split()方法分隔字符串
  29. this.firstName = arr[0];
  30. this.lastName= arr[1];
  31. }
  32. }
  33. }
  34. })
  35. </script>

以上代码的获取数据的简写:(只读取不修改时才能使用)

把通过return返回的结果的值,交给fullName这个中。

  1. <body>
  2. <div id="root">
  3. 姓:<input type='text'v-model="firstName"><br/>
  4. 名:<input type='text'v-model="lastName"><br/>
  5. 全名:<span>{{fullName}}</span>
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. new Vue({
  11. el:'#root',
  12. data:{
  13. firstName:'张',
  14. lastName:'三'
  15. },
  16. computed:{
  17. fullName(){ //相当于get方法
  18. console.log("调用函数")
  19. return this.firstName +'-'+ this.lastName
  20. }
  21. }
  22. })
  23. </script>

天气案例:

  1. <body>
  2. <div>
  3. <h2>今天天气很{{info}}</h2>
  4. <button @click="changeWeather">切换天气</button>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. conset vm= new Vue({
  10. el:'#root',
  11. data:{
  12. isHot:true,
  13. },
  14. computed:{
  15. info(){
  16. return this.isHot?'炎热':'凉爽';
  17. }
  18. },
  19. methods:{
  20. changeWeather(){
  21. this.isHot=!isHot;
  22. }
  23. }
  24. })
  25. </script>

在vue模板中可以在事件类型后边写简单的语句:

  1. <body>
  2. <div>
  3. <button @click='isHot=!isHot'></button>
  4. </div>
  5. </body>

监视属性(watch):

 小结:1、当监视的属性发生变化时,回调函数自动调用,进行相关操作;

2、监视的属性必须存在,才能进行监视;

3、监视的两种写法:

        (1)new Vue 时传入watch配置;(在写代码时就确定监视哪个属性时使用)

         (2)通过Vue实例化的vm.$watch坚持;(没有提前知道要具体监视哪个属性时)

  1. <body>
  2. <div>
  3. <h2>今天天气很{{info}}</h2>
  4. <button @click="changeWeather">切换天气</button>
  5. </div>
  6. </body>
  7. <script type="text/javascript">
  8. Vue.config.productionTip=false;
  9. const vm = new Vue({
  10. el:'#root',
  11. data:{
  12. isHot:true,
  13. },
  14. computed:{
  15. info:{
  16. return isHot?'炎热''凉爽';
  17. }
  18. },
  19. methods:{
  20. changeWeather(){
  21. this.isHot=!isHot;
  22. }
  23. }
  24. 知道具体监视那个属性时
  25. watch:{ //监视方法
  26. isHot:{ //创建对象并传递值;
  27. immediate:true,
  28. handler(newValue,oldValue){
  29. console.log('isHot被修改了',newValue,oldValue);
  30. }
  31. }
  32. }
  33. })
  34. -------------------------------------
  35. 不知道具体监视那个属性时可以使用这个
  36. vm.$watch('isHot',{ //创建配置对象
  37. immediate:true, //初始化时就调用(默认为false)
  38. handler(newValue,oldValue){
  39. console.log('isHot被修改了',newValue,oldValue);
  40. })
  41. </script>

深度监视:

        (1)Vue中的watch默认不监测对象内部值的改变(看一层)

        (2)配置deep:true可以监测对象内部值的改变(多层)

备注:

        (1)Vue自身可以监测对象内部值的改变,但Vue提供的watch默认不可以(false);

        (2)使用watch时根据数据的具体结构,决定是否采用深度监视;

  1. <body>
  2. <div id="root">
  3. <h3>a的值是{{a}}</h3>
  4. <button @click="numbers.a++">点击加一</button>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. const vm = new Vue({
  10. el:'#root',
  11. data:{
  12. numbers:{
  13. a=1,
  14. b=1
  15. }
  16. },
  17. watch:{
  18. //监视多级结构中,某个属性的变化;
  19. "number.a":{
  20. handler(){
  21. console.log("a已经改变了");
  22. }
  23. }
  24. -------------------
  25. number:{
  26. deep:true,
  27. handler(){
  28. console.log("内部有一个被改变了");
  29. }
  30. }
  31. }
  32. })
  33. </script>

简写方式:

方式一:通过new Vue时

  1. <script>
  2. Vue.config.productionTip=false;
  3. const vm = new Vue({
  4. el:'root',
  5. data:{
  6. number:{
  7. a=1,
  8. b=1
  9. }
  10. },
  11. watch:{
  12. number(newValue,oldValue){
  13. console.log('number被修改了',newValue,oldValue);
  14. }
  15. }
  16. })
  17. </script>

 方式二:通过实例化vm.$watch()方式

  1. <script>
  2. Vue.config.productionTip=false;
  3. const vm = new Vue({
  4. el:'root',
  5. data:{
  6. number:{
  7. a=1,
  8. b=2
  9. }
  10. },
  11. })
  12. vm.$watch('number',(newValue,oldValue)={
  13. console.log("number中的值被改变了",newValue,oldValue);
  14. })
  15. </script>

computed和watch之间的区别:

        一、computed能完成的功能,watch都可以完成;

        二、watch能完成的功能,computed不一定能完成;(例如:定时器异步任务;)

两个重要的原则:

        (1)所以被Vue管理的函数,最好写成普通函数,这样this所指向的才是vm或组件实例对象;

        (2)所有不被vue管理的函数(定时器,Ajax回调函数,promise回调函数),最好使用箭头函数,这样可以使得this指向vm 实例或者组件实例。

姓名案例(computed写法):

  1. <body>
  2. <div id='root'>
  3. 姓:<input type='text' v-model="firstName"><br/>
  4. 名:<input type='text' v-model="lastName"><br/>
  5. 全名:<span>{{fullName}}</span>
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip =false;
  10. const vm = new Vue({
  11. el"#root",
  12. data:{
  13. firstName:'张',
  14. lastName:'三'
  15. },
  16. computed:{
  17. fullName(){
  18. console.log('get被调用了');
  19. return this.firstName + '-' + this.lastName;
  20. }
  21. }
  22. ])
  23. </script>

例如姓名案例(watch写法):

  1. <body>
  2. <div id='root'>
  3. 姓:<input type='text' v-model="firstName"><br/>
  4. 名:<input type='text' v-model="lastName"><br/>
  5. 全名:<span>{{fullName}}</span>
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. const vm=new Vue({
  11. el:'#root',
  12. data:{
  13. firstName:'张',
  14. lastName:'三',
  15. fullName:'张-三'
  16. },
  17. watch:{
  18. firstName(fName){
  19. setTimeout(()=>{
  20. console.log(this); //此时函数为箭头函数,没有具体指向,往外边找,
  21. //外边为普通函数,所以指向Vm实例了
  22. this.fullName=fName + '-' + this.lastName;
  23. },1000)
  24. },
  25. lastName(lname){
  26. this.fullName=this.firstName + '-' + lname;
  27. }
  28. }
  29. })
  30. </script>

Vue——绑定class样式

 方式一字符串写法,适用于:样式的类名不确定,需要动态指定。

  1. <body>
  2. <div id="root">
  3. <div class="basic" :class="mood" @click="changeMood">{{name}}</div>
  4. </div>
  5. </body>
  6. <script type="text/javascript">
  7. Vue.config.productionTip=false;
  8. new Vue({
  9. el:'#root',
  10. data:{
  11. name:'尚硅谷',
  12. mood:'normal' //动态指定样式为:normal
  13. },
  14. methods:{
  15. changeMood:{
  16. this.mood='happy'; //指定Vue对象,点击时切换样式为happy
  17. }
  18. }
  19. --------------------------------------------------
  20. methods:{
  21. changeMod(){
  22. const arr = ['happy','sad','normal']
  23. const indes = Math.floor(Math.random()*3)
  24. this.mood= arr[indes]
  25. }
  26. }
  27. })
  28. </script>

方式二 数组写法,适用于:要绑定的样式个数不确定,名字也不确定.

  1. <body>
  2. <div id="root">
  3. <div class="basic" :class="classArr">{{name}}</div>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip=false;
  8. const vm= new Vue({
  9. el:'#root',
  10. data:{
  11. name:'尚硅谷',
  12. classArr:['atguigu1','atguigu2','atguigu3']
  13. },
  14. })
  15. </script>

 方式三对象对法,适用于:要绑定的样式的个数确定,名字也确定,但要动态决定用不用。

  1. <body>
  2. <div id="root">
  3. <div class="basic" :class="classObj">{{name}}</div>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip=false;
  8. const vm = new Vue({
  9. el:'尚硅谷',
  10. data:{
  11. name:'',
  12. classObj:{ //定义一个对象,里边包含样式是否使用
  13. red:true,
  14. blue:false
  15. }
  16. }
  17. })
  18. </script>

Vue样式——style绑定

(1)Style对象样式:

  1. <body>
  2. <div id="root">
  3. <div class='basic' :style:'styleObj'>{{name}}</div>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip=false;
  8. conse vm=new Vue({
  9. el:'#root',
  10. data:{
  11. styleOby:{
  12. fontSize:'50px',
  13. color:'red'
  14. }
  15. }
  16. })
  17. </script>

(2)style数组绑定样式

  1. <body>
  2. <div id="root">
  3. <div class="basic" :style="styleArr">{{name}}</div>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip=false;
  8. const vm=new Vue({
  9. el:'#root',
  10. data:{
  11. name:'尚硅谷',
  12. styleArr:[
  13. {
  14. fontSize:'50px',
  15. color:'red'
  16. },
  17. {
  18. backgroundColor:'blue'
  19. }
  20. ]
  21. }
  22. })
  23. </script>

Vue——添加样式小结:

 1、class样式:

        写法:class="***",***可以是字符串,数组和对象。

        字符串方式适用于:类名不确定,要动态获取;

        对象写法适用于:要绑定多个样式,名气不确定,个数也不确定;

        数组方式适用于:要绑定多个样式,名字确定,个数确定,但不确定是否使用;

2、style样式

        :style="{fontSize:***}",其中***是动态的;

        :style="[a,b]",其中a,b是样式对象; 

 Vue技术——渲染

一、使用v-show做条件渲染

      (1)为true时显示,为false时隐藏(在结构中不消失);

      (2)当表达式为true时显示,否则隐藏;

  1. <body>
  2. <div id='root'>
  3. <h2 v-show='false'></h2>
  4. <h2 v-show="1===1"></h2>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. const vm=new Vue({
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷',
  13. }
  14. })
  15. </script>

二、使用v-if做条件渲染

 此时v-if如果是假值则隐藏,且执行后结构中也看不到;

  1. <body>
  2. <div id="root">
  3. <h2>当前值为:{{n}}</h2>
  4. <button @click="n++">点击加1</button>
  5. <div v-if='false'>隐藏,结构中也看不到</div>
  6. <div v-if="n===1">等于一时显示</div>
  7. </div>
  8. </body>
  9. <script>
  10. Vue.config.productionTip=false;
  11. const vm = new Vue({
  12. el:'#root',
  13. data:{
  14. name:'尚硅谷'
  15. }
  16. })
  17. </script>

三、使用v-if...,v-else-if....判断做渲染

这样判断样式,只执行其中符合的一个,成功后则退出;

  1. <body>
  2. <div id="root">
  3. <h2>当前值为:{{n}}</h2>
  4. <button @click="n++">点击n加一</button>
  5. <div v-if="n===1">等于一显示</div>
  6. <div v-else-if="n===2">等于二时显示</div>
  7. </div>
  8. </body>
  9. <script>
  10. Vue.config.productionTip=false;
  11. const vm= new Vue({
  12. el:'#root',
  13. data:{
  14. name:'尚硅谷'
  15. }
  16. })
  17. </script>

 v-if...可以和template一起使用,可以让符合条件的执行语句并且不会影响结构。

  1. <body>
  2. <div id="root">
  3. <h2>当前值为:{{n}}</h2>
  4. <button @click="n++">点击n加一</button>
  5. <div v-if="n===1">等于一显示</div>
  6. <template v-if="n===2">
  7. <h2>显示</h2>
  8. <h2>显示</h2>
  9. </template>
  10. </div>
  11. </body>
  12. <script>
  13. Vue.config.productionTip=false;
  14. const vm= new Vue({
  15. el:'#root',
  16. data:{
  17. name:'尚硅谷'
  18. }
  19. })
  20. </script>

条件渲染小结:

1、v-if...写法:

        (1)v-if="表达式"

        (2)v-else-if="表达式";

         (3)v-else="表达式"

适用于:切换频率比较低的场景。

特点:不展示的DOM元素直接移除;

注意:v-if  可以和 v-else-if 、v-else 一起使用,但必须中间不能有其他结构打断;

2、v-show写法:

        v-show="表达式";

  适用于:切换频率比较高的场景;

   特点:不展示的DOM元素仅仅是看不到;

3、注意:使用v-if 时候,元素可能无法获取;但是使用v-show一定可以获取;

Vue列表渲染

通过v-for遍历渲染数组

  1. <body>
  2. <div id='root'>
  3. <ul>
  4. <li v-for="p in person" :key="p.id"> //当vue中使用v-for时,要使用唯一的标识
  5. // key="p.id"
  6. {{p.name}}--{{p.age}}
  7. </li>
  8. ----------------------------
  9. //前边形参可以使用两个参数 ,第一个代表得到的数据,第二个是索引值
  10. <li v-for="(p,index) in persons" :key="p.id/index">
  11. {{p.value}}----{{p.index}}
  12. </li>
  13. </ul>
  14. </div>
  15. </body>
  16. <script>
  17. Vue.config.productionTip=false;
  18. const vm = new Vue({
  19. el:'#root',
  20. data:{
  21. person:[
  22. {id:'01',name:'张三',age:20},
  23. {id:'02',name:'李四',age:18},
  24. {id:'03',name:'王五',age:25}
  25. ]
  26. }
  27. })
  28. </script>

通过v-for遍历对象数据

"a"位置参数表示数据值,(key:value)中的value;

"b"位置参数表示数据键,(key:value)中的key;

  1. <body>
  2. <div id="root">
  3. <h2>汽车信息</h2>
  4. <ul>
  5. <li v-for="(a,b)in car" :key="b">
  6. {{b}}--{{a}}
  7. //输出结果为:name--红旗
  8. //price--20
  9. //color:黑色
  10. </li>
  11. </ul>
  12. </div>
  13. </body>
  14. <script>
  15. Vue.config.productionTip=false;
  16. const vm = new Vue({
  17. el:'#root',
  18. data:{
  19. car:{
  20. name:'红旗',
  21. price:'20',
  22. color:'黑色'
  23. }
  24. }
  25. })
  26. </script>

v-for遍历字符串

  1. <body>
  2. <div id="root">
  3. <h2>汽车信息</h2>
  4. <ul>
  5. <li v-for="(char,index)in car" :key="index">
  6. {{char}}--{{index}}
  7. //输出结果为:h--0,e--1这样的
  8. </li>
  9. </ul>
  10. </div>
  11. </body>
  12. <script>
  13. Vue.config.productionTip=false;
  14. const vm = new Vue({
  15. el:'#root',
  16. data:{
  17. str:'hello'
  18. }
  19. })
  20. </script>

v-for小结:

1、用于列表数据;

2、语法:v-for="(item,index) in ***" :key="某个唯一值"

3、可以遍历:数组,对象、字符串(少)、指定次数(很少);

 Vue——key作用与原理

一、当使用inde作为key时,或者不加key值时:

  1. <body>
  2. <div id="root">
  3. <h2>人员编标遍历</h2>
  4. <button @click.once="add">添加一个信息</button>
  5. <ul>
  6. <li v-for="(p,index) of persons" :key="index">
  7. {{p.name}}--{{p.age}}
  8. </li>
  9. <li></li>
  10. </ul>
  11. </div>
  12. </body>
  13. <script>
  14. Vue.config.productionTip=false;
  15. const vm= new Vue({
  16. el:'#root',
  17. data:{
  18. person:[
  19. {id:'001',name:'张三',age:20},
  20. {id:'002',name:'李四',age:18},
  21. {id:'003',name:'王五',age:25},
  22. ]
  23. },
  24. methods:{
  25. add(){
  26. const p = {id:'004','新信息',24}
  27. this.persons.unshift(p);
  28. }
  29. }
  30. })
  31. </script>

执行结果为:

 执行的原理:

二、当遍历列表用id作为key时:

  1. <body>
  2. <div id="root">
  3. <h2>人员编标遍历</h2>
  4. <button @click.once="add">添加一个信息</button>
  5. <ul>
  6. <li v-for="(p,index) of persons" :key="p.id">
  7. {{p.name}}--{{p.age}}
  8. </li>
  9. <li></li>
  10. </ul>
  11. </div>
  12. </body>
  13. <script>
  14. Vue.config.productionTip=false;
  15. const vm= new Vue({
  16. el:'#root',
  17. data:{
  18. person:[
  19. {id:'001',name:'张三',age:20},
  20. {id:'002',name:'李四',age:18},
  21. {id:'003',name:'王五',age:25},
  22. ]
  23. },
  24. methods:{
  25. add(){
  26. const p = {id:'004','新信息',24}
  27. this.persons.unshift(p);
  28. }
  29. }
  30. })
  31. </script>

执行结果为:

 执行原理为:

 key原理与作用小结:

(面试题:react、vue中key的作用,内部原理)

一、虚拟DOM中key的作用:

        key是虚拟DOM对象的表示,当数据发生变化时,Vue会根据【新数据】生成【新的虚拟DOM】,随后Vue进行【新虚拟DOM】与【旧虚拟DOM】的对比;

        比较规则:

        1、旧虚拟DOM中如果找到了与新虚拟DOM中相同的key:

                        (1)、若虚拟DOM中内容没变,直接使用之前的真是DOM;

                        (2)、若虚拟DOM中内容变了,则生成新的真实DOM,随后替换之前页面中的真 是DOM。

        2、旧虚拟DOM中未找到与新虚拟DOM相同的key:创建新的真实DOM,随后渲染到页面中。

二、用index作为key时:

        1、若对数据进行逆序添加、逆序删除等破坏顺序的操作:会产生没有必要的真实DOM更新===》界面效果没问题,但效率低;

        2、如果结构中包括输出类DOM,会产生错误的DOM更新===》界面有问题;

三、开发中的如果选择:

        1、最好使用每条数据中唯一的值作为唯一标识key,比如id,手机号等;

        2、如果不存在对数据进行逆序添加、删除等破坏顺序的操作,仅用于渲染列表用于展示,使用index(索引)作为key也可以。

Vue列表过滤

一、通过数据监视实现:

  1. <body>
  2. <div id='root'>
  3. <h2>过滤列表</h2>
  4. <input type='text' placeholder="请输入信息" v-model="keyWords">
  5. <ul>
  6. <li v-for="(p,index)of filPerons" :key="index">
  7. {{p.name}}--{{p.age}}
  8. </li>
  9. </ul>
  10. </div>
  11. </body>
  12. <script type='text/javascript'>
  13. Vue.config.productionTip=false;
  14. const vm = new Vue({
  15. el:'#root',
  16. data:{
  17. keyWords:'',
  18. persons:[
  19. {id:'001',name:'冬天',age:18},
  20. {id:'002',name:'立冬',age:25},
  21. {id:'003',name:'立春',age:20}
  22. ],
  23. filPerons:[]
  24. },
  25. watch:{ //监视完全写法
  26. keyWords:{
  27. immediate:true,
  28. handler(val){
  29. this.filPerons = this.persons.filter((p)=>{
  30. return p.name.indexOf(val) !==-1
  31. })
  32. }
  33. }
  34. }
  35. })
  36. </script>

二、通过数据计算:

  1. <body>
  2. <div id='root'>
  3. <h2>过滤列表</h2>
  4. <input type='text' placeholder="请输入信息" v-model="keyWords">
  5. <ul>
  6. <li v-for="(p,index)of filPersons" :key="index">
  7. {{p.name}}--{{p.age}}
  8. </li>
  9. </ul>
  10. </div>
  11. </body>
  12. <script type='text/javascript'>
  13. Vue.config.productionTip=false;
  14. const vm = new Vue({
  15. el:'#root',
  16. data:{
  17. keyWords:'',
  18. persons:[
  19. {id:'001',name:'冬天',age:18},
  20. {id:'002',name:'立冬',age:25},
  21. {id:'003',name:'立春',age:20}
  22. ]
  23. },
  24. computed:{
  25. filPersons(){
  26. return this.persons.filter((p)=>{
  27. return p.name.indexOf(this.keyWords) !==-1
  28. }
  29. })
  30. }
  31. })
  32. </script>

vue——列表排序:

arr.sort( (a,b) => {  });

数组排序,a-b为升序;b-a为降序;

  1. <body>
  2. <div id='root'>
  3. <h2>过滤列表</h2>
  4. <input type='text' placeholder="请输入信息" v-model="keyWords">
  5. <button>年龄升序</button>
  6. <button>年龄降序</button>
  7. <button>原顺序</button>
  8. <ul>
  9. <li v-for="(p,index)of filPersons" :key="index">
  10. {{p.name}}--{{p.age}}
  11. </li>
  12. </ul>
  13. </div>
  14. </body>
  15. <script type='text/javascript'>
  16. Vue.config.productionTip=false;
  17. const vm = new Vue({
  18. el:'#root',
  19. data:{
  20. keyWords:'',
  21. sortType:0, //0代表原顺序,1代表升序,2代表降序
  22. persons:[
  23. {id:'001',name:'冬天',age:18},
  24. {id:'002',name:'立冬',age:25},
  25. {id:'003',name:'立春',age:20}
  26. ],
  27. filPerons:[]
  28. },
  29. computed:{
  30. filPersons(){
  31. const arr = this.persons.filter((p)=>{
  32. return p.name.indexOf(this.keyWords) !==-1
  33. }
  34. if(this.sortType !== 0){
  35. arr.sort((a,b)=>{
  36. return this.sortType ===1 ? a.age - b.age : b.age-a.age
  37. })
  38. }
  39. return arr;
  40. })
  41. }
  42. })
  43. </script>

  

 Vue——检测数据

  1. <body>
  2. <div id="root">
  3. <h2>学生信息</h2>
  4. <button @click='student.age++'>年龄加一</button>
  5. <button @click="addSex">添加性别属性。默认值:男</button>
  6. <button @click="student.sex='未知'">修改性别</button>
  7. <button @click="addFriend">在列表首位添加一个朋友</button>
  8. <button @click="updataFriend">修改第一个朋友的名字:张三</button>
  9. <button @click="addHobby">添加一个爱好</button>
  10. <button @click="updataHobby">修改第一个爱好者:开车</button>
  11. <h3>姓名:{{student.name}}</h3>
  12. <h3>年龄:{{student.age}}</h3>
  13. <h3 v-if:"student.sex">性别:{{student.sex}}</h3>
  14. <h3>爱好:{{student.hobby}}</h3>
  15. <ul>
  16. <li v-for="(h,index) in student.hobby" :key="index">{{h}}</li>
  17. </ul>
  18. <h3>朋友们:</h3>
  19. <ul>
  20. <li v-for="(f,index) in student.friends" :key="index">
  21. {{f.name}}--{{f.age}}
  22. </li>
  23. </ul>
  24. </div>
  25. </body>
  26. <script>
  27. Vue.config.productionTip=false;
  28. conse vm= new Vue({
  29. el:'#root',
  30. data:{
  31. student:{
  32. name:'tom',
  33. age:20,
  34. hobby:["游泳","看书","敲代码"],
  35. friends:[
  36. {name:'jerry',age:18},
  37. {name:'andi',age:20}
  38. ]
  39. }
  40. },
  41. methods:{
  42. addSex(){
  43. vue.set(this.student,'sex','男') //或者 vm.$set(this.student,'sex','女');
  44. },
  45. addFriend(){
  46. this.student.friends.unshift({name:'aaa',age:25})
  47. },
  48. updataFriend(){
  49. this.student.friends[0].name="jack";
  50. this.student.friends[0].age=16;
  51. },
  52. addHobby(){
  53. this.student.hobby.push('学习');
  54. },
  55. updataHobby(){
  56. this.sdudent.hobby.splice(0,1,"开车")
  57. ----------------------------------
  58. vue.set(this.student.hobby,0,"开车");
  59. -----------------------------------
  60. vm.$set(this.student.hobby,0,"开车");
  61. }
  62. }
  63. })
  64. </script>

一、Vue会监视data中的所有层次的数据。

Vue检测数据的原理——对象

二、通过setter实现监视,且要在new.Vue时就传入要检测的数据:

        (1)对象中后追加的属性,Vue默认不做响应式处理;

        (2)如需要给后添加的属性做响应式,需要使用如下API:

  1. Vue.set(target, properyName/index, value)
  2. 目标 追加的属性 追加属性的值
  3. 或者:
  4. vm.$set(target, propertyName/index, value);

 注意:Vue.set() 和 vm.$set() 不能修改vm 或者 vm的根数据对象添加属性!!

Vue检测数据的原理——数组

三、通过包裹数组更新元素的方法实现,本质就做了两件事:

        (1)调用原生对应的方法对数组进行更新;

        (2)重新解析模板,进而更新页面;

  1. <script>
  2. Vue.config.productionTip=false;
  3. const vm = new Vue({
  4. el:'#root',
  5. data:{
  6. persons:[
  7. {id:'001',name:'张三',age:20,sex:'女'},
  8. {id:'002',name:'王五',age:22,sex:'男'},
  9. {id:'003',name:'李四',age:18,sex:'女'},
  10. ]
  11. },
  12. methods:{
  13. upda(){
  14. this.persons.splice(0,1,{id:'001',name:'学习',age:25,sex:'男'})
  15. }
  16. }
  17. })
  18. </script>

 也可以这样使用:

 

在Vue修改数组中的某个元素一定要用到如下方法:

        (1)、使用这些API:push()、pop()、shift()、unshift()、splice()、sort()、 reverse();

        (2)、Vue.set() 或者 vm.$set();

Vue——表单数据收集

  1. <body>
  2. <div id="root">
  3. <form @submit.prevent="demo"> //阻止默认提交行为,
  4. 账号:<input type='text' v-model.trim="user"><br/>
  5. 密码:<input type='password' v-model.trim="password"><br/>
  6. 年龄:<input type="number" v-model.number="age"><br/>
  7. 性别:
  8. 男:<input type="radio" name="sex" v-model="man" value="man"><br/>
  9. 女:<input type="radio" name="sex" v-model="woman" value="woman"><br/>
  10. 爱好:
  11. 学习<input type="checkbox" v-model="hobby" value="stydy"><br/>
  12. 游戏<input type="checkbox" v-model="hobby" value="game"><br/>
  13. 看书<input type="checkbox" v-model="hobby" value="readbook"><br/>
  14. 所属校区
  15. <select v-model="city">
  16. <option value="">请选择校区</option>
  17. <option value="beijing">北京</option>
  18. <option value="shanghai">上海</option>
  19. <option value="shenzhen">深圳</option>
  20. <option value="wuhan">武汉</option>
  21. <option value="tianjin">天津</option>
  22. </select>
  23. 其他信息<textarea v-model.lazy="other"></textarea>
  24. <input type="checkbox" v-model="agree">阅读并接收用户协议<a href="https://www.baidu.com">用户协议</a>
  25. <button>提交</button>
  26. </form>
  27. </div>
  28. </body>
  29. <script>
  30. Vue.config.productionTip=false;
  31. const vm = new Vue({
  32. el:'#root',
  33. data:{
  34. user:'',
  35. password:'',
  36. sex:'man',
  37. hobby:[],
  38. city:'beijing',
  39. other:'',
  40. agree:'',
  41. },
  42. methods:{
  43. demo:{
  44. console.log(this._data); //方式一
  45. ---------------------
  46. // console.log(JSON.stringify(this.userInfo)); 此方式需要把信息放入一个
  47. userInfo对象里边,并需要在全部的v-model前边加userInfo前缀;
  48. }
  49. }
  50. })
  51. </script>

收集表单小结:

       若:<input type="text"/>,则v-model收集的是value值,用户输入的就是value值。

        若:<input type="radio"/>,则v-model收集的是value值,且要给标签配置value值。

        若:<input type="checkbox"> 

                        1、没有配置Input的value属性,那么收集的就是checked(勾选或者未勾选,true或false)

                        2、配置Input的value属性:

                                        (1)v-model的初始值是非数组,那么收集的就是checked值(true或false)

                                           (2)v-model的初始值是数组,那么收集的就是value组成的数据;

备注:v-model的三个修饰符:

        (1)lazy:失去焦点收集数据;

        (2)Number:输入字符串转为有效数字(一般type="number" v-model.number同时出现)

        (3)trim:输入的首位空格过滤;

Vue——过滤器

方式一:计算属性方式和构造方法(局部)

  1. <body>
  2. <div id="root">
  3. <h2>显示格式化后的时间</h2>
  4. <h3>现在是:{{fmtTime}}</h3>
  5. <h3>现在是:{{getFmtTime()}}</h3>
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. const vm = new Vue({
  11. el:'#root',
  12. data:{
  13. time:1621561277603
  14. },
  15. computed:{ //计算属性方式
  16. fmtTime(){
  17. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss') //返回调用dayjs方法
  18. }
  19. },
  20. methods:{
  21. getFmtTime(){
  22. return dayjs(this.time).format('YYYY-MM-DD HH:mm:ss') //返回调用dayjs方法
  23. }
  24. }
  25. })
  26. </script>

方式二:过滤器方式(局部)

  1. <body>
  2. <div id="root">
  3. //不包含参数的过滤器
  4. <h3>现在是:{{time | timeFormater}}</h3>
  5. ---------------------------------------
  6. //有参数的过滤器
  7. <h3>现在是{{time | timeFormater('YYYY_MM_DD')}}</h3>
  8. </div>
  9. </body>
  10. <script>
  11. Vue.config.productionTip=false;
  12. const vm = new Vue({
  13. el:'#root',
  14. data:{
  15. time:1621561277603
  16. },
  17. filters:{
  18. timeFormater(value,str='YYYY-MM-DD HH:mm:ss'){ //如果传递的是不包含参数的使用后边的参数,如果传递的包含参数则使用传递的
  19. return dayjs(value).format(str); //format计划,设计
  20. }
  21. }
  22. --------------------------------------------
  23. filters:{
  24. timerFormater(value){
  25. return dayjs(value).format('yyyy年mm月dd日 hh:mm:ss')
  26. }
  27. }
  28. })
  29. </script>

多个过滤器联动(局部)

  1. <body>
  2. <div id="root">
  3. //不包含参数的过滤器
  4. <h3>现在是:{{time | timeFormater}}</h3>
  5. ---------------------------------------
  6. //有参数的过滤器
  7. <h3>现在是{{time | timeFormater('YYYY_MM_DD') | mySlice}}</h3>
  8. </div>
  9. </body>
  10. <script>
  11. Vue.config.productionTip=false;
  12. const vm = new Vue({
  13. el:'#root',
  14. data:{
  15. time:1621561277603
  16. },
  17. filters:{
  18. timeFormater(value,str='YYYY-MM-DD HH:mm:ss'){ //如果传递的是不包含参数的使用后边的参数,如果传递的包含参数则使用传递的
  19. return dayjs(value).format(str);
  20. },
  21. mySiice(value){
  22. return value.slice(0,4) //从得到的值从截取四个长度
  23. }
  24. }
  25. })
  26. </script>

全局过滤器:

  1. <body>
  2. <div id="root">
  3. //不包含参数的过滤器
  4. <h3>现在是:{{time | timeFormater}}</h3>
  5. ---------------------------------------
  6. //有参数的过滤器
  7. <h3>现在是{{time | timeFormater('YYYY_MM_DD')}}</h3>
  8. </div>
  9. //模拟使用全局过滤器
  10. <div id='root2'>
  11. <h2>{{msg | mySlice}}</h2>
  12. </div>
  13. </body>
  14. <script>
  15. Vue.config.productionTip=false;
  16. //声明全局过滤器
  17. Vue.filter('mySlice',function(value){
  18. return value.slice(0,4)
  19. })
  20. const vm = new Vue({
  21. el:'#root',
  22. data:{
  23. time:1621561277603
  24. },
  25. filters:{
  26. timeFormater(value,str='YYYY-MM-DD HH:mm:ss'){ //如果传递的是不包含参数的使用后边的参数,如果传递的包含参数则使用传递的
  27. return dayjs(value).format(str);
  28. },
  29. mySlice(value){
  30. return value.slice(0,4)
  31. }
  32. }
  33. })
  34. new Vue({
  35. el:'#root2',
  36. data:{
  37. msg:'hello,word'
  38. },
  39. mySiice(value){
  40. return value.slice(0,4) //从得到的值从截取四个长度
  41. }
  42. })
  43. </script>

 过滤器小结:

定义:对要显示的数据进行特定的格式化后再显示(使用一些简单的处理)。

语法:

        (1)注册过滤器:Vue.filter(name,callback)new Vue { filters:{  }  }

            (2)使用过滤器:{{xxx  |  过滤器名称}或者  v-bind: 属性=" xxx  |   过滤器名称  "

    两种用法:    一、 用在差值语法中;                    二、   v-bind中

 备注:

        (1)过滤器可以接收额外参数、多个过滤器可以串联;

        (2)并不会改变原来数据,而是产生新的对应的数据;

Vue——内置指令

我们之前学过的指令:

        v-bind:单向数据绑定,可简写"";

        v-model: 双向数据绑定;

        v-for:遍历数组/对象/字符串;

        v-on:绑定事件监听,可简写为:@;

        v-if:条件渲染(动态控制节点是否存在;)

        v-else: 条件渲染(动态控制节点是否存在)

        v-show:条件渲染(动态控制节点是否存在)

v-text指令:

  1. <body>
  2. <div id= "root">
  3. <div>{{name}}</div>
  4. <div v-text="name">被替换</div> //v-text中的内容会替换到节点中内容
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip='false';
  9. const vm = new Vue({
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷',
  13. str:'你好啊'
  14. }
  15. })
  16. </script>

1、作用:向其所在的节点中渲染文本的内容。

2、与差值语法不同的是:v-text会替换到节点中的内容;差值语法{{ }}不会;

内置指令——v-html

  1. <body>
  2. <div id="root">
  3. <div v-html="str"><>
  4. <div v-html="str2"></div>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. const vm = new Vue({
  10. el:'#root',
  11. data:{
  12. name:'尚硅谷',
  13. str2:'<h3>你好</h3>',
  14. }
  15. })
  16. </script>

小结:

v-html指令:

        1、作用:向指定的节点中渲染包含HTML结构的内容;

        2、与差值语法区别:

                        (1)v-html会替换掉节点中所有的内容,{{  }}不会;

                        (2)v-html可以识别HTML结构;

        3、注意:

        (1)在网站上动态渲染任意HTML是非常危险的,容易被XSS共计;

        (2)一定要在可信的内容上使用v-html(永远不要用在用户提交的内容上)

 v-clock指令

五秒钟之前不显示结构,五秒钟后显示调用Vue.js 完成后的样式。

  1. <head>
  2. <style>
  3. [v-cloak]{ //属性选择器,选择所有的v-cloak属性
  4. display:none
  5. }
  6. </style>
  7. </head>
  8. <body>
  9. <div id="root">
  10. <h2 v-clock>{{name}}</h2>
  11. </div>
  12. <script type="text/javascript" src="https:www.baidu.com/resours/5s/vue.js">五秒钟后执</script>
  13. </body>
  14. <script>
  15. Vue.config.productionTip=false;
  16. const vm = new Vue({
  17. el:'#root';
  18. data:{
  19. name:'尚硅谷'
  20. }
  21. })
  22. </script>

小结:

v-cloak指令(没有值):

        1、本质是一个特殊属性,Vue实例创建完毕并接管容器后,会删除v-cloak属性;

        2、使用css配合v-cloak可以解决网速慢时页面展示{{  **}}的问题;

v-once指令:

小结:

        (1)v-once所在节点在初次动态渲染后,就视为静态内容了。

        (2)以后的数据的改变不会引起v-once所在结构的更新,可以用于优化性能

  1. <body>
  2. <div id="root">
  3. <h2 v-once>初始化值{{n}}</h2>
  4. <h2>初始值是:{{n}}</h2>
  5. <button @click="add">点击加1</button>
  6. </div>
  7. </body>
  8. <script>
  9. Vue.config.productionTip=false;
  10. const vm = new Vue({
  11. el:'#root',
  12. data:{
  13. n:1
  14. },
  15. methods:{
  16. add(){
  17. return this.n++;
  18. }
  19. }
  20. })
  21. </script>

v-pre指令:

  1. <body>
  2. <div id="root">
  3. <h2 v-pre>vue很简单</h2>
  4. <button>使用v-pre后跳过h2的编译过程</button>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. const vm = new Vue({
  10. el:'#root',
  11. data:{
  12. n:1;
  13. }
  14. })
  15. </script>

小结:

v-pre指令:(1)可以跳过所在节点的编译过程; 

                (2)可利用它跳过:没有使用指令语法、没有使用差值语法的节点,会加快编译;

 vue自定义属性

(自定义指令明不需要加“v-”)

方式一:函数式

  1. <body>
  2. <div id="root">
  3. <h2>{{name}}</h2>
  4. <h2>当前值是:<span v-text='n'></span></h2>
  5. <h2>放大十倍:<span v-big='n'></span></h2>
  6. <button @click="n++">点击加1</button>
  7. </div>
  8. </body>
  9. <script>
  10. Vue.config.productionTip=false
  11. onst vm = new Vue({
  12. el:'#root',
  13. data:{
  14. name:'尚硅谷',
  15. n:1
  16. },
  17. directives:{
  18. big(element,binding){
  19. console.log('big');
  20. element.innerText = binding.value *10;
  21. }
  22. }
  23. })
  24. </script>

big函数何时被调用时何时被调用?

(1)指令与元素成功绑定时(一上来);

(2)指令所在的模板被重新解析时。

方式二:对象式

  1. <body>
  2. <div id ="root">
  3. <h2>{{name}}</h2>
  4. <h2>当前n的值是:<span v-text="n"></span></h2>
  5. <h2>放大后n的值是:<span v-big="n"></span></h2>
  6. <button>点击增加</button>
  7. <input type = "text" v-fbind:value="n">
  8. </div>
  9. </body>
  10. <script>
  11. Vue.config.productionTip=false;
  12. const vm= new Vue({
  13. el:'#root',
  14. data:{
  15. name:'尚硅谷',
  16. n:1
  17. },
  18. directives:{
  19. big:(element,binding){ //简写方式,相当于只执行了指令与元素成功绑定的步骤,和,指令所在被重新解析时;这两
  20. element.innerText = binding.value*10;
  21. },
  22. fbind:{ //对象方式调用
  23. bind(element,binding){ //指令与元素成功绑定时(一上来);
  24. element.value=binding.value;
  25. },
  26. inserted(element,binding){ //指令所在元素被插入页面时;
  27. element.focus();
  28. },
  29. update(element,binding){ //指令所在的模板被重新解析时;
  30. element.value=binding.value;
  31. }
  32. }
  33. }
  34. })
  35. </script>

Vue——自定义语法小结:

一、定义语法

(1)局部指令

    对象式:    new Vue({

        directives:{"指令名字":"配置对象"}         

})

函数式:

        new Vue({

        directives("指令名:回调函数"){

        }        

  })

(2)全局指令

Vue.directive(指令名,配置对象)

或:

Vue.directive(指令名,回调函数)

二、配置对象中常用的3个回调

        (1)bind:指令与元素成功绑定时调用;

        (2)inserted:指令所在元素被插入页面时调用        

        (3)update:指令所在模板结构贝重新解析时调用;

三、备注

指令定义时不加"v-",但使用时要加"v-"

指令明如果是多个单词,要使用kebab-case命名方式。

自定义指令this指向问题:this指向的是window

自定义指令多个单词组成的用"-"分隔,同时要用完全写法;

  1. <body>
  2. <div id="root">
  3. <h2>当前的n的值是:<span v-text='n'></span></h2>
  4. <h2>放大十倍后是:<span v-big-number="n"></span></h2>
  5. <button @click="n++"></button>
  6. <br/>
  7. <input type='text' v-fbind:value="v">
  8. </div>
  9. </body>
  10. <script>
  11. Vue.config.productionTip=flase;
  12. const vm = new Vue({
  13. el:"#root",
  14. data:{
  15. name='尚硅谷',
  16. n:1
  17. },
  18. directives:{
  19. 'big-nameber'(element,binding){
  20. //如果自定义名字有多个单词组成,用“-”符号隔开,则如要原写法;
  21. element.innerText = binding.value * 10;
  22. },
  23. fbind:{
  24. bind(element,binding){
  25. console.log("fbind-bind",this)
  26. element.value = binding.value;
  27. },
  28. inserted(element,binding){
  29. console.log("fbind-inserted",this);
  30. element.focus();
  31. },
  32. update(){
  33. console.log("fbind-update",this)
  34. //上述三个自定义指令中this指window
  35. element.value=binding.value;
  36. }
  37. }
  38. }
  39. })
  40. </script>

定义全局指令时:

  1. <body>
  2. <div id="root">
  3. <h2>当前的n的值是:<span v-text='n'></span></h2>
  4. <h2>放大十倍后是:<span v-big-number="n"></span></h2>
  5. <button @click="n++"></button>
  6. <br/>
  7. <input type='text' v-fbind:value="v">
  8. </div>
  9. </body>
  10. <script>
  11. Vue.config.productionTip=flase;
  12. Vue.directive('fbind',{
  13. bind(element,binding){
  14. console.log("fbind-bind",this)
  15. element.value = binding.value;
  16. },
  17. inserted(element,binding){
  18. console.log("fbind-inserted",this);
  19. element.focus();
  20. },
  21. update(){
  22. console.log("fbind-update",this)
  23. //上述三个自定义指令中this指window
  24. element.value=binding.value;
  25. }
  26. })
  27. const vm = new Vue({
  28. el:'#root',
  29. data:{
  30. name:'尚硅谷',
  31. }
  32. })
  33. </script>

Vue——生命周期

引出:生命周期

小结:

(1)生命周期又称为:生命周期回调函数、生命周期函数、生命周期钩子;

(2)作用:Vue在关键时刻帮我们调用一些特殊名称的函数

(3)生命周期函数的名字不可更改,但函数的具体内容是程序员根据需求编写的;

(4)生命周期函数中的this指向的是Vm或组件实例对象

  1. <body>
  2. <div id="root">
  3. <h2 v-if="a">你好</h2>
  4. <h2 :style="{opacity}">欢迎学习Vue</h2>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. const vm = new Vue({
  10. el:'#root',
  11. data:{
  12. a:false,
  13. opacity:1
  14. },
  15. //Vue完成模板的解析后并把初始的真是DOM元素放入界面后(挂载完毕)调用mounted
  16. mounted(){
  17. console.log("执行了生命周期函数");
  18. setInterval(()=>{
  19. this.opacity -=0.01
  20. if(this.opacity <=0) this.opacity=1
  21. },1000)
  22. },
  23. })
  24. </script>

 Vue——生命周期挂载流程

(1组)创建(beforeCreate  、create)

(2组)挂载(beforeMounted、mounted):发送Ajax请求、启动定时器、绑定自定义事件等【初始化操作】

(3组)更新(beforeUpdate、update)

(4组)销毁(beforeDestory、destory):清除定时器、解绑自定义事件、取消订阅等【收尾工作】

 

 使用清除定时器方式

  1. <body>
  2. <div id="root">
  3. <h2 :style="{opacity}">欢迎学习,字体颜色变换</h2>
  4. <button @click="stop">点击停止变化</button>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. const vm = new Vue({
  10. el:'root',
  11. data:{
  12. opacity:1
  13. },
  14. methods:{
  15. stop(){
  16. clearInterval(this.timer);
  17. }
  18. },
  19. mounted(){
  20. console.log('mounted',this)
  21. this.timer = setInterval(()=>{
  22. this.opacity -=0.01
  23. if(this.opacity) <=0 this.opacity=1
  24. },15)
  25. }
  26. })
  27. </script>

使用销毁声明周期方式

  1. <body>
  2. <div id="root">
  3. <h2 :style="{opacity}">欢迎学习,字体颜色变换</h2>
  4. <button @click="stop">点击停止变化</button>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productiontip=false;
  9. const vm = new Vue({
  10. el:'#root',
  11. data:{
  12. opacity:1
  13. },
  14. methods:{
  15. stop(){
  16. this.$destroy() //点击销毁生命周期
  17. }
  18. },
  19. mounted(){ //生命周期——挂载
  20. console.log('mounted',this)
  21. this.timer = setInterval(()=>{
  22. console.log('setInterval')
  23. this.opacity -=0.01
  24. if(this.opacity <=0) this.opacity =1
  25. },15)
  26. },
  27. beforeDestory(){ //生命周期——销毁之前
  28. console.log("销毁之前")
  29. clearInterval(this.timer)
  30. }
  31. })
  32. </script>

  小结:

 一、常用的生命周期钩子:

        (1)mounted:发送Ajax请求,启动定时器、绑定自定义事件、订阅消息等【初始化操作】

        (2)beforedestroy:清楚定时器、解绑自定义事件、取消订阅消息等【收尾工作】

二、关于销毁Vue实例:

        (1)、销毁后借助Vue开发者工具看不到任何消息;

        (2)、销毁后自定义事件会失效,但看原生DOM事件依然有效;

        (3)、一般不会再beforeDestroy操作数据,因为即使操作数据,也不会再触发更多新流程了。

Vue——组件

一、对组件的理解

定义:实现应用中局部功能代码和资源集合

二、非单文件组件

创建局部组件:

  1. <body>
  2. <div id="root">
  3. <h1></h1>
  4. //第三步:编写组件标签
  5. <hr/>
  6. <xuexiao></xuexiao>
  7. <hr/>
  8. <xuesheng></xuesheng>
  9. </div>
  10. <div id="root2">
  11. <hello></hello>
  12. </div>
  13. </body>
  14. <script>
  15. Vue.config.productionTip=false;
  16. 第一步:创建组件
  17. const schools = Vue.extend({ //组件定义不能有el配置项,最所有组件都要被一个vm管理
  18. template:`
  19. <div>
  20. <h2>学校名称:{{schoolName}}</h2>
  21. <h2>学校地址:{{address}}</h2>
  22. <button @click="al">点击弹出名称</button>
  23. </div>
  24. `,
  25. data(){
  26. return{
  27. schoolName:'尚硅谷',
  28. address:'北京'
  29. }
  30. }
  31. }),
  32. const students = Vue.extend({
  33. template:`{
  34. <h2>学生名字{{studentName}}</h2>
  35. <h2>学生年龄{{age}}</h2>
  36. }`
  37. data(){
  38. return{
  39. studentName:'小红',
  40. age:'18'
  41. }
  42. }
  43. }),
  44. const vm = new Vue({
  45. el:'#root',
  46. 第二步:注册组件
  47. components:{ //注册组件们
  48. xuexiao : schools, //key:value 定义最终的组件名字
  49. xuesheng : students
  50. }
  51. })
  52. <script>

创建全局组件:

  1. <body>
  2. <div id="root2">
  3. <hel></hel>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip=false;
  8. const hello = Vue.extend({ //第一步创建组件
  9. template:`
  10. <div>
  11. <h2>你好,注册全局组件{{name}}</h2>
  12. </div>
  13. `,
  14. data(){
  15. return{
  16. name:'Tom',
  17. }
  18. }
  19. }),
  20. Vue.component("hel",hello)
  21. const vm = new Vue({
  22. el:'#root2',
  23. })
  24. </script>

小结:

Vue中使用组件的三个步骤:

        (1)定义组件;

 

        (2)注册组件;

全局注册:                                                局部注册:

        

        (3)使用组件(写组件的标签)

(一)、如果定义一个组件:

        使用Vue.extend(options组件名)创建,其中optionsnew Vue(options)时传入的那个options几乎一样,但也有点区别:

        区别如下

        1、el配置不要写——最终所有的组件都要经过一个vm的管理,由vm中的el决定服务哪个容器。

        2、data必须写成函数——避免组件被复用时,数据存在引用关系。

备注:使用template可以配置组件结构。

二、如果注册组件: 

(1)局部组件:靠new Vue的时候传入components选项;

(2)全局注册:靠Vue.component(“组件名”,组件)

 三、编写组件标签:

        1、<school></school>

定义组件的几个注意点:

  1. <body>
  2. <div id="root">
  3. <h2>{{msg}}</h2>
  4. //编写组件标签
  5. //组件标签方式一
  6. <xuexiao><xuexiao>
  7. //组件标签写法方式二
  8. <xuexioa/>
  9. </div>
  10. </body>
  11. <script>
  12. Vue.config.productionTip=false;
  13. //定义组件
  14. const s = Vue.extend({
  15. name:'vue开发者工具',
  16. template:`
  17. <div>
  18. <span>定义组件{{name}}</span>
  19. </div>
  20. `,
  21. data(){
  22. return {
  23. name:'组件的参数'
  24. }
  25. }
  26. })
  27. const vm = new Vue({
  28. el:'#root',
  29. data:{
  30. msg:'欢迎学习Vue'
  31. },
  32. //注册组件
  33. components:{
  34. xuexiao:s //接收从组件传递的值
  35. }
  36. })
  37. </script>

一、关于组件名——一个单词组成

        第一种写法(首字母小写):school

        第二种写法(首字母大写):School

        关于组件名——多个单词组成:

        第一种写法(kebab-case命名):my-school

        第二种写法(CameCase命名):MySchool(需要Vue脚手架支持

备注:(1)组件命名尽可能回避HTML中已有的元素名称,例如:h2、H2都不行。

            (2)可以使用name配置项指定组件在开发者工具中呈现的名字。

二、关于组件标签:

        第一种写法:<school></school>

        第二种写法:<school/>

备注:不使用脚手架时,第二种方式可能会导致后序组件不能渲染。

三、一个简写方式:

const school = Vue.extend(options)可简写为:const school = options

 Vue——组件的嵌套

  1. <body>
  2. <div id="root">
  3. <school></school>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip=false;
  8. const student = Vue.extend({
  9. name:'student',
  10. template:`
  11. <div>
  12. <h2>姓名{{name}}</h2>
  13. <h2>年龄{{age}}</h2>
  14. </div>
  15. `,
  16. data(){
  17. return{
  18. name:'张三',
  19. age:25
  20. }
  21. }
  22. }),
  23. const school= Vue.extend({
  24. name:'school',
  25. template:`
  26. <div>
  27. <h2>学校姓名{{name}}</h2>
  28. <h2>学生数量{{number}}</h2>
  29. <student></student>
  30. </div>
  31. `,
  32. data(){
  33. return{
  34. name:'尚硅谷',
  35. number:100
  36. }
  37. },
  38. components:{
  39. student
  40. }
  41. }),
  42. new Vue({
  43. el:'#root',
  44. components:{
  45. school;
  46. }
  47. })
  48. </script>

 App合并

  1. <body>
  2. <div id="root">
  3. <app></app>
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip=false;
  8. const student = Vue.extend({
  9. name:'Student',
  10. template:`
  11. <div>
  12. <h2>学生姓名{{name}}</h2>
  13. </div>
  14. `,
  15. data(){
  16. return{
  17. name:'张三'
  18. }
  19. }
  20. }),
  21. const school = Vue.extend({
  22. name:'School',
  23. template:`
  24. <div>
  25. <h2>学校名称:{{name}}</h2>
  26. <h2>学校地址:{{address}}</h2>
  27. <student></student>
  28. </div>
  29. `,
  30. components:{ //注册学生组件
  31. student
  32. }
  33. data(){
  34. return{
  35. name:'尚硅谷',
  36. address:'北京'
  37. }
  38. }
  39. }),
  40. const app = Vue.extend({
  41. name:'App',
  42. template:`
  43. <div>
  44. <school></school>
  45. </div>
  46. `,
  47. components:{ //注册学校组件
  48. school
  49. }
  50. }),
  51. const vm = new Vue({
  52. el:'#root',
  53. components:{
  54. app
  55. }
  56. })
  57. </script>

Vue——VueComponent构造函数

  1. <body>
  2. <div id="root">
  3. <school></school>
  4. <hello></hello>
  5. </div>
  6. </body>
  7. <script>
  8. Vue.config.productionTip=false;
  9. const school = Vue.extend({
  10. name:'school',
  11. template:`
  12. <div>
  13. <h2>学校名称{{name}}</h2>
  14. <button @click='showName'>点击弹出名称</button>
  15. </div>
  16. `,
  17. data(){
  18. return{
  19. name:'尚硅谷'
  20. }
  21. },
  22. methods:{ //定义一个方法,弹出当前对象,当前对象this指向VueComponent
  23. showName(){
  24. alert(this.name);
  25. }
  26. }
  27. }),
  28. const hello = Vue.extend({
  29. name:'hello',
  30. template:`
  31. <div>
  32. <h3>与school同级的对象{{name}}</h3>
  33. </div>
  34. `,
  35. data(){
  36. return{
  37. name:'构造函数';
  38. }
  39. },
  40. })
  41. const vm = new Vue({
  42. el:'#root',
  43. data:{
  44. components:{
  45. school;
  46. hello;
  47. }
  48. }
  49. })
  50. </script>

 关于VueComponent小结:

1、school组件本质是一个名为VueComponent的构造函数,且不是程序员我们自己定义的,是Vue.extend生成的; 

2、我们只需要写<school></school>或者<school/>,Vue解析时就会帮我们创建一个school组件的实例对象;

3、特别注意:每次调用Vue.extend,返回的都是一个新的VueComponent。而不是使用同一个;

4、关于this只想问题:

        (1)组件配置中:data函数、methods中的函数、watch中的函数、computed中的函数、它们的this指向的均是【VueComponent实例的对象】

        (2)newVue(options)配置中:data函数、methods中的函数、watch中的函数、computed中的函数、它们的this指向的都是【Vue实例对象】

5、VueComponent的实例对象,简称为“VC”(组件实例对象)。Vue实例对象简称:vm

        

Vue实例和VC组件实例

因为组件时可复用的Vue实例,所以它们与new vue接收相同的选项,例如data、computed、watch、methods以及生命周期钩子等。仅有的例外是像el这样的根实例(vm)特有的选项,一个组件的data选项必须是一个函数,因此每个实例可以维护一份被返回对象的独立拷贝

  1. <body>
  2. <div id="root">
  3. <school></school> //创建组件标签
  4. </div>
  5. </body>
  6. <script>
  7. Vue.config.productionTip= false;
  8. Vue.prototype.x=99
  9. const school=Vue.extend({ //创建组件
  10. name:'school',
  11. template:`
  12. <div>
  13. <h2>学校名称{{name}}</h2>
  14. <h2>学校地址{{address}}</h2>
  15. </div>
  16. `,
  17. data(){
  18. return {
  19. name:'尚硅谷',
  20. address:'北京'
  21. }
  22. },
  23. methods:{
  24. showX(){
  25. console.log(this.x)
  26. }
  27. }
  28. })
  29. const vm = new Vue({ //创建vm实例
  30. el:'#root',
  31. data:{
  32. msg:'你好'
  33. },
  34. components:{school} //注册组件
  35. })
  36. </script>

一个重要的内置关系(原型链)

VueComponent.prototype === Vue.prototype

为什么要有这个关系:让组件实例对象(vc)可以访问到Vue原型上的属性,方法(依据原型链),如果都没找到返回null。

 Vue——单文件组件

一、声明组件

  1. <template>
  2. <div class = "demo">
  3. <h2>学校名称{{name}}</h2>
  4. <h2>学校地址{{address}}</h2>
  5. <button @click="showName">点击提示学校名称</button>
  6. </div>
  7. </template>
  8. <script>
  9. export default{
  10. name:'school',
  11. data(){
  12. return{
  13. school:'尚硅谷',
  14. address:'北京昌平'
  15. }
  16. }.
  17. methods:{
  18. showName(){
  19. alert(this.schoolName)
  20. }
  21. },
  22. }
  23. <script>
  24. <style>
  25. .deom{
  26. background-color:pink;
  27. }
  28. </style>
  1. <template>
  2. <div>
  3. <h2>学生{{name}}</h2>
  4. <h2>年龄{{age}}</h2>
  5. </div>
  6. </template>
  7. <script>
  8. export default{
  9. name:'Student',
  10. data(){
  11. return{
  12. name:'张三',
  13. age:18
  14. }
  15. }
  16. }
  17. </script>
  18. <style></style>

二、合并组件(App)

  1. <template>
  2. <div>
  3. <School></School>
  4. <Student></Student>
  5. </div>
  6. </template>
  7. <script>
  8. //引入组件
  9. import School from './School'
  10. import Student from './Student'
  11. export default{
  12. name:'App',
  13. components:{
  14. School,
  15. Student
  16. }
  17. }
  18. </script>

三、引入合并好的组件,实例化Vue实例(main.js)

  1. import App from './App.Vue'
  2. new Vue({
  3. el:'#root',
  4. template:`<App><App>`,
  5. components:{
  6. App
  7. },
  8. })

四、创建页面(index.html)引入main.js

  1. <html>
  2. <head>
  3. <title>Document</title>
  4. </head>
  5. <body>
  6. <div id="root"></div>
  7. <script type='text/javascript' src='../js/vue.js'></script>
  8. <script type="text/javascript" src="./main.js"></script>
  9. </body>
  10. </html>

Vue——创建Vue脚手架:

结构:

Vue——render函数

在main.js文件中:

一、引入的Vue是残缺的时,需要使用函数render:(  ){  return ***}

import引入的Vue文件如果是ES6模式引入,默认指向的是vue.runtime.esm.js

  1. //引入Vue
  2. import Vue from 'vue'
  3. //引入App组件,它是所有组件的父组件
  4. //import App from './App.vue'
  5. Vue.config.productionTip = false;
  6. //创建Vue实例对象——vm
  7. new Vue({
  8. el:'#app',
  9. render(createElement){
  10. return createElement('h1','创建的是<h1></h1>标签')
  11. }
  12. ----------------------------------
  13. render:h =>h(App) //参数是一个组件时,直接写组件名称
  14. })

二、引入的Vue是完整的时:

  1. <body>
  2. <div id="root">
  3. </div>
  4. </body>
  5. <script>
  6. Vue.config.productionTip =false;
  7. new Vue({
  8. el:'#root',
  9. <template>
  10. <h1>你好,引入的时完整版Vue</h1>
  11. </template>
  12. })
  13. </script>

小结:

1、vue.js与vue.runtime.xxx.js的区别

        (1)vue.js是完整版的Vue,包含:核心功能+模板解析器。

        (2)vue.runtime.xxx.js是运行时的vue,只包含:核心功能;没有模板解析器。

2、因为vue.runtime.xxx.js没有模板解析器,所以不能使用template配置项,需要使用render函数接收收到的createElement函数去指定具体内容

 Vue——脚手架修改默认配置

小结:(1)使用vue  inspect >output.js可以查看Vue脚手架的默认配置

       (2) 使用vue.config.js可以对脚手架进行个性化定制;

Vue——ref属性(School.vue)

  1. <template>
  2. <h2 v-text="msg" ref="title"><>
  3. <button ref="btn" @click="showDOM">点击输出全部DOM元素</button>
  4. <School ref="sch">
  5. </template>
  6. <script>
  7. import School from './components/School'
  8. export default{
  9. name:'App', //组件名
  10. components:{School} //组件集
  11. data(){
  12. return{
  13. msg:'欢迎学习Vue'
  14. }
  15. },
  16. methods:{
  17. showDOM(){ //点击输出真是DOM元素,通过ref操作
  18. console.log(this.$refs.title)
  19. console.log(this.$refs.btn)
  20. console.log(this.$refs.sch)
  21. }
  22. }
  23. }
  24. </script>
  25. <style></style>

ref属性小结:

(1)被用来给元素或者子组件注册引用信息(id替代者)

(2)应用在HTML标签上获取的是真实DOM元素,应用在组件标签上是组件实例对象(VC)

(3)使用方式:

打标识方式<h1 ref="xxx"></h1><School ref="xxx"></School>

获取标识:this.$refs.xxx

 Vue——props配置

配置组件:

接收到的props是不允许修改,且优先使用props传递的值。

(Student.vue)

  1. <template>
  2. <div>
  3. <h1>{{msg}}</h1>
  4. <h2>学生姓名{{name}}<h2>
  5. <h2>学生性别{{sex}}</h2>
  6. <h2>学生年龄{{age}}</h2>
  7. <button @click="updataAge">点击年龄加加</button>
  8. </div>
  9. </template>
  10. <script>
  11. export default{
  12. name:'Student',
  13. data(){
  14. console.log(this)
  15. return {
  16. msg:'我是一个学生',
  17. //this指向的值接收过来的数据
  18. MyAge:this.age //修改数据,把props传递的数据复制一个放入data中
  19. }
  20. },
  21. methods:{
  22. updateAge(){
  23. this.myAge++
  24. }
  25. },
  26. props:['name','age','sex'] //简单声明接收
  27. ----------------------------------------
  28. props:{
  29. name:String, //接收同时对数据进行类型限制
  30. age:Number,
  31. sex:String
  32. }
  33. -------------------------------------------
  34. props:{ //接收同时对数据进行类型限制+默认值指定+必要性限制
  35. name:{
  36. type:String,
  37. required:true,
  38. },
  39. age:{
  40. type:Number,
  41. default:25
  42. }
  43. sex:{
  44. type:String
  45. required:true
  46. }
  47. }
  48. }
  49. </script>

收集全部组件(app.vue)

  1. <template>
  2. <div>
  3. <student name="张三" sex="男" :age='18+1'> //传递数据
  4. </div>
  5. </template>
  6. <script>
  7. import Student from "./components/Student"
  8. export default{
  9. name:'App',
  10. components:{Student}
  11. }
  12. </script>

小结:功能是让组件接收从外部传过来的数据

(1)传递数据:<Demo name="***">

(2)接收数据:

        第一种方式:只接受props:['name']

        第二种:限制类型props:{

                                        name;String

                                        }

        第三种(限制类型、限制必要性、指定默认值)

        props:{

              name:{

              type:String,

                required:true,

                default:'张三'  

                }

        }

备注props是只读的,Vue底层会检测对props的修改,如果进行了修改,就会发出警告,若业务需求确实需要修改,那么需要复制props内容中的一个数据到data中,然后去修改data中的数据

 Vue——mixin混入(混合文件名.js)

 创建混合

  1. export const hunhe={
  2. methods:{
  3. showName(){
  4. alert(this.name)
  5. }
  6. },
  7. mounted(){ //挂载是输入你好
  8. console.log("你好啊")
  9. },
  10. }
  11. //引用混合的都会有这两个数据
  12. export const hunhe2={
  13. data(){
  14. return {
  15. x:100,
  16. y:200
  17. }
  18. }
  19. }

引入局部混合文件 

注:当引入混合文件中数据和源文件数据冲突时,以源文件数据为准;都出现挂载时,全部执行。

  1. <template>
  2. <div>
  3. <h2 @click="showName">学校名称{{name}}</h2>
  4. <h2>学校地址{{address}}</h2>
  5. </div>
  6. </template>
  7. <script>
  8. //引入混合文件
  9. import {hunhe,hunhe2} from './mixin'
  10. export default{
  11. name:'',
  12. data(){
  13. return {
  14. name:'尚硅谷',
  15. address:'北京',
  16. x:666
  17. }
  18. },
  19. mixin:[hunhe,hunhe2],
  20. mounted(){
  21. console.log("你好!!")
  22. }
  23. }
  24. <script>

全局混合:

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import {hunhe,hunhe2} from './mixin'
  4. Vue.config.productionTip = false;
  5. Vue.mixin(hunhe)
  6. Vue.mixin(hunhe2)
  7. new Vue({
  8. el:'',
  9. render:h=>h(App) //render使用残缺Vue时,使用
  10. })

mixin(混入)小结:

功能:可以吧多个组件共用的配置提取成一个混入的对象;

使用方法:第一步定义混合,例如:{ data(){***}

                                                                        methods:{**}

                                                                                }

第二步使用混入:

(1)全局混入:Vue.mixin(***)

(2)局部混入:mixin:[ ' *** ' ]

Vue——插件

定义插件(plugins.js):

  1. export default{
  2. install(Vue){
  3. Vue.filter("mySlice",function(value){ //定义全局过滤器
  4. return value.slice(0,4)
  5. }),
  6. Vue.directive('fbind',{ //定义全局指定
  7. bind(element,binding){
  8. element.value=binding.value
  9. },
  10. inserted(element,binding){
  11. element.focus()
  12. },
  13. update(element,binding){
  14. element.value=binding.value
  15. }
  16. }),
  17. Vue.mixin({ //定义全局混入
  18. data(){
  19. return {
  20. x:100,
  21. y:100
  22. }
  23. }
  24. })
  25. Vue原型对象上添加一个方法(vm和VC都能用)
  26. Vue.prototype.hello = ()=>{alert('你好!!')}
  27. }
  28. }

应用(使用)插件(main.js):

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import plugins from './plugins'
  4. Vue.config.productionTip= false
  5. Vue.use(plugins)
  6. new Vue({
  7. el:'#App',
  8. render h=>h(App)
  9. })

组件中使用插件(Student.vue): 

  1. <template>
  2. <div>
  3. <h2>学生姓名{{name}}</h2>
  4. <h2>学生性别{{sex}}</h2>
  5. </div>
  6. </template>
  7. <script>
  8. export default{
  9. name:'Student',
  10. data(){
  11. return {
  12. name:'张三',
  13. sex:'男'
  14. }
  15. },
  16. }
  17. </script>

插件小结:

功能:用于增强Vue。

本质:包含install方法的对象,install的第一个参数是Vue,第二个以后的参数是插件使用者传递的数据。

定义插件:

        对象.install = function(Vue,options){

                //添加全局过滤器

                Vue.filter(***)

        }

        //添加全局指令

        Vue.directive(***)

        //配置全局混入

        Vue.mixin(***)

        //添加实例方法

        Vue.prototype.$myMethod = function(){***}

        Vue.prototype.$myProperty = ***

Vue——scoped样式

作用:让样式在局部生效,防止冲突。

写法:<style scoped>(style后边可以跟着lang="less"或者"css"样式,但是可能需要安装less-loader)

 当两个组件样式冲突时,以引入组件的最后的那个顺序为准:

(App.vue)合并组件中

  1. <template>
  2. <div>
  3. <School/>
  4. <Student/>
  5. </div>
  6. </template>
  7. <script>
  8. import Student from './components/Student'
  9. import School from './components/School'
  10. export default{
  11. name:'App',
  12. components:{School,Student}
  13. }
  14. </script>

分组件(School.vue)

scoped:使属性仅在局部有效。

  1. <template>
  2. <div class="demo">
  3. <h2>学校名称:{{name}}</h2>
  4. <h2>学校地址:{{address}}</h2>
  5. </div>
  6. </template>
  7. <script>
  8. export default {
  9. name:'School',
  10. data(){
  11. return{
  12. name:'尚硅谷',
  13. address:'北京'
  14. }
  15. }
  16. }
  17. </script>
  18. <style scoped>
  19. .demo{
  20. background-color:pink;
  21. }
  22. </style>

 style后边可以跟着lang="less"或者"css"样式,但是可能需要安装less-loader:

  1. <template>
  2. <div class="demo">
  3. <h2>学生姓名:{{name}}</h2>
  4. <h2>学生年龄:{{age}}</h2>
  5. </div>
  6. </template>
  7. <script>
  8. name:'Student',
  9. data(){
  10. name:'张三',
  11. age:25
  12. }
  13. </script>
  14. <style lang=less scoped>
  15. .demo{
  16. background: blue;
  17. .atguigu{
  18. font-size:25px;
  19. }
  20. }
  21. </style>

 Vue—— Todo-list案例

 步骤一:实现静态组件:抽取组件,使用组件实现静态页面效果。

步骤二:展示动态数据:

        (1)数据的类型,名称是什么。

        (2)数据保存在哪个组件。

步骤三:交互——从绑定事件监听开始。·······

静态页面创建

初始化列表:

(MyList.vue)

  1. <template>
  2. <ul class ="todo-main">
  3. <MyItem v-for="todoObj in todos" :key="todoObj.id" :todo="todoObj"/>
  4. </ul>
  5. </template>
  6. <script>
  7. import MyItem from './MyItem'
  8. export default {
  9. name:'MyList',
  10. components:{MyItem},
  11. }
  12. </script>
  13. <style>
  14. </style>

 列表组件:(Myitem.vue) 

  1. <template>
  2. <li>
  3. <label>
  4. <input type="checkbox" :checked="todo.done">
  5. <span>{{todo.title}}</span>
  6. </label>
  7. </li>
  8. </template>
  9. <script>
  10. export default{
  11. name:'MyItem',
  12. props:['todo'],
  13. }
  14. </script>
  15. <style></style>

获取添加数据(Myheader.vue)

  1. <template>
  2. <div class ="todo-header">
  3. <input type="text" placeholder="请输入名称,按回车确认" v-model="title" @keyup.enter='add'/>
  4. </div>
  5. </template>
  6. <script>
  7. import {nanoid} from 'nanoid'
  8. export default{
  9. name:'MyHeader',
  10. props:["addTodo"],
  11. data(){
  12. return{
  13. title:''
  14. }
  15. }
  16. methods:{
  17. add(){
  18. //效验数据
  19. if(!this.title.trim()) return alert("请输入数据")
  20. 将用户的输入包装成一个todo对象
  21. const todoObj={id:nanoid(),title:this.title,done:false}
  22. 通知App组件去添加一个todo对象
  23. this.addTodo(todoObj)
  24. this.title=''
  25. }
  26. }
  27. }
  28. </script>
  29. <style>
  30. <style>

组件集合(App.vue):

  1. <template>
  2. <div id="root">
  3. <div class="todo-container">
  4. <div class="todo-wrap">
  5. <MyHeader :addTodo="addTodo"/>
  6. <MyList :todos="todos/">
  7. <MyFooter/>
  8. </div>
  9. </div>
  10. </div>
  11. </template>
  12. <script>
  13. import MyHeader from './components/MyHeader'
  14. import MyList from './components/MyList'
  15. import MyFooter from './components/MyFooter.vue'
  16. export default{
  17. name:'App',
  18. components:{MyHeader,MyList,MyFooter},
  19. data() {
  20. return{
  21. todos:[
  22. {id:'001',title:'吃饭',done:true},
  23. {id:'002',title:'看书',done:false},
  24. {id:'003',title:'打代码',done:true}
  25. ]
  26. }
  27. },
  28. methods:{
  29. addTodo(todoObj){
  30. this.todos.unshift(todoObj)
  31. }
  32. },
  33. }
  34. </script>
  35. <style></style>

  

 总结:TodoList案例

一、组件化编码流程:

        

本地存储:

Window.sessionStorageWindow.localStorage属性 :

Window.sessionStorage大小约为5MB;

Window.localStorage大小约为20MB;

(1、存储数据:

sessionStorage.setItem(key,value)

(2)、获取数据

sessionStorage.getItem(key,value)

(3)、删除数据

sessionStorage.removeItem(key,value)

(4)、删除所有数据

sessionStorage.clear()

Vue——自定义事件绑定

学生组件

  1. <template>
  2. <div class="student">
  3. <h2>学生姓名:{{name}}</h2>
  4. <h2>学生性别:{{sex}}</h2>
  5. <button @click="sendStudentName">把学生名给App组件</button>
  6. </div>
  7. </template>
  8. <script>
  9. export default{
  10. name:'Student',
  11. data(){
  12. return{
  13. name:'张三',
  14. sex:'男'
  15. }
  16. },
  17. methods:{
  18. sendStudentName(){
  19. this.$emit("atguigu",this.name) 触发App组件实例身上的'atguigu'事件
  20. }
  21. }
  22. }
  23. </script>
  24. <style lang="less" scoped>
  25. .demo{
  26. background-color:'pink';
  27. .atguigu{
  28. font-size:40px;
  29. }
  30. }
  31. </style>

学校组件:

  1. <template>
  2. <div class="school">
  3. <h2>学校{{name}}</h2>
  4. <h2>学校地址{{address}}</h2>
  5. <button @click="sendSchoolName">点击把学校名称给App</button>
  6. </div>
  7. </template>
  8. <script>
  9. export default{
  10. name:'School',
  11. props:['getSchoolName'], //接收从App组件中传过来的数据
  12. data(){
  13. name:'尚硅谷',
  14. address:'北京'
  15. },
  16. methods:{
  17. sendSchoolName(){
  18. this.getSchoolName(this.name)
  19. }
  20. }
  21. }
  22. </script>
  23. <style lang="less">
  24. .demo{
  25. background-color:blue;
  26. .atguigu{
  27. font-size:40px;
  28. }
  29. }
  30. </style>

App.vue组件

  1. <template>
  2. <div class="app">
  3. <h1>{{msg}}</h1>
  4. 通过父组件给子组件传递函数类型的props实现:子给父传递数据
  5. <School :getSchoolName="getSchoolName"/>
  6. 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第一个自定义写法:使用@或v-on)
  7. <Student v-on:atguigu="getStudentName"/>
  8. 通过父组件给子组件绑定一个自定义事件实现:子给父传递数据(第二种自定义写法,使用ref)
  9. <Student ref="stu"/>
  10. </div>
  11. </template>
  12. <script>
  13. import Student from"./components/Student"
  14. import School from './components/School'
  15. export default{
  16. name:'App',
  17. data(){
  18. return{
  19. msg:'你好啊'
  20. }
  21. },
  22. methods:{
  23. getSchoolNmae(name){
  24. console.log("传递参数,学校名称",name)
  25. },
  26. getStudentName(name){
  27. console.log("触发了事件",name)
  28. }
  29. },
  30. mounted(){
  31. //挂载自定义事件
  32. this.$refs.stu.$on("atguigu",this.getStudentName)
  33. //只执行一次
  34. this.$refs.stu.$once("atguigu",this.getStudentName)
  35. }
  36. }
  37. </script>
  38. <style></style>

 Vue——自定义事件解绑

 student.vue组件:

  1. <template>
  2. <div class="student">
  3. <h2>学生姓名:{{name}}</h2>
  4. <h2>学生性别:{{sex}}</h2>
  5. <button @click="sendStudentName">把学生名传递到App</button>
  6. <button @click="unbind">解绑指定事件</button>
  7. <button @click="xiaohui">点击销毁当前Student组件实例</button>
  8. </div>
  9. </template>
  10. <script>
  11. export default{
  12. name:'Student',
  13. data(){
  14. return {
  15. name:'张三',
  16. sex:'男'
  17. }
  18. },
  19. methods:{
  20. sendStudentName(){
  21. this.$emit("atguigu",this.name)
  22. this.$emit("demo")
  23. }
  24. },
  25. unbind(){
  26. this.$off('atguigu') //解绑一个自定义事件
  27. this.$off(['atguigu','demo']) //解绑多个自定义事件
  28. this.$off() //解绑多个自定义事件
  29. },
  30. xiaohui(){
  31. this.destroy() //销毁了当前Student组件的实例,销毁后所有的Student实例的自定义事件都失效
  32. }
  33. }
  34. </script>
  35. <style></style>

App.vue组件:

  1. <template>
  2. <div class="app">
  3. <h1>{{msg}}</h1>
  4. <School :getSchoolName="getSchoolName"></School>
  5. <Student @atguigu="getStudentName" @demo="m1"></Student>
  6. </div>
  7. </template>
  8. <script>
  9. import {Student} from './component/Student'
  10. import {School} from './component/School'
  11. export default{
  12. name:'App',
  13. components:{School,Student}
  14. data(){
  15. return{
  16. msg:'你好啊'
  17. }
  18. },
  19. methods:{
  20. getSchoolName(name){
  21. console.log("App收到了学校的名",name)
  22. },
  23. getStudentName(name){
  24. console.log("App收到了学生名字",name)
  25. },
  26. m1(){
  27. console.log("m1事件被调用了");
  28. }
  29. },
  30. // mounted(){
  31. // this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件
  32. // }
  33. }
  34. </script>
  35. <style></style>

Vue——自定义事件总结

一、一种组件间通信的方式,适用于:子组件===》父组件

二、使用场景:A是父组件,B是子组件,B想给A传数据,那么就要在A中给B绑定自定义事件(事件回调在A中);

三、绑定自定义事件:

        (1)第一种方式,在父组件中:

         (2)第二种方式,在父组件中:

   

         (3)若想让自定义事件只能触发一次,可以使用"once"修饰符,或者$once方法;

四、触发自定义事件:

 五、解绑自定义事件:

 六、组件上可以也可以绑定原生DOM事件,需要使用“native”修饰符。

七、注意:通过绑定自定义事件时,回调要么配置在methods中,或者用箭头函数,否则this指向会出现问题。

  1. <template>
  2. <div class="app">
  3. <h1>{{msg}} 学生姓名是:{{studentName}}</h1>
  4. <Student ref="student"/>
  5. </div>
  6. </template>
  7. <script>
  8. import Student from './components/Student'
  9. export default {
  10. name:'App',
  11. data(){
  12. return {
  13. msg:'你好啊',
  14. studentName:''
  15. }
  16. },
  17. methods:{
  18. getStudentName(name){
  19. console.log("App收到了学生名字",name)
  20. this.studentName=name
  21. },
  22. m1(){
  23. console.log("demo事件被触发了")
  24. }
  25. },
  26. mounted(){
  27. this.$refs.student.$on('atguigu',this.getStudentName) //绑定自定义事件
  28. }
  29. }
  30. </script>
  31. <style></style>

TodoList案例自定义事件:

<template></template>

Vue——全局事件总线,任意组件间通信

 创建全局事件总线:

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. Vue.config.productionTip=false;
  4. new Vue({
  5. el:'',
  6. render: h=>h(App),
  7. beforeCreate(){
  8. Vue.prototype.$bus=this //安装全局事件总线
  9. },
  10. })

兄弟组件一传递数据:

  1. <template>
  2. <div class="student">
  3. <h2>学生姓名:{{name}}</h2>
  4. <h2>学生性别:{{sex}}</h2>
  5. <button @click='sendStudentName'>点击接收School组件信息</button>
  6. </div>
  7. </template>
  8. <script>
  9. export default{
  10. name:'Student',
  11. data(){
  12. return {
  13. name:'张三',
  14. sex:'男',
  15. }
  16. },
  17. methods(){
  18. sendStudentName(){
  19. this.$bus.$emit('hello',this.name) //应用自定义事件
  20. }
  21. }
  22. }
  23. </script>
  24. <style><style>

兄弟组件——接收数据:

  1. <template>
  2. <div class="school">
  3. <h2>学校{{name}}</h2>
  4. <h2>学校地址{{address}}</h2>
  5. </div>
  6. </template>
  7. <script>
  8. export default{
  9. name:'School',
  10. data(){
  11. return{
  12. name:'尚硅谷',
  13. address:'北京'
  14. }
  15. },
  16. mounted() {
  17. this.$bus.$on('hello',(data)=>{ //设置自定义事件
  18. console.log("我是School组件,Student组件收到了数据",data)
  19. })
  20. },
  21. beforeDestory(){
  22. this.$bus.$off('hello') //解绑自定义事件
  23. }
  24. }
  25. </script>
  26. <style></style>

小结:

一、一种组件间通信的方式,适用于任意组件间通信。

二、安装全局事件总线:

三、使用事件总线:

        (1)接收数据:A组件想接收数据,则在A组件中给$bus绑定自定义事件,事件回调留在A组件自身。

写法一:

写法二:

         (2)提供数据:

 四、最好在beforeDestroy钩子中,用$off解绑当前组件所用的事件。

 TodoList案例——事件总线写法

(main.js)创建全局事件总线

  1. import Vue from 'Vue'
  2. import App from './App.vue'
  3. Vue.config.productionTip=false;
  4. new Vue({
  5. el:'#app',
  6. render:h=>(App),
  7. beforeCreate(){
  8. Vue.prototype.$bus=this
  9. },
  10. })

App.vue创建事件,接收数据

  1. <template></template>
  2. <script>
  3. import MyHeader from './components/MyHeader'
  4. import MyList from './components/MyList'
  5. import MyFooter from './components/MyFooter'
  6. export default {
  7. name:'App',
  8. components:{MyHeader,MyList,MyFooter}
  9. data(){},
  10. methods:{}
  11. watch:{},
  12. mounted(){ //挂载时,绑定全局事件总线
  13. this.$bus.$on('checkTodo',this.checkTodo)
  14. this.$bus.$on('deleteTodo',this.deleteTodo)
  15. },
  16. beforeDestroy() { //销毁事件时,解绑全局事件
  17. this.$bus.$off('checkTodo')
  18. this.$bus.$off('deleteTodo')
  19. }
  20. }
  21. </script>
  22. <style></style>

MyItem.vue触发事件,传递数据

  1. <template></template>
  2. <script>
  3. export default{
  4. name:'MyItem',
  5. props:['todo'],
  6. methods:{
  7. handleCheck(id){
  8. this.$bus.$emit('checkTodo',id)
  9. },
  10. handleDelete(id){
  11. if(confirm("确认删除吗")){
  12. this.$bus.$emit('deleteTodo',id)
  13. }
  14. }
  15. }
  16. }
  17. </script>
  18. <style></style>

Vue——消息订阅与发布

School.vue,接收数据,订阅消息

  1. <template>
  2. <div class="school">
  3. <h2>学校名称:{{name}}</h2>
  4. <h2>学校地址:{{address}}</h2>
  5. </div>
  6. </template>
  7. <script>
  8. import pubsub from 'pubsub-js'
  9. export default{
  10. name:'School',
  11. data(){
  12. return {
  13. name:'尚硅谷',
  14. address:'北京',
  15. }
  16. },
  17. mounted(){ (消息名,数据)
  18. this pubId=pubsub.subscribe('hello',(msgName,data)=>{
  19. console.log("有人发布了hello消息,执行会滴函数hello")
  20. })
  21. },
  22. beforeDestroy(){
  23. pubsub.unsubscribe(this.pubId)
  24. }
  25. }
  26. </script>
  27. <style></style>

student.vue发送数据

  1. <template>
  2. <div>学生姓名:{{name}}</div>
  3. <div>学生性别:{{sex}}</div>
  4. <button @click="sendStudentName">把学生名发送给School组件</button>
  5. </template>
  6. <script>
  7. import pubsub from 'pubsub-js'
  8. export default{
  9. name:'Student',
  10. data(){
  11. return {
  12. name:'张三',
  13. sex:'男'
  14. }
  15. },
  16. methods:{
  17. sendStudentName(){
  18. pubsub.publish('hello',"发送数据给School")
  19. }
  20. }
  21. }
  22. </script>
  23. <style></style>

消息订阅与发布(pubsub)

小结:

1、安装pubsub:

2、引入pubsub: 

3、接收数据:A组件想接收数据,则在A组件中订阅消息,订阅的回调留在A组件中

 

 写法二:

 4、提供数据:

 5、最好在beforeDestroy钩子中,用

 TodoList案例优化——消息订阅方式

App.vue

  1. import MyList from './components/MyList'
  2. import MyFooter from './components/Footer'
  3. export default{
  4. name:'App',
  5. components:{MyHeader,MyList,MyFooter},
  6. data(){},
  7. methods:{},
  8. watch:{},
  9. mounted(){
  10. this.$bus.$on('checkTodo',this.checkTodo)
  11. this.pubId=pubsub.subscribe('deleteTodo',this.deleteTodo)
  12. },
  13. beforeDestroy(){
  14. this.$bus.$off('checkTodo')
  15. pubsub.unsubscribe(this.pubId)
  16. }
  17. }

MyItem.vue

  1. import pubsub from 'pubsub-js'
  2. export default{
  3. name:'MyItem',
  4. props:['todo'],
  5. methods:{
  6. handleCheck(id){
  7. this.$bus.$emit('checkTodo',id)
  8. }
  9. },
  10. handleDelete(id){
  11. if(confirm('确定删除吗')){
  12. pubsub.publish('deleteTodo',id)
  13. }
  14. }
  15. }

 TodoList案例优化——添加编辑功能

MyItem.vue

  1. <template>
  2. <li>
  3. <label>
  4. <input type='checkbox' :checked="todo.done" @change="handleCheck(todo.id)">
  5. <span v-show="!todo.isEdit">{{todo.title}}</span>
  6. <input
  7. type="text"
  8. v-show="todo.isEdit"
  9. :value="todo.title"
  10. @blur="handleBlur(todo)">
  11. </label>
  12. <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
  13. <button v-show="!todo.isEdit" class="btn btn-edit" @click="handleEdit(todo)">编辑</button>
  14. </li>
  15. </template>
  16. <script>
  17. import pubsub from "pubsub-js"
  18. export default{
  19. name:'MyItem',
  20. props:['todo'],
  21. methods:{
  22. handleCheck(id){},
  23. handleDelete(id){},
  24. handleEdit(todo,$event){
  25. if(todo.hasOwnProperty('isEdit')){
  26. todo.isEdit =true
  27. }
  28. else{
  29. this.$set(todo,'isEdit',true)
  30. }
  31. },
  32. //失去焦点回调,(真正执行修改逻辑)
  33. handleBlur(todo,e){
  34. todo.isEdit=false
  35. if(!e.target.value.trim()) return("输入不能为空")
  36. this.$bus.$emit('updataTodo',todo.id,e.target.value)
  37. }
  38. }
  39. }
  40. </script>
  41. <style></style>

App.vue文件中

  1. <template></template>
  2. <script>
  3. import MyHeader from './components/MyHeader'
  4. import MyList from './components/MyList'
  5. import MyFooter from './components/MyFooter'
  6. export default{
  7. name:'App',
  8. components:{MyHeader,MyList,MyFooter}
  9. data(){},
  10. methods:{
  11. addTodo(todoObj){},
  12. checkTodo(id){
  13. this.todos.forEach((todo)=>{
  14. if(todo.id=id) todo.done=!todo.done
  15. })
  16. },
  17. updataTodo(id,title){
  18. this.todos.forEach((todo)=>{
  19. if(todo.id=id) todo.title=title
  20. })
  21. },
  22. deleteTodo(_,id)}{},
  23. checkAllTodo(done){},
  24. clearAllTodo(){}
  25. },
  26. mounted(){
  27. this.$bus.$on('checkTodo',this.checkTodo)
  28. this.$bus.$on('updataTodo',this.updataTodo)
  29. this.pubId=pubsub.subscribe('deleteTodo',this.deleteTodo)
  30. },
  31. beforeDestroy(){
  32. this.$bus.$off('checkTodo')
  33. this.$bus.$off('updataTodo')
  34. pubsub.unsubscribe(this.pubId)
  35. }
  36. }
  37. </script>
  38. <style></style>

Vue——$nextTick 

MyItem.vue

点击自动获取焦点:

  1. <template>
  2. <li>
  3. <label>
  4. <input type='checkbox' :checked="todo.done" @change="handleCheck(todo.id)">
  5. <span v-show="!todo.isEdit">{{todo.title}}</span>
  6. <input
  7. type="text"
  8. v-show="todo.isEdit"
  9. :value="todo.title"
  10. ref="inputTitle"
  11. @blur="handleBlur(todo)">
  12. </label>
  13. <button class="btn btn-danger" @click="handleDelete(todo.id)">删除</button>
  14. <button v-show="!todo.isEdit" class="btn btn-edit" @click="handleEdit(todo)">编辑</button>
  15. </li>
  16. </template>
  17. <script>
  18. import pubsub from "pubsub-js"
  19. export default{
  20. name:'MyItem',
  21. props:['todo'],
  22. methods:{
  23. handleCheck(id){},
  24. handleDelete(id){},
  25. handleEdit(todo,$event){
  26. if(todo.hasOwnProperty('isEdit')){
  27. todo.isEdit =true
  28. }
  29. else{
  30. this.$set(todo,'isEdit',true)
  31. },
  32. 方式一:---------------------------------------------
  33. this.$nextTick(function(){
  34. this.$refs.$inputTitle.focus()
  35. })
  36. 方式二:----------------------------------------------
  37. setTimeout({
  38. this.$refs.$inputTitle.focus()
  39. },10)
  40. },
  41. //失去焦点回调,(真正执行修改逻辑)
  42. handleBlur(todo,e){
  43. todo.isEdit=false
  44. if(!e.target.value.trim()) return("输入不能为空")
  45. this.$bus.$emit('updataTodo',todo.id,e.target.value)
  46. this.$refs.inputTitle.focus()
  47. }
  48. }
  49. }
  50. </script>
  51. <style></style>

 nextTick小结:

(1)、语法:this.%nextTick(“回调函数”)

(2)、作用:在下一次DOM更新结束后,执行其指定的回调;

(3)、什么时候用:当改变数据后,要基于更新后的新DOM进行某些操作时,要在nextTick所指定的回调函数中执行。

 Vue——动画与过度

子组件:

  1. <template>
  2. <div>
  3. <button @click="isShow = !isShow">显示/隐藏</button>
  4. <transition appear> //如果transition有名称,则,调用时需要加上名,加上appear可以出现进入动画
  5. <h1 v-show="isShow">你好啊</h1>
  6. </transition>
  7. </div>
  8. </template>
  9. <script>
  10. export default{
  11. name:'Test',
  12. data(){
  13. return{
  14. isShow:true
  15. }
  16. }
  17. }
  18. </script>
  19. <style scoped>
  20. h1{
  21. background-color:pink;
  22. }
  23. .v-enter-active{
  24. animation:donghua 1s linear;
  25. }
  26. .v-leave-active{
  27. animation:donghua 1s linear reverse;
  28. }
  29. @keyframes donghua{
  30. from{
  31. transfrom:translateX(-100px);
  32. }
  33. to{
  34. transfrom:translateX(0px)
  35. }
  36. }
  37. </style>

父组件:

  1. <template>
  2. <div>
  3. <Text/>
  4. </div>
  5. </template>
  6. <script>
  7. import Test from './conponents/Test'
  8. export default{
  9. name:'App',
  10. components:{Test}
  11. }
  12. </script>
  13. <style>
  14. </style>

过渡效果

子组件:

  1. <template>
  2. <div>
  3. <button @click="isShow = !isShow>显示隐藏</button>
  4. <transition name="hello" appear>
  5. <h2 v-show="isShow"></h2>
  6. </transition>
  7. </div>
  8. </template>
  9. <script>
  10. export default{
  11. name:'Test2',
  12. data(){
  13. return{
  14. isShow=true;
  15. }
  16. }
  17. }
  18. </script>
  19. <style>
  20. h2{
  21. background-color:pink;
  22. transition:1s linear;
  23. }
  24. //进入的起点;离开的终点
  25. .hello-enter,.hello-leave-to{
  26. transform:translateX(-100px);
  27. }
  28. //进入的过程中,离开的过程中
  29. .hello-enter-active,.hello-leave-active{
  30. transition:1s linear;
  31. }
  32. //进入的终点;离开的起点
  33. .hello-enter-to,.hello-leave{
  34. transform:translateX(0px);
  35. }
  36. </style>

父组件:

  1. <template>
  2. <div>
  3. <Test/>
  4. <Test2/>
  5. </div>
  6. </template>
  7. <script>
  8. import Test from './components/Test'
  9. import Test2 from './components/Test2'
  10. export default{
  11. name:'App',
  12. components:{
  13. Test,
  14. Test2
  15. }
  16. }
  17. </script>
  18. <style></style>

多个元素过渡:

利用<transition-group></transition-group>

集成第三方库,创建动画:

动画小结:

  1. <template>
  2. <ul>
  3. <transition-group name="todo" appear>
  4. <MyItem>
  5. v-for="todoObj in todos"
  6. :key="todoObj.id"
  7. :todo="todoObj"
  8. </MyItem>
  9. </transition-group>
  10. </ul>
  11. </template>
  12. <script>
  13. import MyItem from './MyItem'
  14. export default{
  15. name:'MyList',
  16. components:{MyItem},
  17. props:['todos']
  18. }
  19. </script>
  20. <style>
  21. .todo-enter-active{
  22. animation:donghua 1s linear;
  23. }
  24. .todo-leave-active{
  25. animation:donghua 1s linear reverse;
  26. }
  27. @keyframes donghua{
  28. from{
  29. transfrom:translateX(-100px);
  30. }
  31. to{
  32. transfrom:translateX(0px)
  33. }
  34. }
  35. </style>

Vue封装过渡与动画:

1、作用:在插入、更新或移除DOM元素时,在合适的时候给元素添加样式类名。

2、如图:

 写法:

        (1)准备好样式:

                元素进入的样式:1、v-enter:进入的起点

                                                2、v-enter-active:进入的过程中

                                                3、v-enter-to:进入终点

                元素离开样式:

                                                1、v-leave:离开的起点;

                                                2、v-leave-active:离开过程中

                                                3、v-leave-to:离开的终点

3、使用<transition>包裹要过渡的元素,并配置name属性:

  1. <transition>
  2. <h1 v-show="isShow">你好啊</h1>
  3. </transition>

配置代理——方式一

脚手架中,创建代理服务器:

  1. module.exports={
  2. pages:{
  3. index:{
  4. entry:'src/main.js'
  5. },
  6. },
  7. lintOnSave:false,
  8. 开启代理服务器
  9. devServer:{
  10. proxy:'http://localhost:5000'
  11. }
  12. }

 这样配置代理方式两点不足:(1)一次只能配置一个搭理服务器;

(2)如果在本文件中有和请求同名字的,则执行本文件中的,不执行服务器中的;

App.vue组件

  1. <template>
  2. <div>
  3. <button @click="getStudents">获取学生信息</button>
  4. </div>
  5. </template>
  6. <script>
  7. import axios from 'axios'
  8. export default{
  9. name:'App',
  10. methods:{
  11. getStudents(){
  12. axios.get('https://localhost:8080/student').then(
  13. response=>{
  14. console.log('请求成功',response.data)
  15. }
  16. error=>{
  17. console.log("请求失败",error.message)
  18. }
  19. )
  20. }
  21. }
  22. }
  23. </script>

方式一小结:

在脚手架文件中(vue.config.js)添加如下配置:

优点:配置简单,请求资源时直接发给前端(8080)即可。

缺点:不能配置多个代理,不能灵活控制请求是否走代理。

工作方式:若按照上述配置代理,当请求了前端不存在的资源时,那么该请求会转发给服务器(优先匹配前端资源)

配置代理方式二:

Vue.config.js在脚手架中,配置

  1. module.exports={
  2. pages:{
  3. index:{
  4. entry:'src/main.js',
  5. },
  6. },
  7. lintOnSave:false,
  8. devServer:{
  9. proxy:{
  10. '/atguigu':{
  11. target:'http://localhost:5000',
  12. pathRewrite:{'^/atguigu':''}
  13. ws:true, //用于支持websocket
  14. changeOrigin:true //是否传递真实服务器端口
  15. },
  16. '/demo':{
  17. target:'http://localhost:5001',
  18. pathRewrite:{'^/demo':''}
  19. }
  20. }
  21. }
  22. }

(changeOrigin:true / false:用于控制请求头中的host值)

同时配置多个代理服务器:

  1. <template>
  2. <div>
  3. <button @click="getCars">点击获取汽车信息</button>
  4. <button @click="getStudents">获取学生信息</button>
  5. </div>
  6. </template>
  7. <script>
  8. import axios from 'axios'
  9. export default {
  10. name:'App',
  11. methods:{
  12. getStudents(){
  13. axios.get('http://localhost:8080/atguigu/students').then(
  14. response=>{
  15. console.log("请求成功",response.data)
  16. },
  17. error=>{
  18. console.log("请求失败",error.message)
  19. }
  20. )
  21. },
  22. getCars(){
  23. axios.get("http://localhost:8080/demo/car").then(
  24. response=>{
  25. console.log('',response.data)
  26. },
  27. error=>{
  28. console.log("请求失败了",error.message)
  29. }
  30. )
  31. }
  32. }
  33. }
  34. </script>
  35. <style></style>

方式二小结:

github案例

 html引入第三方库

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  7. <link rel="icon" href="<%=BASE_URL %>favicon.ico">
  8. <link rel="stylesheet" href="<%= BASE_URL %> css/bootstarp.css">
  9. <title><%=htmlWebpackPlugin.options.title %></title>
  10. </head>
  11. <body>
  12. <noscript>
  13. <strong>当浏览器不支持js时执行</strong>
  14. </noscript>
  15. <div id="app"></div>
  16. </body>
  17. </html>

App组件

  1. <template>
  2. <div class='container'>
  3. <Search/>
  4. <List/>
  5. </div>
  6. </template>
  7. <script>
  8. import Search from './components/Search.vue'
  9. import List from './components/List.vue'
  10. export default{
  11. name:'App',
  12. components:{Search,List}
  13. }
  14. <script>
  15. <style></style>

子组件:Search.vue

  1. <template>
  2. <section class="jumbotron">
  3. <h3 class="jumbotron-heading"></h3>
  4. <div>
  5. <input type="text" placeholder="enter the name you search" v-model="keywords"/> $nbsp;
  6. <button @click="searchUsers">search</button>
  7. </div>
  8. </section>
  9. </template>
  10. <script>
  11. export default{
  12. name:'Search',
  13. data(){
  14. return{
  15. keyWord:''
  16. }
  17. },
  18. methods:{
  19. searchUsers(){
  20. this.$bus.$emit('userList',{isFirst:false,isLoading:true,errMsg:'',users:[]})
  21. axios.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
  22. response=>{
  23. console.log("请求成功")
  24. this.$bus.$emit("userList",{isLoading:false,errMsg:'',users:response.data.item})
  25. },
  26. error=>{
  27. console.log("请求失败",isLoading:false,errMsg:error.message,user:[])
  28. }
  29. )
  30. },
  31. },
  32. }
  33. </script>
  34. <style></style>

子组件List.vue

  1. <template>
  2. <div class="row">
  3. <div class="card" v-for="user in users" :key="user.login">
  4. <a :href="user.html_url" target="_blank">
  5. <img :src="user.avatar_url" style="width:100px">
  6. </a>
  7. <p class="card-text">{{user.login}}</p>
  8. </div>
  9. <h1 v-show="isFirst">欢迎使用</h1>
  10. <h1 v-show="isLoading">加载中</h1>
  11. <h1 v-show="errMas">{{errMas}}</h1>
  12. </div>
  13. </template>
  14. <script>
  15. export default{
  16. name:'List',
  17. data(){
  18. return {
  19. info:{
  20. isFirst:true,
  21. isLoading:false,
  22. errMas:'',
  23. users:[]
  24. }
  25. }
  26. },
  27. mounted(){ (形参)
  28. this.$bus.$on("userList",(dataObj)=>{
  29. this.info={...this.info,...dataObj}
  30. (上边的info中的参数)
  31. console.log(this)
  32. })
  33. },-
  34. }
  35. </script>
  36. <style>
  37. </style>

 Vue——resource

main.js

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import vueResource from 'vue-resource'
  4. Vue.config.productionTip=false
  5. Vue.use(vueResource)
  6. new Vue({
  7. el:'',
  8. render:h=>h(App),
  9. beforeCreate(){
  10. Vue.prototype.$bus=this
  11. },
  12. })

Search.vue

  1. <template>
  2. <section class="jumbotron">
  3. <h3 class="jumbotron-heading"></h3>
  4. <div>
  5. <input type="text" placeholder="enter the name you search" v-model="keywords"/> $nbsp;
  6. <button @click="searchUsers">search</button>
  7. </div>
  8. </section>
  9. </template>
  10. <script>
  11. import axios from 'axios'
  12. export default{
  13. name:'Search',
  14. data(){
  15. return{
  16. keyWord:''
  17. }
  18. },
  19. methods:{
  20. searchUsers(){
  21. this.$bus.$emit('userList',{isFirst:false,isLoading:true,errMsg:'',users:[]})
  22. this.$http.get(`https://api.github.com/search/users?q=${this.keyWord}`).then(
  23. response=>{
  24. console.log("请求成功")
  25. this.$bus.$emit("userList",{isLoading:false,errMsg:'',users:response.data.item})
  26. },
  27. error=>{
  28. console.log("请求失败",isLoading:false,errMsg:error.message,user:[])
  29. }
  30. )
  31. },
  32. },
  33. }
  34. </script>
  35. <style></style>

 Vue——默认插槽

子组件category.vue

  1. <tmeplate>
  2. <div class="category">
  3. <h3>{{title}}</h3>
  4. <slot></slot> //定义一个插槽;等组件使用者向里边填充
  5. </div>
  6. </template>
  7. <script>
  8. export default{
  9. name:'Category',
  10. props:['title']
  11. }
  12. </script>
  13. <style></style>

App.vue父组件

  1. <template>
  2. <div class="container">
  3. <Category title="实物">
  4. <img src="https://*****.jpg" alt="">
  5. </Category>
  6. <Category title="游戏"">
  7. <ul>
  8. <li v-for="(item,index) in games" :key="index">{{item}}</li>
  9. </ul>
  10. </Category>
  11. </div>
  12. </template>
  13. <script>
  14. import Category from './components/Category'
  15. export default{
  16. name:'App',
  17. components:{Category}
  18. data(){
  19. return{
  20. foots:['牛肉','羊肉',],
  21. games:['打代码','看书']
  22. }
  23. }
  24. }
  25. </script>
  26. <style></style>

 Vue——具名插槽

  1. <template>
  2. <div class="container">
  3. <Category title="实物">
  4. <img slot="center" src="https://*****.jpg" alt="">
  5. <a slot="foot" href="http://www.***.com">更多美食</a>
  6. </Category>
  7. <Category title="游戏">
  8. <ul slot="center">
  9. <li v-for="(item,index) in listData" :key="index">{{item}}</li>
  10. </ul>
  11. <template v-slot:foot> //最新写法,但是只能放在template标签中
  12. <div class="foot">
  13. <a href="http://***">单机游戏</a>
  14. <a href="http://***">网络游戏</a>
  15. </div>
  16. <h2>使用template可以包裹放入同一个组件中</h2>
  17. </template>
  18. </Category>
  19. </div>
  20. </template>
  21. <script>
  22. import Category from './components/Category'
  23. export default{
  24. name:'App',
  25. components:{Category}
  26. data(){
  27. return{
  28. foots:['牛肉','羊肉',],
  29. games:['打代码','看书']
  30. }
  31. }
  32. }
  33. </script>
  34. <style></style>

Category.vue组件

  1. <tmeplate>
  2. <div class="category">
  3. <h3>{{title}}</h3>
  4. <slot name="center"></slot> //定义一个具有名字插槽;等组件使用者向里边填充
  5. <slot name="foot"></slot> //定义一个具有名字插槽;等组件使用者向里边填充
  6. </div>
  7. </template>
  8. <script>
  9. export default{
  10. name:'Category',
  11. props:['title']
  12. }
  13. </script>
  14. <style></style

Vue—— 作用域插槽,

App.vue组件:

  1. <template>
  2. <div class="container">
  3. <Category title="美食">
  4. <template scope="atguigu">
  5. <ul>
  6. <li v-for="(g,index) in atguigu.game":key="index">{{g}}</li>
  7. </ul>
  8. </template>
  9. </Category>
  10. <Category title="游戏">
  11. <template scope="{games}">
  12. <ol>
  13. <li v-for="(g,index) in games":key="index">{{g}}</li>
  14. </ol>
  15. </template>
  16. </Category>
  17. </div>
  18. </template>
  19. <script>
  20. import Category from './components/Category'
  21. export default{
  22. name:'App',
  23. components:{Category},
  24. }
  25. </script>
  26. <style></style>

Category.vue组件

  1. <template>
  2. <div class="category">
  3. <h3>{{title}}</h3>
  4. <slot :games="games" msg="hello">默认的内容,如果没有传递过来插槽则显示</slot>
  5. </div>
  6. </template>
  7. <script>
  8. export default{
  9. name:'Category',
  10. props:['title']
  11. data(){
  12. return {
  13. game:['红警','原神','打代码']
  14. }
  15. }
  16. }
  17. </script>
  18. <style></style>

插槽小结:

一、作用:让父组件可以向子组件指定位置插入html结构,也是一种组件通信方式,适用于父组件===》子组件。

二、分类:默认插槽、具名插槽、作用域插槽。

三、使用方式:

        1、默认插槽:

         2、具名插槽:

         3、作用域插槽:

 

 Vue——vuex

一、概念:专门在Vue中实现集中式状态(数据)管理的一个Vue插件,对vue中应用多个组件的共享状态进行集中式的管理(读写),也是一种组件间通信的方式,且适用于任意组件间通信、

二、GitHub地址:

什么时候使用Vuex :(1)多个组件依赖于统一状态;(2)来自不同组件的行为需要变更同一状态

 Vue——点击加案例(一般写法)

  1. <template>
  2. <div>
  3. <h1>当前和是{{sum}}</h1>
  4. <select v-model="n">
  5. <option :value="1">1</option>
  6. <option :value="2">2</option>
  7. <option :value="3">3</option>
  8. </select>
  9. <button @click="increment">+</button>
  10. <button @click="decrement">-</button>
  11. <button @click="incrementOdd">当前求和为奇数再加一</button>
  12. <button @click="incrementWait">等一等再加</button>
  13. </div>
  14. </template>
  15. <script>
  16. export default{
  17. name:'Count',
  18. data(){
  19. return{
  20. n:1,
  21. sum:0
  22. }
  23. },
  24. methods:{
  25. increment(){
  26. this.sum+=this.n;
  27. },
  28. decrement(){
  29. this.sum-=this.n;
  30. },
  31. incrementOdd(){
  32. if(this.sum % 2){
  33. this.sum+=this.n;
  34. }
  35. },
  36. incrementWait(){
  37. setTimeout({
  38. this.sum+=this.n;
  39. },1000)
  40. },
  41. }
  42. }
  43. </script>
  44. <sty></style>

分析Vuex的原理

 Vue——搭建环境并使用vuex

 步骤:

index.js

  1. //引入Vue核心库
  2. import Vue from 'vue'
  3. //引入Vuex
  4. import Vuex from 'vues'
  5. //应用Vuex插件
  6. Vue.use(Vuex)
  7. //准备actions对象——响应组件中用户的动作
  8. const actions={}
  9. //准备mutations对象修改state中的数据
  10. const mutations={}
  11. //准备state对象——保存具体的数据
  12. const state={}
  13. //创建并暴露store
  14. export default new Vuex.Store({
  15. actions,
  16. mutations,
  17. state
  18. })

main.js中创建vm时传入store配置项

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. import vueResource from 'vue-resource'
  4. //引入store
  5. import store from './store'
  6. Vue.config.producation=flase
  7. Vue.use(vueResource)
  8. //创建vm
  9. new Vue({
  10. el:'#app',
  11. render:h=>h(App),
  12. store,
  13. beforeCreate(){
  14. Vue.prototype.$bus = this
  15. }
  16. })

 Vue——点击加案例(Vuex写法)

 Count.vue组件

  1. <template>
  2. <div>
  3. <h1>当前求和为:{{$store.state.sum}}</h1>
  4. <select v-model.number='n'>
  5. <option value="1">1</option>
  6. <option value="2">2</option>
  7. <option value="3">3</option>
  8. </select>
  9. <button @click="increment">+</button>
  10. <button @click="decrement">-</button>
  11. <button @click="incrementOdd">当前求和为奇数再加</button>
  12. <button @click="incrementWait">等一等再加</button>
  13. </div>
  14. </template>
  15. <script>
  16. export default{
  17. name:'Count',
  18. data(){
  19. return {
  20. n:1
  21. }
  22. },
  23. methods:{
  24. increment(){
  25. this.$store.commit('jia',this.n) //不用经过处理的数据,直接跳过action
  26. },
  27. decrement(){
  28. this.$store.commit('jian',this.n) //不用经过处理的数据,直接跳过action
  29. },
  30. incrementOdd(){
  31. this.$store.dispatch('jiaOdd',this.n)
  32. },
  33. incrementWait(){
  34. this.$store.dispatch('jiaWait',this.n)
  35. },
  36. },
  37. mounted(){
  38. }
  39. }
  40. </script>
  41. <style></style>

 index.js:

  1. import Vue from 'vue'
  2. import Vuex from 'vues'
  3. Vue.use(Vuex)
  4. const actions = { //准备action——用于响应组件中的动作
  5. jia(context,value){ //函数的简写:jia:function(){} ; context译为上下文
  6. console.log('actions中的jia被调用了')
  7. context.commit('JIA',value)
  8. },
  9. jian(context,value){
  10. console.log('actions中的jian被调用了')
  11. context.commit('JIAN',value)
  12. },
  13. jiaOdd(context,value){
  14. console.log('actions中的jiaOdd被调用了')
  15. if(context.state.sum % 2){
  16. context.commit('JIA',value)
  17. }
  18. },
  19. jiaWait(context,value){
  20. console.log("actions中的jiaOdd被调用了")
  21. setTimeout(()=>{
  22. context.commit('JIA',value)
  23. },1000)
  24. }
  25. },
  26. const mutations={
  27. JIA(state,value){
  28. console.log('mutations中的JIA被调用了')
  29. state.sum+=value
  30. },
  31. JIAN(state,value){
  32. console.log('mutations中的JIA被调用了')
  33. state.sum-=value
  34. },
  35. },
  36. //初始化数据
  37. const state={
  38. sum:0
  39. },
  40. //创建并暴露store
  41. export default new Vues.Store({
  42. actions,
  43. mutations,
  44. state,
  45. })

 小结:

(1)组件中读取Vuex中的数据: 

(2)组件中修改vuex中的数据:

 备注:

Vue——getters配置项

一、概念:当state中的数据需要经过加工后再使用时,可以使用getters加工;

index.js文件中

  1. import Vue from 'vue'
  2. import Vuex from 'vues'
  3. Vue.use(Vuex)
  4. ................
  5. const actions={}
  6. const mutations={}
  7. const state={
  8. sum=0
  9. }
  10. ......
  11. const getters={
  12. bigSum(state){
  13. return state.sum*10
  14. }
  15. }
  16. export default new Vuex.Store({
  17. actions,
  18. mutations,
  19. state,
  20. getters
  21. })

Count.vue组件中

  1. <template>
  2. <div>
  3. <h1>当前值和为:{{$store.state.sum}}</h1>
  4. <h3>当前求和放大十倍为:{{$store.getters.bigSum}}</h3>
  5. .......
  6. </div>
  7. </template>
  8. <script>
  9. export default{
  10. name:'Count',
  11. .......
  12. methods:{
  13. increment(){
  14. this.$store.commit('jia',this.n) //不用经过处理的数据,直接跳过action
  15. },
  16. decrement(){
  17. this.$store.commit('jian',this.n) //不用经过处理的数据,直接跳过action
  18. },
  19. incrementOdd(){
  20. this.$store.dispatch('jiaOdd',this.n)
  21. },
  22. incrementWait(){
  23. this.$store.dispatch('jiaWait',this.n)
  24. },
  25. },
  26. mounted(){
  27. console.log('Count',this.$store)
  28. }
  29. }
  30. </script>
  31. <style></style>

    Vue——mapState和mapGetters优化computed计算属性

"...":es6把...后边的展开。

  1. <template>
  2. <div>
  3. <h1>当前值和为:{{$store.state.sum}}</h1>
  4. <h3>当前求和放大十倍为:{{$store.getters.bigSum}}</h3>
  5. .......
  6. </div>
  7. </template>
  8. <script>
  9. import {mapState,mapGetters} from "vues"
  10. export default{
  11. name:'Count',
  12. data(){},
  13. computed:{
  14. 靠程序员自己写计算属性
  15. sum(){
  16. return this.$store.state.sum
  17. },
  18. school(){
  19. return this.$store.state.school
  20. },
  21. subject(){
  22. return this.$store.state.subject
  23. },
  24. --------------------------------
  25. 借助mapState生成计算器,从state中读取数据:对象写法
  26. ...mapState({sum:'sum',school:'school',subject:'subject'})
  27. 数组写法,当属性名和计算时名相同时
  28. ...masState(['sum','school','subject'])
  29. 借助mapGetters生成计算器,从getters中读取属性:对象写法
  30. ...mapGetter({bigSum:'bigSum'})
  31. 数组写法,当属性名和计算时名相同时
  32. ...mapGetter(['bigSum'])
  33. },
  34. methods:{}
  35. }
  36. </script>
  37. <style></style>

小结:

 Vue——mapMutations与mapActions优化methods方法

Count.vue组件:

mapMutations生成对应方法:

  1. <template>
  2. <div>
  3. <h1>当前值和为:{{$store.state.sum}}</h1>
  4. <h3>当前求和放大十倍为:{{$store.getters.bigSum}}</h3>
  5. .......
  6. <button @click="increment(n)">+</button>
  7. <button @click="decrement(n)">-</button>
  8. <button @click="incrementOdd(n)">当前求和为奇数再加</button>
  9. <button @click="incrementWait(n)">等一等再加</button>
  10. </div>
  11. </template>
  12. <script>
  13. import {mapMutations} from "vues"
  14. export default{
  15. name:'Count',
  16. data(){},
  17. computed:{}
  18. methods:{
  19. //靠程序员自己写计算属性
  20. increment(){
  21. this.$store.commit('JIA',this.n)
  22. },
  23. decrement(){
  24. this.$store.commit('JIAN',this.n)
  25. }
  26. -------------------------------
  27. //借助mapMutations生成对应的方法,方法中会调用commit去联系mutations:对象写法
  28. ...mapMutations({increment:'JIA',decrement:'JIAN'}),
  29. //借助mapMutations生成对应的方法,方法会调用commit去联系mutations:数组写法
  30. ...mapMutations({'JIA','JIAN'})
  31. }
  32. }
  33. </script>
  34. <style></style>

mapActions生成对应方法:

  1. <template>
  2. <div>
  3. <h1>当前值和为:{{$store.state.sum}}</h1>
  4. <h3>当前求和放大十倍为:{{$store.getters.bigSum}}</h3>
  5. .......
  6. <button @click="increment(n)">+</button>
  7. <button @click="decrement(n)">-</button>
  8. <button @click="incrementOdd(n)">当前求和为奇数再加</button>
  9. <button @click="incrementWait(n)">等一等再加</button>
  10. </div>
  11. </template>
  12. <script>
  13. import {mapActions} from "vues"
  14. export default{
  15. name:'Count',
  16. data(){},
  17. computed:{}
  18. methods:{
  19. //靠程序员自己写计算属性
  20. increment(){
  21. this.$store.dispatch('JIA',this.n)
  22. },
  23. decrement(){
  24. this.$store.dispatch('JIAN',this.n)
  25. }
  26. -------------------------------
  27. //借助mapMutations生成对应的方法,方法中会调用dispatch去联系actions:对象写法
  28. ...mapActions({increment:'JIA',decrement:'JIAN'}),
  29. //借助mapMutations生成对应的方法,方法会调用dispatch去联系actions:数组写法
  30. ...mapActions({'JIA','JIAN'})
  31. }
  32. }
  33. </script>
  34. <style></style>

小结:

 注意:使用

 如果需要传递参数,在模板中绑定事件时,就需要传递阐参数,否则参数是默认事件对象(单击,鼠标移动...)

 Vue——多组件共享

 person.vue

  1. <template>
  2. <h2>人员列表组件</h2>
  3. <h3>Count组件的和为:{{sum}}</h3>
  4. <div>
  5. <input type = 'text' placeholder="请输入姓名" v-model="name">
  6. <button @click="add">添加</button>
  7. <ul>
  8. <li v-for"p in personList" :key="p.id">{p.name}</li>
  9. </ul>
  10. </div>
  11. </template>
  12. <script>
  13. import {nanoid} from 'nanoid'
  14. export default{
  15. name:'Person',
  16. computed:{
  17. personList(){ //程序员自己写代码,计算属性
  18. return this.$store.state.personList
  19. },
  20. sum(){
  21. return this.$store.state.sum
  22. }
  23. },
  24. data(){
  25. return{
  26. name:''
  27. }
  28. },
  29. methods:{
  30. add(){
  31. const personOjb = {id:nanoid(),name:this.name}
  32. this.$store.commit('ADD_PERSon',personObj)
  33. this.name=""
  34. }
  35. }
  36. }
  37. -------------------------------------
  38. import {mapState} from 'vuex'
  39. export default{
  40. name:'Person',
  41. computed:{ //通过引入vuex的mapState计算属性
  42. ...mapState(['personList']) 数组方式
  43. }
  44. }
  45. </script>
  46. <style></style>

 Count.vue组件

  1. <template>
  2. <div>
  3. <h1>当前求和为:{{$store.state.sum}}</h1>
  4. <h3>当前值放大十倍是:{{bigSum}}</h3>
  5. <h3>我在{{school}},学习{{subject}}</h3>
  6. <h3>person组件的总人数是:{{personList.length}}</h3>
  7. <select v-model.number='n'>
  8. <option value="1">1</option>
  9. <option value="2">2</option>
  10. <option value="3">3</option>
  11. </select>
  12. <button @click="increment">+</button>
  13. <button @click="decrement">-</button>
  14. <button @click="incrementOdd">当前求和为奇数再加</button>
  15. <button @click="incrementWait">等一等再加</button>
  16. </div>
  17. </template>
  18. <script>
  19. import {mapState,mapGetters,mapMutations,mapActions} from 'vuex'
  20. export default{
  21. name:'Count',
  22. data(){
  23. return{
  24. n:1,
  25. }
  26. },
  27. computed:{
  28. ...mapState(['sum','school','subject','personList']),
  29. ...mapGetters(['bigSum'])
  30. }
  31. methods{
  32. ...mapMutations({increment:'JIA',decrement:'JIAN'}),
  33. ...mapActions({incrementOdd:'jiaOdd',incrementWait:'jiaWait'})
  34. }
  35. }
  36. </script>
  37. <style></style>

index.js中配置数据

  1. import Vue from 'vue'
  2. import Vuex from 'vux'
  3. Vue.use(Vuex)
  4. const actions={}
  5. const mutations={
  6. ......
  7. ADD_PERSON(state,personObj){
  8. console.log('mutations中的ADD_PERSON被调用了')
  9. state.personList.unshift()
  10. }
  11. }
  12. const state={
  13. sum:0,
  14. school:'尚硅谷',
  15. subject:'前端',
  16. personList:[
  17. {id:'001',name:'张三'}
  18. ]
  19. }
  20. const getters={}
  21. export default{
  22. actions,
  23. mutations,
  24. state,
  25. getters
  26. }

Vue——vuex模板化+namespace

小结:

 

Vue——路由(vue-router)

 一、定义:是vue的一个插件库,专门用来实现SPA应用。

二、对SPA应用的理解:

1、单页Web应用(SPA)

2、整个应用只有一个完整的页面(index.html)

3、点击页面中的导航链接不会刷新页面,只会做页面的据不更新。

4、数据需要通过Ajax获取。

三、路由的理解

1、什么是路由?

        (1)一个路由就是一组映射关系(key-value)

        (2)key为路径,value可能是function或者component

2、路由分类:

        (1)后端路由:

                理解:value是function,用于处理客户端提交的请求。

               工作过程:服务器接收到一个请求时,根据请求路径找到匹配的函数来处理请求,返回相应数据。

        (2)前端路由:

        理解:value是component,用于展示页面内容。

        工作过程:当浏览器的路径改变时,对应的组件就会显示。

 基本路由切换案例

 Home.vue组件

  1. <template>
  2. <h2>我是HOME内容</h2>
  3. </template>
  4. <script>
  5. export default{
  6. name:'Home'
  7. }
  8. </script>

About.vue组件

  1. <template>
  2. <h2>我是ABOUT内容</h2>
  3. </template>
  4. <script>
  5. export default{
  6. name:'About'
  7. }
  8. </script>

 App.vue组件

  1. <template>
  2. <div>
  3. .......
  4. <div class='row'>
  5. <div class="">
  6. <div class="list-group">
  7. 原始的html中我们使用a标签实现页面的跳转
  8. <a class="list-group-item active" href="./about.html">About</a>
  9. <a class="list-group-item" href="./home.html">Home</a>
  10. -----------------------------------------------
  11. // Vue中借助router-link实现组件切换
  12. <router-link class="list-group-item" active-class="active" to="/about">About</router-link>
  13. <router-link class="list-group-item" active-class="active" to="/home">Home</router-link>
  14. </div>
  15. </div>
  16. <div class="clo-xs-6">
  17. <div class="pannel">
  18. <div class="pannel-body">
  19. <router-view></router-view> //路由器视图,指定组件呈现位置
  20. </div>
  21. </div>
  22. </div>
  23. </div>
  24. </div>
  25. </template>
  26. <><>

main.js

  1. import Vue from 'vue'
  2. import App from './App.vue'
  3. 引入VueRouter路由器
  4. import VueRounter from 'vue-router'
  5. 引入路由器
  6. import router from './router/index' //index文件可以省略
  7. Vue.config.productionTip=false;
  8. Vue.use(VueRouter)
  9. new Vue({
  10. el:'#app',
  11. render:h=>h(App),
  12. router:router
  13. })

router文件夹中创建index.js,这个文件夹专门用来创建整个应用的路由器:

  1. 引入VueRouter
  2. import VueRounter from 'vue-router'
  3. 引入路由组件
  4. import About from './components/About'
  5. import Home From './components/Home'
  6. //创建并暴露一个人路由器
  7. export default router = new VueRouter({
  8. routes:[ //路由器里边的路由
  9. {
  10. path:'/about',
  11. component:About
  12. },
  13. {
  14. path:'/home',
  15. component:Home
  16. }
  17. ]
  18. })

小结:

1、安装vue-router,命令:npm i vue-router

2、应用插件:

3、编写router配置项:

 

Vue——使用路由(router)的几个注意点

路由中分为:路由组件、一般组件

根据使用方式区分:利用路由器来调用的组件为路由组件;通过我们自己用组件标签调用的为一般组件。

小结

1、路由组件通常存放在pages文件夹,一般组件通常存放在components文件夹。

2、通过切换,“隐藏了”的路由组件,默认是贝销毁的,需要使用时候再挂载。

3、每个组件都有自己的$route属性,里面存储着自己的路由信息。

4、整个应用只有一个$router,可以通过组件的$router属性获取到。

 Vue——嵌套(多级)路由

 Home组件

  1. <template>
  2. <h2>Home组件内容</h2>
  3. <div>
  4. <ul class="nav nav-tabs">
  5. <li>
  6. <router-link class="list-group-item"active-class="active" to="/home/news">News</a>
  7. </li>
  8. <li>
  9. <router-link class="list-group-item"active-class="active" to="/home/message">Message</a>
  10. </li>
  11. </ul>
  12. </div>
  13. </template>
  14. <script>
  15. </script>
  16. <style></style>

message.vue组件

  1. <template>
  2. <div>
  3. <ul class="nav nav-tabs">
  4. <li>
  5. <a href="/message1">message001</a> $nbsp;$nbsp;
  6. </li>
  7. <li>
  8. <a href="/message2">message002</a> $nbsp;$nbsp;
  9. </li>
  10. <li>
  11. <a href="/message3">message002</a> $nbsp;$nbsp;
  12. </li>
  13. </ul>
  14. </div>
  15. </template>
  16. <script>
  17. export default{
  18. name:'Message'
  19. }
  20. </script>
  21. <style></style>

news.vue组件

  1. <template>
  2. <ul>
  3. <li>new001</li>
  4. <li>new002</li>
  5. <li>new003</li>
  6. </ul>
  7. <template>
  8. <script>
  9. export default{
  10. name:'News',
  11. }
  12. </script>
  13. <style></style>

index.js创建路由规则

  1. import About from '../pages/About'
  2. import Home from '../pages/Home'
  3. import News from '../pages/News'
  4. export default new VueRouter({
  5. routes:[
  6. {
  7. path:'/about',
  8. component:About
  9. },
  10. {
  11. path:'/home',
  12. component:Home,
  13. children:[
  14. {
  15. path:'news',
  16. component:News,
  17. }
  18. ]
  19. }
  20. ]
  21. })

小结:

1、多级路由规则,使用children配置项:

 2、跳转(要写完整路径)

 Vue——路由的传参

 Detail.vue组件

  1. <template>
  2. <ul>
  3. <li>消息编号:{{$route.query.id}}</li>
  4. <li>消息标题{{$route.query.title}}</li>
  5. </ul>
  6. </template>
  7. <script>
  8. export default{
  9. name:'Detail',
  10. mounted(){
  11. console.log(this.$route)
  12. }
  13. }
  14. </script>

message.vue组件

  1. <template>
  2. <div>
  3. <ul>
  4. <li v-for="m in messageList" :key="m.id">
  5. //跳转路由并携带query参数,to的字符串写法:
  6. <router-link :to="`home/message/detail?id=${m,id}&title=${m.title}`"></router-link>&nbsp;&nbsp
  7. //跳转路由并携带query参数,to的对象写法
  8. <router-link :to="{
  9. path:'/home/message/detail',
  10. query:{
  11. id:m.id,
  12. title:m.title
  13. }
  14. }">{{m.title}}</router-link>
  15. </li>
  16. </ul>
  17. <router-view></router-view>
  18. </div>
  19. </template>
  20. <script>
  21. export default{
  22. return{
  23. messageList:[
  24. {id:'001',title:'消息一'},
  25. {id:'002',title:'消息二'},
  26. {id:'003',title:'消息三'},
  27. ]
  28. }
  29. }
  30. </script>
  31. <style></style>

配置index.js路由规则

  1. import About from '../pages/About'
  2. import Home from '../pages/Home'
  3. import News from '../pages/News'
  4. import Detail from '../pages/Detail'
  5. export default new VueRouter({
  6. routes:[
  7. {
  8. path:'/about',
  9. component:About
  10. },
  11. {
  12. path:'/home',
  13. component:Home,
  14. children:[
  15. {
  16. path:'news',
  17. component:News,
  18. children:[
  19. path:'detail',
  20. component:Detail
  21. ]
  22. }
  23. ]
  24. }
  25. ]
  26. })

小结:

  Vue——命名+-路由

 作用:可以简化路由的跳转。

如何使用

1、给路由命名:

 2、简化跳转:

Vue——路由的params参数

 1、配置路由,声明接收params参数

2、传递参数

  注意:路由携带params参数时,若使用to的对象写法,则不能使用path配置项,必须使用name配置!

3、接收参数

Vue——路由的props配置

router文件夹中index.js配置规则

  1. import About from '../pages/About'
  2. import Home from '../pages/Home'
  3. import News from '../pages/News'
  4. import Detail from '../pages/Detail'
  5. export default new VueRouter({
  6. routes:[
  7. {
  8. path:'/about',
  9. component:About
  10. },
  11. {
  12. path:'/home',
  13. component:Home,
  14. children:[
  15. {
  16. path:'news',
  17. component:News,
  18. children:[
  19. name:"命名路由",
  20. path:'detail/:id/:title',
  21. component:Detail,
  22. ----------------------------------------
  23. props的第一种写法,值为对象,
  24. 该对象中的所有的key-value都会以props的形式传给Detail组件(只能传递固定值)
  25. props:{a:1,b:'zujian'}
  26. -----------------------------------
  27. props第二种写法,值为布尔值,
  28. 如果为真,就会把该路由组件中收到的所有params参数,以props的形式传给Detail组件。
  29. props:true
  30. ]
  31. }
  32. ---------------------------------------
  33. props第三种写法,值为函数,
  34. props($route){
  35. return {
  36. id:$route.query.id,
  37. title:$route.query.title
  38. }
  39. }
  40. ]
  41. }
  42. ]
  43. })

Detail.vue组件中

  1. <template>
  2. <ul>
  3. <li>消息编号:{{id}}</li>
  4. <li>消息标题:{{title}}</li>
  5. <li>{{a}}</li>
  6. <li>{{b}}</li>
  7. </ul>
  8. </template>
  9. <script>
  10. export default{
  11. name:'Detail',
  12. -------------------------------第一种写法
  13. props:['a','b']
  14. computed:{
  15. id(){
  16. return this.$route.params.id
  17. },
  18. title(){
  19. return this.$route.params.title
  20. },
  21. },
  22. ---------------------------第二种写法
  23. props:['id','title']
  24. --------------------------------第三种写法
  25. props:['id','title']
  26. }
  27. </script>
  28. <style></style>

小结:

  Vue——router-link的replace属性

小结:

 Vue——编程时路由导航

 messageList组件

  1. <template>
  2. <div>
  3. <ul>
  4. <li v-for="m in messageList" :key="m.id">
  5. <router-link :to="{
  6. name:'',
  7. query:{
  8. id:m.id,
  9. title:m.title
  10. }
  11. }">{{m.title}}</router-link>
  12. <button @click='pushShow(m)'>push查看</button>
  13. <button @click='replaceShow(m)'>replace查看</button>
  14. </li>
  15. </ul>
  16. </div>
  17. </template>
  18. <script>
  19. export default{
  20. name:'Message',
  21. data(){
  22. },
  23. methods:{
  24. pushShow(){ //记录每次跳转的记录,回退逐个回退
  25. this.$router.push({
  26. name:'xiangqing',
  27. query:{
  28. id:m.id,
  29. title:m.title
  30. }
  31. })
  32. },
  33. replaceShow(m){ //销毁上一次的记录,
  34. this.$router.replace({
  35. name:'xiangqing',
  36. query:{
  37. id:m.id,
  38. title:m.title
  39. }
  40. })
  41. }
  42. }
  43. }
  44. </script>
  45. <style>
  46. </style>
  1. <template>
  2. <div class="col-xs-offset-2">
  3. <div class="page-header">
  4. <button @click="back">后退</button>
  5. <button @click="forward">前进</button>
  6. <button @click="go">根据数字正值前进,负值后退</button>
  7. </div>
  8. </div>
  9. </template>
  10. <script>
  11. export default{
  12. name:'Banner',
  13. methods:{
  14. back(){
  15. this.$router.back()
  16. }
  17. forward(){
  18. this.$router.forward()
  19. }
  20. go(){
  21. this.$router.go(2) //前进两步记录
  22. }
  23. }
  24. }
  25. </script>
  26. <style></style>

Vue——缓存路由组件

  1. <template>
  2. <div>
  3. <h2>Home组件内容</h2>
  4. <div>
  5. <ul>
  6. <li>
  7. <router-link class="list-group-item" active-class="active" to="/home/news">News</router-link>
  8. </li>
  9. <li>
  10. <router-link class="list-group-item" active-class="active" to="/home/Message">Message</router-link>
  11. </li>
  12. </ul>
  13. <keep-alive include="News"> 指定缓存的组件名
  14. <router-view></router-view>
  15. </keep-alive>
  16. </div>
  17. </div>
  18. </template>
  19. <script>
  20. export default{
  21. name:'Home'
  22. }
  23. </script>
  24. <style></style>

小结:

 当需要保持多个缓存组件时,可以在通过绑定include数组:

Vue——两个新的生命周期钩子

 1、作用:路由组件所独有的两个钩子,用于捕获路由组件的激活状态。

2、具体名字:

        (1)activated路由组件被激活时触发

        (2)deactivated路由组件失活时触发

  1. <template>
  2. <ul>
  3. <li :style="{opacity}">透明度变化动画</li>
  4. <li>new001</li>
  5. <li>new002</li>
  6. <li>new003</li>
  7. </ul>
  8. <template>
  9. <script>
  10. export default{
  11. name:'News',
  12. data(){
  13. return{
  14. opacity:1
  15. }
  16. },
  17. activated(){
  18. console.log("News组件被激活了")
  19. this.timer = setInterval(()=>{
  20. this.opacity-=0.01
  21. if(this.opacity <= 0) this.opacity=1
  22. },100)
  23. },
  24. deactivated(){
  25. console.log("News组件失活了")
  26. clearInterval(this.timer)
  27. }
  28. }
  29. </script>
  30. <style></style>

Vue——全局前置-路由守卫

 路由规则index.js文件

  1. import About from '../pages/About'
  2. import Home from '../pages/Home'
  3. import News from '../pages/News'
  4. import Detail from '../pages/Detail'
  5. export default new VueRouter({
  6. routes:[
  7. {
  8. path:'/about',
  9. component:About
  10. },
  11. {
  12. path:'/home',
  13. component:Home,
  14. children:[
  15. {
  16. path:'news',
  17. component:News,
  18. children:[
  19. path:'detail',
  20. component:Detail
  21. props($route){
  22. return {
  23. id:$route.query.id,
  24. title:$route.query.title
  25. }
  26. ]
  27. }
  28. ]
  29. }
  30. ]
  31. })
  32. router.deforeEach((to,from,next)=>{ //全局前置路由守卫 ——初始化的时候被调用,每次路由切换之前被调用
  33. //to:前往的地址;
  34. //from:来自的地址;
  35. //next:是否允许放行
  36. if(to.path==='/home/news' || to.path==='/homemessage'){
  37. if(localStorage.getItem('school')==='atguigu'){
  38. next()
  39. }else{
  40. alert("学校名称不对,无权限")
  41. }
  42. }else{
  43. next()
  44. }
  45. })

全局后置——路由守卫

  1. import About from '../pages/About'
  2. import Home from '../pages/Home'
  3. import News from '../pages/News'
  4. import Detail from '../pages/Detail'
  5. export default new VueRouter({
  6. routes:[
  7. {
  8. path:'/about',
  9. component:About,
  10. meta:{title:'关于'}
  11. },
  12. {
  13. path:'/home',
  14. component:Home,
  15. meta:{title:'标题'}
  16. children:[
  17. {
  18. path:'news',
  19. component:News,
  20. meta:{isAuth:true}
  21. children:[
  22. path:'detail',
  23. component:Detail
  24. props($route){
  25. return {
  26. id:$route.query.id,
  27. title:$route.query.title
  28. }
  29. ]
  30. }
  31. ]
  32. }
  33. ]
  34. })
  35. router.deforeEach((to,from,next)=>{ 全局前置路由守卫 ——初始化的时候被调用,每次路由切换之前被调用
  36. //to:前往的地址;
  37. //from:来自的地址;
  38. //next:是否允许放行
  39. if(to.meta.isAuth){ //判断是否需要鉴权
  40. if(localStorage.getItem('school')==='atguigu'){
  41. next()
  42. }else{
  43. alert("学校名称不对,无权限")
  44. }
  45. }else{
  46. next()
  47. }
  48. })
  49. 全局后置路由守卫 ——初始化的时候被调用,每次路由切换之后被调用
  50. router.afterEach((to,from)=>{
  51. console.log("后置路由守卫")
  52. if(to.meta.title){
  53. document.title=to.meta.title //修改网页的title
  54. }else{
  55. document.title="默认标题"
  56. }
  57. })

Vue——独享路由守卫

  1. import About from '../pages/About'
  2. import Home from '../pages/Home'
  3. import News from '../pages/News'
  4. import Detail from '../pages/Detail'
  5. export default new VueRouter({
  6. routes:[
  7. {
  8. path:'/about',
  9. component:About,
  10. meta:{title:'关于'}
  11. },
  12. {
  13. path:'/home',
  14. component:Home,
  15. meta:{title:'标题'}
  16. children:[
  17. {
  18. path:'news',
  19. component:News,
  20. meta:{isAuth:true,}
  21. beforeEnter:()=>{ 独享守卫
  22. console.log("独享守卫",to,from)
  23. if(to.meta.isAuth){
  24. if(localStorage.getItem('school')==='atguigu'){
  25. next()
  26. }else{
  27. alert("学校名不对,无权限")
  28. }
  29. }else{
  30. next
  31. }
  32. }
  33. children:[
  34. path:'detail',
  35. component:Detail
  36. props($route){
  37. return {
  38. id:$route.query.id,
  39. title:$route.query.title
  40. }
  41. ]
  42. }
  43. ]
  44. }
  45. ]
  46. })
  47. 全局后置路由守卫 ——初始化的时候被调用,每次路由切换之后被调用
  48. router.afterEach((to,from)=>{
  49. console.log("后置路由守卫")
  50. if(to.meta.title){
  51. document.title=to.meta.title //修改网页的title
  52. }else{
  53. document.title="默认标题"
  54. }
  55. })

 Vue——组件间守卫

  1. import About from '../pages/About'
  2. import Home from '../pages/Home'
  3. import News from '../pages/News'
  4. import Detail from '../pages/Detail'
  5. export default new VueRouter({
  6. routes:[
  7. {
  8. path:'/about',
  9. component:About,
  10. meta:{isAuth:true,title:'关于'}
  11. },
  12. {
  13. path:'/home',
  14. component:Home,
  15. meta:{isAuth:true,title:'标题'}
  16. children:[
  17. {
  18. path:'news',
  19. component:News,
  20. meta:{isAuth:true}
  21. children:[
  22. path:'detail',
  23. component:Detail
  24. props($route){
  25. return {
  26. id:$route.query.id,
  27. title:$route.query.title
  28. }
  29. ]
  30. }
  31. ]
  32. }
  33. ]
  34. })

About.vue组件 

  1. <template>
  2. <h2>我是ABOUT内容</h2>
  3. </template>
  4. <script>
  5. export default{
  6. name:'About'
  7. mounted(){
  8. console.log('@@@',this.$route)
  9. },
  10. beforeRouteEnter(to,from,next){
  11. console.log("组件间路由守卫")
  12. if(to.meta.isAuth){
  13. if(localStorage.getItem('school')=="atguigu"){
  14. next()
  15. }else{
  16. alert("学校名称不对,无权限访问")
  17. }
  18. }else{
  19. next()
  20. }
  21. },
  22. beforeRouterLeave(to,from,next){
  23. next()
  24. }
  25. }
  26. </script>

小结:路由守卫

1、作用:对路由进行权限控制

2、分类:全局守卫,独享守卫,组件守卫

3、全局守卫:

 4、独享守卫:

 5、组件内路由守卫

Vue——hash与history

Vue——UI组件库

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/lpred/article/detail/62788
推荐阅读
相关标签
  

闽ICP备14008679号