06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)

01-父组件传值子组件

06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第1张图片

App.vue文件(主组件)
<template>
  
  <div>
    <p>我是父组件p>
    <button @click="btnClick">点我button>
    
    <son ref="son">son>
  div>
template>

<script>
// 1.导入子组件
import son from "./components/son";
export default {
  // 2.注册组件
  components: {
    son
  },
  methods: {
    btnClick() {
      //按按钮修改子组件的msg,和调用子组件的sayHi方法.
      //console.log(this.$refs.son);//这就等价于子组件this
      this.$refs.son.sonMsg = "呵呵";
      this.$refs.son.sonSayhi();
    }
  },
  mounted() {
     //如果你想在 进入页面就改子组件中的值,而不是按按钮就写在钩子mounted函数里面
      // 不能写在created里面,因为父组件和子组件的生命周期, 都是独立的. 
      // 就算父组件创建了,子组件说不定还没创建好,所以访问子组件的msg访问不到
      // 那如果是mounted里面就不一样,mounted都渲染出来那子组件里的msg肯定也可以访问到
      
    //console.log(this.$refs.son.sonMsg);
      this.$refs.son.sonMsg='嘻嘻嘻嘻嘻嘻嘻'
  },
};
script>

<style>
style>
son.vue(子组件)
<template>
  <div class="son">
    <p>我是子组件p>
    <div>{{sonMsg}}div>
 div>
template>

<script>
export default {
  data() {
    return {
      sonMsg: "我是子组件的msg"
    };
  },
  methods: {
    sonSayhi() {
      console.log("我是子组件的方法");
    }
  }
};
script>

<style>
.son {
  width: 200px;
  height: 200px;
  background-color: pink;
}
style>

效果展示说明: 没点按钮之前子组件的msg:"我是子组件的msg,
由于在主组件的mounted钩子函数中设置了一进入页面修改子组件的msg:“嘻嘻嘻嘻嘻嘻嘻
然后又设置了点击按钮修改子组件的msg:‘呵呵’,并调用了子组件的方法打印了出来

06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第2张图片

02-子组件传值父组件

06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第3张图片

App.vue文件(主组件)
<template>
  <div>
    <p>我是主组件p>
    <div>{{fatherMsg}}div>
    
    <son>son>
  div>
template>

<script>
// 导入组件
import son from './components/son'
export default {
    // 注册组件
    components:{
        son
    },
    data() {
       return {
          fatherMsg: "我是主组件的msg"
       };
    },
  methods: {
    fatherSayhi() {
      console.log("我是主组件的方法");
    }
  }
};
script>

<style>
style>
son.vue文件(子组件)
<template>
  
  <div class="son">
    <p>我是子组件p>
    <button @click="btnClick">点我button>
  div>
template>

<script>
export default {
  methods: {
    btnClick() {
      // 修改父组价的data中的msg,并调用父节点的方法
      this.$parent.fatherMsg = "呵呵";
      this.$parent.fatherSayhi();
    }
  },
  mounted() {
    // 如果你想直接打开页面就修改主组件的msg值,而不是按按钮就写在mounted钩子函数里
    //注意: 父组件的生命周期和 子组件的生命周期是独立的.
    //这里要延时,因为怕主组件还没渲染出来
    setTimeout(() => {
      //console.log(this.$parent.fatherMsg);
      this.$parent.fatherMsg = "嘻嘻嘻嘻嘻嘻";
    }, 10);
  }
};
script>

<style>
.son {
  width: 300px;
  height: 300px;
  background-color: aqua;
}
style>

效果展示说明: 没点按钮之前子组件的msg:"我是主组件的msg,
由于在子组件的mounted钩子函数中设置了一进入页面修改主组件的msg:“嘻嘻嘻嘻嘻嘻
然后又设置了点击按钮修改主组件的msg:‘呵呵’,并调用了主组件的方法打印了出来
06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第4张图片

03-export与import的基本使用

06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第5张图片

App.vue文件(主组件)
<template>
  <div>
      <p>我是主组件p>
      <son>son>
  div>
template>

<script>
// 导入子组件
import son from './components/son'
// 导入外部js文件
import obj from './assets/sb'

export default {
//    注册组件
   components:{
       son
   },
   created() {
       console.log(obj)
   },
}
script>

<style>

style>
son.vue文件(子组件)
<template>
  <div>
      <p>我是子组件p>
      <p>{{msg}}p>
  div>
template>

<script>
export default {
    data() {
        return {
            msg:'你好鸭'
        }
    },
}
script>

<style>

style>
sb.js文件(assets里面)
let obj = {
    name: '杨杨',
    age: 19,
    gender: '男'
}

//只能有一个输出
export default obj;

效果展示说明: 运行主组件,(主组件里面有子组件,也有sb.js文件)
子组件son.vue与sb.js都有导出export default(导出只能有一个输出), 主组件就有导入import这两个文件
sb.js文件就写了一个obj对象并且写在主组件的created里面打印出来,所以一打开页面就会出现打印台有这个obj对象
06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第6张图片


04-音乐播放器(网易云接口)

06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第7张图片

App.vue组件

<template>
  <div class="wrap">
    <div class="play_wrap" id="player">
      
      <div class="search_bar">
        <img src="./assets/images/player_title.png" alt />
        <input type="text" v-model="songName" @keyup.enter="search" />
      div>

      
      <div class="center_con">
        
        <songList ref="songList">songList>

        
        <middle ref="middle">middle>

        
        <comments ref="comments">comments>
      div>
      
      <div class="audio_con">
        <audio @pause="pauseEvent" @play="playEvent" :src="songUrl" autoplay controls loop class="myaudio" >audio>
      div>
    div>
  div>
template>

<script>
//安装导入axios
import axios from "axios";
//导入左边歌曲列表子组件songList.vue
import songList from "./components/songList";
// 导入右边评论子组件comment.vue
import comments from "./components/comment";
//导入中间碟片动画子组件middle.vue
import middle from "./components/middle";

export default {
  //c2.注册组件
  components: {
    songList,
    comments,
    middle
  },
  data() {
    return {
      //搜索的歌曲名字
      songName: "",
      //   歌曲播放地址
      songUrl: ""
    };
  },
  methods: {
    //   搜索事件
    search() {
      //b3.利用axios发送ajax请求 得到搜索相应的所有歌曲
      axios({
        url: "http://183.237.67.218:3000/search",
        params: {
          keywords: this.songName,
          //网易云音乐看你这个ip一直发请求,会把你跨域限制.
          //加这个随机数参数就是不会出现跨域
          xxx: Math.random() * 99999
        }
      }).then(res => {
        // console.log(res);
        //  把返回的所有歌曲保存到子组件的list数组中,然后显示在页面上
        this.$refs.songList.list = res.data.result.songs;
        //   搜索的时候就调用子组件的重新刷新方法,重新加载滚动条高度
        this.$refs.songList.reload();
      });
    },

    getSongInfo(id) {
      //1. 获取歌曲的url
      axios({
        url: "https://autumnfish.cn/song/url",
        params: {
          id
        }
      }).then(res => {
        //console.log(res);
        this.songUrl = res.data.data[0].url;
      });

      //   2.获取歌曲的评论
      axios({
        url: "https://autumnfish.cn/comment/music",
        params: {
          id
        }
      }).then(res => {
        //console.log(res);
        // 主组件传值子组件
        this.$refs.comments.list = res.data.hotComments;
        // 调用评论子组件中的刷新方法,来刷新滚动条
        this.$refs.comments.reload();
      });

      //3.获得碟片中间动画的图片封面
      axios({
        url: "https://autumnfish.cn/song/detail",
        params: {
          ids: id
        }
      }).then(res => {
        //console.log(res);
        this.$refs.middle.picUrl = res.data.songs[0].al.picUrl;
      });
    },
    // 播放触发的事件
    pauseEvent() {
      // 当播放条暂时播放时,让中间碟片停下来起来也就是取消playing类
      this.$refs.middle.playing = false;
    },
    // 暂停触发的事件
    playEvent() {
      // 当播放条开始播放时,让中间碟片动起来也就是加上playing类
      this.$refs.middle.playing = true;
    }
  }
};
script>

  <style>
body,
ul,
dl,
dd {
  margin: 0px;
  padding: 0px;
}

.wrap {
  position: fixed;
  left: 0;
  top: 0;
  width: 100%;
  height: 100%;
  background: url("./assets/images/bg.jpg") no-repeat;
  background-size: 100% 100%;
}

.play_wrap {
  width: 800px;
  height: 544px;
  position: fixed;
  left: 50%;
  top: 50%;
  margin-left: -400px;
  margin-top: -272px;
  /* background-color: #f9f9f9; */
}

.search_bar {
  height: 60px;
  background-color: #1eacda;
  overflow: hidden;
  border-top-left-radius: 4px;
  border-top-right-radius: 4px;
  display: flex;
  align-items: center;
  justify-content: space-between;
  position: relative;
  z-index: 11;
}

.search_bar img {
  margin-left: 23px;
}

.search_bar input {
  margin-right: 23px;
  width: 296px;
  height: 34px;
  border-radius: 17px;
  border: 0px;
  background: url("./assets/images/zoom.png") 265px center no-repeat
    rgba(255, 255, 255, 0.45);
  text-indent: 15px;
  outline: none;
}

.center_con {
  height: 435px;
  background-color: rgba(255, 255, 255, 0.5);
  display: flex;
}

.song_wrapper {
  width: 200px;
  height: 435px;
  box-sizing: border-box;
  padding: 10px;
  list-style: none;
  background: url("./assets/images/line.png") right center no-repeat;
  position: relative;
  overflow: hidden;
}

.song_list li {
  font-size: 12px;
  color: #333;
  line-height: 36px;
  width: 180px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  cursor: pointer;
}

.song_list .active {
  color: #da651e;
}

.player_con {
  width: 400px;
  height: 435px;
  position: relative;
}

.disc {
  position: absolute;
  left: 73px;
  top: 60px;
  z-index: 9;
}

.cover {
  position: absolute;
  left: 125px;
  top: 112px;
  width: 150px;
  height: 150px;
  border-radius: 75px;
  z-index: 8;
}

.comment_list {
  width: 200px;
  height: 435px;
  box-sizing: border-box;
  padding: 10px;
  list-style: none;
  background: url("./assets/images/line.png") left center no-repeat;
  overflow: hidden;
  position: relative;
}

.comment_list dl {
  padding-left: 55px;
  position: relative;
  margin-bottom: 20px;
}

.comment_list dt {
  position: absolute;
  left: 4px;
  top: 0px;
}

.comment_list dt img {
  width: 40px;
  height: 40px;
  border-radius: 20px;
}

.comment_list dd {
  font-size: 12px;
}

.comment_list .name {
  font-weight: bold;
  color: #333;
  margin-top: 5px;
}

.comment_list .detail {
  color: #666;
  margin-top: 5px;
  line-height: 18px;
}

.audio_con {
  height: 50px;
  background-color: #f1f3f4;
  border-bottom-left-radius: 4px;
  border-bottom-right-radius: 4px;
}

.myaudio {
  width: 800px;
  height: 40px;
  margin-top: 5px;
  outline: none;
  background-color: #f1f3f4;
}

/* 旋转的动画 */
@keyframes Rotate {
  from {
    transform: rotateZ(0);
  }

  to {
    transform: rotateZ(360deg);
  }
}

/* 旋转的类名 */
.autoRotate {
  animation-name: Rotate;
  animation-iteration-count: infinite;
  animation-play-state: paused;
  animation-timing-function: linear;
  animation-duration: 5s;
}

/* 是否正在播放 */
.playing {
  animation-play-state: running;
}

.play_bar {
  position: absolute;
  left: 200px;
  top: -10px;
  z-index: 10;
  transform: rotate(-25deg);
  transform-origin: 12px 12px;
  transition: 1s;
}

/* 播放杆 转回去 */
.play_bar.playing {
  transform: rotate(0);
}
style>
songList.vue(子组件)左边歌曲列表部分
<template>
  
  <div class="song_wrapper" ref="song_wrapper">
    <ul class="song_list">
      <li v-for="(item, index) in list" :key="index" @dblclick="play(item.id)">{{item.name}}li>
    ul>
  div>
template>

<script>
// 要给左边歌曲列表滚动条,导入IScroll
import iscroll from "iscroll";

export default {
  data() {
    return {
      // 存放搜索对应的所有歌曲的数组
      list: [],
      //   滚动条实例
      myIscroll: "",
       
    };
  },
  methods: {
    //   滚动条刷新方法
    reload() {
      //$nextTick只适用于vue,它自动帮每次增加了新的li渲染完毕之后就帮我们刷新
      this.$nextTick(() => {
        this.myIscroll.refresh();
      });
    },
    // 双击左边的歌曲li播放音乐
    play(id) {
        // 调用主组件的getUrl方法
        this.$parent.getSongInfo(id)
    }
  },
  //列表渲染出来就有滚动条
  mounted() {
    this.myIscroll = new iscroll(this.$refs.song_wrapper, {
      mouseWheel: true,
      scrollbars: true
    });
  }
};
script>

<style>
style>
middle.vue(子组件)中间动画部分
<template>
  <div class="player_con">
    <img src="../assets/images/player_bar.png" class="play_bar" :class="{playing:playing}"/>
    
    <img src="../assets/images/disc.png" class="disc autoRotate" :class="{playing:playing}"/>
    <img :src="picUrl" class="cover autoRotate" :class="{playing:playing}"/>
  div>
template>

<script>
export default {
    data() {
        return {
            // 控制是否加playing这个class的变量
            playing:false,
            // 中间图片封面
            picUrl:'https://timgsa.baidu.com/timg?image&quality=80&size=b9999_10000&sec=1589124884781&di=a6c25dd1c055f8afd1ee1fcb7008c5d0&imgtype=0&src=http%3A%2F%2Fb-ssl.duitang.com%2Fuploads%2Fitem%2F201704%2F11%2F20170411194843_HGBrC.thumb.700_0.jpeg'
        }
    },
};
script>

<style>
style>
comments.vue(子组件)右边评论区部分
<template>
  <div class="comment_list" ref="comment_list">
    <div>
      
      <dl v-for="(item, index) in list" :key="index">
        <dt>
          <img :src="item.user.avatarUrl" alt />
        dt>
        <dd class="name">{{item.user.nickname}}dd>
        <dd class="detail">{{item.content}}dd>
      dl>
    div>
  div>
template>

<script>
// 1.导入滚动条外部插件
import iscroll from "iscroll";
export default {
  data() {
    return {
      // 存放评论的数组
      list: [],
      //评论区滚动条实例
      myIscroll: ""
    };
  },
  methods: {
    //   刷新滚动条方法
    reload() {
      this.$nextTick(() => {
        this.myIscroll.refresh();
      });
    }
  },

  mounted() {
    //   使用 实例化滚动条
    this.myIscroll = new iscroll(this.$refs.comment_list, {
      mouseWheel: true,
      scrollbars: true
    });
  }
};
script>

<style>
style>

效果展示说明: 该播放器功能分成三个部分,分别是左边歌曲列表,中间动画,右边评论区.
分开开发更有利于团队协作,
现在还没学兄弟之间组件怎么传值所以发送请求歌曲的播放地址,评论,图片封面,的ajax请求都写在主组件在



05-Vue-cli项目创建:

脚手架就是个项目模板 , 相当于把整个文件基本目录结构搭好了,把必要的文件也建好 了,让我们省了很多事情。脚手架安装: npm install -g @vue/cli ,vue -V 能出现版本号就是安装成功,最好npm配置指向淘宝镜像

创建项目:

1.创建时路径不要选错,就是命令的路径要是需要创建项目的文件夹下
    完美选择不出错路径方法:在文件夹相应路径下的地址栏输入cmd —再 回车
2.运行创建命令:vue create 项目名 //这里项目名不要有中文,不要有大写字母,不要搞特殊符号,尽可能有意义 ,像普    通变量命名一样
3.弹出的对话框先选择默认的选项(如下图)在这里插入图片描述
4.稍等一会,等进度条走完 提示如下画面说明成功了,如下图:在这里插入图片描述
5.进入项目文件夹(就是项目名的文件夹):`cd 项目名 直接根据提示即可
6.运行项目:npm run serve
7.稍等片刻 ,出现如下效果说明成功了06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第8张图片

报错的原因:

1.创建命令是create输成了creat
2.06-vue(父(主)组件与子组件之间的传值,export与import的基本使用,一个分组件完成的音乐播放器案例,脚手架初识别)_第9张图片

  a.网络问题换wifi
  b.终端的权限问题,新建管理员模式的终端
  c. 当前这个文件夹,这个文件被其他软件占用:关闭所有可能影响的软件(重启)
  d. npm包管理工具的问题:(昨天那篇安装时已做说明)用yarn来安装或. 清除缓存npm cache clean -f 再重新创建项目
3.创建项目时,用到了第三方模块,文件太多了git人为没有必要管,提示你一下,选择不再显示就OK了,vue-cli创建项目时,已经设置了git忽略文件 就在.gitignore文件当

实在无法创建项目的解决方案(重要)

  1. vue-cli创建项目的本质是:
    1. 创建文件夹
    2. 下载第三方模块
    3. 创建项目的基本结构
    4. 设置各个文件之间的关系
    5. 创建git仓库
  2. 找一个可以创建项目的人,创建一个项目
    1. 删除node_modules(这个里面都是一些第三方模块)
    2. 发给你
    3. 你使用npm i安装项目中用到的第三方模块(会根据package-lock.json文件下载回来)
    4. 运行项目npm run serve

Vue-cli项目结构说明:

  • node_modules 第三方模块包,也就是项目所需要用到的依赖包
  • public
    • favicon.ico 运行项目时在网页上显示 的小图标
    • index.html 项目的页面模板 ,也就是项目运行最开始,是先执行这个模板html的
  • src 项目开发主体就是在这个src目录下面
    • assets 项目所需要的静态资源,如css,图片等文件
    • components 项目中的单文件组件都放这里
    • App.vue 入口组件 ,可以理解为一个项目就是一个app.vue的单文件组件,只不过里面包括了很多小组件
    • main.js 入口js文件,进入项目会优先执行main.js以此来运行app.vue
  • .gitignore 让git忽略某些文件,文件夹
  • babel.config.js js编译的设置,比如把高版本的js转为低版本的js,让项目达到更好兼容性
  • package-lock.json 项目模块详细信息,包括来源。
  • package.json 项目基本信息
  • README.md 项目说明

你可能感兴趣的:(笔记)