Vue进阶(1)

1.slot插槽(内容分发)


内容分发:把父组件的内容分发到子组件里面 a.单个slot b.具名slot(具有名字的插槽) 混合父组件的内容与子组件自己的模板-->内容分发 父组件模板的内容在父组件作用域内编译; 子组件模板的内容在子组件作用域内编译
  <body>
    <div id="box">
      <child>
        <div slot='a'>aaaaaa</div>
        <div slot="b">bbbbbb</div>
      </child>
      <swiper>
        <li v-for='data in dataList'>
          {{data}}
        </li>
      </swiper>
    </div>
    <script>
      Vue.component('child',{
        template:`<div>
          <slot name='a'></slot>
            child
          <slot name='b'></slot>
        </div>`
      })

      Vue.component("swiper",{
        template:`<div>
          <ul>
            <slot></slot>
          </ul>
        </div>`
      })

      new Vue({
        el:"#box",
        data:{
          dataList:['111','222','333']
        }
      })
    </script>
  </body>

实例

  <body>
    <div id="box">
     <!-- <button @click='isShow=!isShow'>click</button> -->
     <navbar>
      <button @click='isShow=!isShow'>navbar-button</button>
     </navbar>
     <sidebar v-show='isShow'></sidebar>

    </div>
    <script>
      Vue.component('navbar',{
        template:`<div>
            navbar
          <slot></slot>
        </div>`,
      }),
      Vue.component('sidebar',{
        template:`<div style='background:yellow;width:200px;'>
          <ul>
            <li>1111</li>
            <li>1111</li>
            <li>1111</li>
          </ul>
          </div>`
      })
      new Vue({
        el:"#box",
        data:{
          isShow:false
        },
      })
    </script>
  </body>

2.transition过渡


Vue在插入、更新或者移除DOM时,提供多种不同方式的应用过渡效果。

1.单元素/组件过渡

CSS过渡
CSS动画
结合animate.css动画库

    <script src="../js/vue.js"></script>
    <style>
      .kerwinfade-enter-active,.kerwinfade-leave-active{
        transition:all 1.5s;
      }
      .kerwinfade-enter,.kerwinfade-leave-to{
        opacity:0;
        transform:translateX(100px);
      }

      .kerwinbounce-enter-active{
        animation:bounce-in .5s;
      }
      .kerwinbounce-leave-active{
        animation:bounce-in .5s reverse;
      }
      @keyframes bounce-in{
        0%{
          opacity: 0;
          transform:translateX(100px);
        }
        100%{
          opacity: 1;
          transform: translateX(0px);
        }
      }
    </style>
  <body>
    <div id="box">
      <button @click='isShow=!isShow'>click</button>
      <transition name='kerwinfade'>
        <div v-show='isShow'>11111</div>
      </transition> 
      <transition name='kerwinbounce'>
        <div v-show='isShow'>22222</div>
      </transition> 
    </div>
    <script>
      var vm = new Vue({
        el:"#box",
        data:{
          isShow:false
        }
      })
    </script>
  </body>

2.多个元素过渡(设置key)

多个元素过渡解决方案:
1. 标签名不同(diff算法标签名相同会复用),采用v-if v-else
2. 当有相同标签名的元素切换时,需要通过key特性设置唯一的值来标记以让Vue区分它们,否则Vue为了效率只会替换相同标签内部的内容。
mode:in-out 先来后走
mode:out-in 先走后来
不设置的话,多个元素同时进行

    <style>
      .kerwinbounce-enter-active{
        animation:bounce-in .5s;
      }
      .kerwinbounce-leave-active{
        animation:bounce-in .5s reverse;
      }
      @keyframes bounce-in{
        0%{
          opacity: 0;
          transform:translateX(100px);
        }
        100%{
          opacity: 1;
          transform: translateX(0px);
        }
      }
    </style>
  <body>
    <div id="box">
      <button @click='isShow=!isShow'>click</button>
      <transition name='kerwinbounce' mode='in-out'>
        <p v-if='isShow' key='1'>11111</p>
        <!-- <div v-else>22222</div> -->
        <p v-else key='2'>22222</p>
      </transition>
    </div>
    <script>
      var vm = new Vue({
        el:'#box',
        data:{
          isShow:false
        }
      })
    </script>
  </body>

3.多个组件过渡

    <script src="../js/vue.js"></script>
    <style>
      .fade-enter-active,
      .fade-leave-active {
        transition: all 1.5s;
      }
      .fade-enter,
      .fade-leave-to {
        opacity: 0;
        transform: translateX(100px);
      }

      .bounce-enter-active {
        animation: bounce-in 0.5s;
      }
      .bounce-leave-active {
        animation: bounce-in 0.5s reverse;
      }
      @keyframes bounce-in {
        0% {
          opacity: 0;
          transform: translateX(100px);
        }
        100% {
          opacity: 1;
          transform: translateX(0px);
        }
      }
    </style>
  <body>
    <div id="box">
      <keep-alive>
        <transition name='bounce' mode='out-in'>
          <component :is='who'></component>
        </transition>
      </keep-alive>
      <footer>
        <ul>
          <li><a @click='who="home"'>首页</a></li>
          <li><a @click='who="list"'>列表页</a></li>
          <li><a @click='who="shopcar"'>购物车页面</a></li>
        </ul>
      </footer>
    </div>
    <script>
      var vm = new Vue({
        el:"#box",
        data:{
          who:'home'
        },
        components:{
          'home':{
            template:`<div>home</div>`
          },
          'list':{
            template:`<div>list</div>`
          },
          'shopcar':{
            template:`<div>shopcar</div>`
          }
        }
      })
    </script>
  </body>

4.列表过渡(设置key)

<transition-group>不同于transition,
它会以一个真实元素呈现:默认为一个<span>。
你也可以通过tag特性更换为其他元素。
    <script src="../js/vue.js">
      /* 列表过渡(设置key)
          <transition-group>不同于transition,它会以一个真实元素呈现:默认为一个<span>
          你也可以通过tag特性更换为其他元素
          提供唯一的Key属性值
      */
    </script>
    <style>
      .bounce-enter-active {
        animation: bounce-in 0.5s;
      }
      .bounce-leave-active {
        animation: bounce-in 0.5s reverse;
      }
      @keyframes bounce-in {
        0% {
          opacity: 0;
          transform: translateX(100px);
        }
        100% {
          opacity: 1;
          transform: translateX(0px);
        }
      }
    </style>
  <body>
    <div id="box">
      <input type="text" v-model='mytext'>{{mytext}}
      <button @click='handleAddClick'>add</button>

      <!-- <ul> -->
        <transition-group tag='ul' name='bounce'>
          <li v-for='(data,index) in dataList' :key='data'>
              {{data}}----{{index}}
            <button @click='handleDelClick(index)'>del</button>
          </li>
      </transition-group>
      <!-- </ul> -->
    </div>
    <script>
      var vm = new Vue({
        el:"#box",
        data:{
          mytext:'',
          dataList:[]
        },
        methods:{
          handleAddClick(){
            
          },
          handleDelClick(index){

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

3.生命周期

  1. 生命周期各个阶段
  2. 生命周期钩子函数的触发条件与作用
    在这里插入图片描述
  <body>
    <div id="box">
      <input type="button" value="修改msg" @click="msg='No'" />
      <h3 id="h3">{{msg}}</h3>
    </div>

    <script>
      var vm = new Vue({
        el: "#box",
        data: {
          msg: "ok",
        },
        methods: {
          show() {
            console.log("执行了show方法");
          },
        },
        beforeCreate() {
          //这是我们遇到的第一个生命周期函数,表示实例完全被创建出来之前,会执行它
          //console.log(this.msg);
          //this.show();
          /* 注意:在beforeCreate生命周期函数执行的时候,data和methods中的数据都还没有初始化 */
        },
        created() {
          //这是遇到的第二个生命周期函数
          //console.log(this.msg); //ok
          //this.show();  //执行了show方法
          /* 在created中,data和methods都已经被初始化好了! */
          /* 如果要调用methods中的方法,或者操作data中的数据,最早只能在created中操作 */
        },
        beforeMount() {
          //这是遇到的第三个生命周期函数,表示模板已经在内存中编辑完成了,但是尚未把模板渲染到页面上
          //console.log(document.getElementById("h3").innerText); //{{msg}}
          /* 在beforeMount执行的时候,页面中的元素,还没有被真正替换过来,只是之前写的一些模板字符串 */
        },

        mounted() {
          //这是遇到的第四个生命周期函数,表示内存中的模板已经真实的挂载到了页面中,用户已经可以看到渲染好的页面了
          //console.log(document.getElementById("h3").innerText);
          /* 注意:mounted是实例创建期间的最后一个生命周期函数,当执行完mounted就表示,实例已经被完全创建好了,此时,如果没有其他操作的话,这个实例就静静的躺在我们的内存中一动不动 */
        },

        //接下来的是运行中的两个事件
        beforeUpdate() {
          //这时候,表示我们的页面还没有被更新,数据肯定被更新了
          //console.log(document.getElementById("h3").innerText);//Ok
          //console.log("data中的msg数据是:" + this.msg);//No
          /* 得出结论:当执行beforeUpdate的时候,页面中的显示的数据,还是旧的,此时data数据是最新的,页面尚未和最新的数据保持同步 */
        },
        updated() {
          console.log(document.getElementById("h3").innerText);
          console.log("data中的msg数据是:" + this.msg);
          /* update事件执行的时候,页面和data数据已经保持同步了,都是新的 */
        },
        beforeDestory() {},
        destroyed() {},
      });
    </script>
  </body>

过滤器

  <body>
    <div id="box">
      <ul>
        <li v-for='data in dataList' :key='data.id'>
          <h3>{{data.nm}}</h3>
          <!-- <img :src="changepath(data.img)"> -->
          <img :src="data.img | kerwinpath">
        </li>
      </ul>
    </div>
    <script>
      Vue.filter("kerwinpath",function(data){
        return data.replace('w.h','128.180')
      })  

      var vm = new Vue({
        el:"#box",
        data:{
          dataList:[]
        },
        mounted(){
          axios.get('test.json').then(res=>{
            console.log(res.data);
            this.dataList=res.data.movieList
          })
        },
        methods:{
          // changepath(path){
          //   return path.replace('w.h','128.180')
          // }
        }
      })
    </script>
  </body>

4.swiper学习

  <body>
    <div id="box">
      <div class="swiper-container a">
        <div class="swiper-wrapper">
          <div class="swiper-slide" v-for='data in dataList'>
            {{data}}
          </div>
        </div>
        <div class="swiper-pagination"></div>
      </div>
    </div>

    <script>
      new Vue({
        el:"#box",
        data:{
          dataList:[]
        },

        mounted(){
          setTimeout(()=>{
            this.dataList=['1111','2222','3333'] // 状态改完,异步更新dom
            // swiper 初始化过早
          },2000)
        },
        updated(){
          new Swiper(".a",{
              loop:true,
              pagination:{
                el:"'.swiper-pagination'"
              }
            })
        }
      })
    </script>
  </body>

swiper组件封装
自定义封装swiper组件(基于swiper)
注意:防止swiper初始化过早

  <body>
    <div id="box">
      <swiper :key="{datalist.length;">
        <div class="swiper-slide" v-for="data in datalist">
          {{data}}
        </div>
      </swiper>
    </div>

    <script>
      Vue.component("swiper", {
        template: `<div class="swiper-container a">
        <div class="swiper-wrapper">
         <slot></slot>
        </div>
          <div class="swiper-pagination"></div>
        </div>`,

        mounted() {
          new swiper(".a", {
            //direction:'vertical'
            loop: true,
            //如果需要分页器
            pagination: {
              el: ".swiper-pagination",
            },
          });
        },
      });

      new Vue({
        el: "#box",
        data: {
          datalist: [],
        },
        mounted() {
          setTimeout(() => {
            this.datalist = ["111", "222", "333"];
          }, 2000);
        },
      });
    </script>
  </body>

6.自定义指令

自定义指令:操作底层dom
定义在谁身上,就能拿到谁的dom节点

  <body>
    <div id="box">
      <div v-hello='"red"'>111111</div>
      <div v-hello='"yellow"'>222222</div>
      <div v-hello='mycolor'>333333</div>
    </div>
    <script>
      Vue.directive('hello',{
        inserted(el,bind){
          // 指令-生命周期-创建 只会执行一次
          // 插入
          // console.log(el)
          // console.log(bind.value)
          el.style.background=bind.value
        },
        update(el,bind){
          // 指令-生命周期-更新
          el.style.background=bind.value
        }
      })

      var vm = new Vue({
        el:'#box',
        data:{
          mycolor:'blue'
        }
      })
    </script>
  </body>

指令轮播

  <body>
    <div id="box">
      <div class="swiper-container a">
        <div class="swiper-wrapper">
          <div
            class="swiper-slide"
            v-for="(data,index) in list"
            v-swipe="{
              index:index,
              length:list.length
            }"
          >
            {{data}}
          </div>
        </div>
        <!-- 如果需要分页器 -->
        <div class="swiper-pagination"></div>
      </div>
    </div>

    <script>
      Vue.directive("swipe", {
        inserted(el, bind) {
          console.log(bind.value);
          if (bind.value.index === bind.value.length - 1) {
            new Swiper(".a", {
              loop: true,
              pagination: {
                el: ".swiper-pagination",
              },
            });
          }
        },
      });

      new Vue({
        el: "#box",
        data: {
          list: [],
        },
        mounted() {
          setTimeout(() => {
            this.list = ["111", "222", "333"];
          }, 2000);
        },
      });
    </script>
  </body>

7.单文件/多文件组件

创建.vue文件,要想让单文件被使用
需要用到webpack将vue文件转为html文件、es6转es5,脚手架来配置webpack
只安装一次脚手架就行,一个全局就够了
npm install -g @vue/cli(一次安装) node-sass需要单独处理
#or
yarn global add @vue/cli
vue-cli3.0的使用
npm install -g @vue/cli(一次安装) node-sass需要单独处理

按住shift,右键,可以直接进入该目录下的windows powerShell中

创建一个项目
vue create myapp
    npm run serve 开发环境构建
    npm run build 生产环境构建
    npm run lint   代码检测工具(会自动修正)

yes
manually select features
Babel(babel es6转es5) Router,Vuex(复杂状态管理), CSS pre-processors(CSS预处理器,想用SCSS、less可以安装), Linter/Formatter(eslint规范,保持风格一致性,该用双引号还是单引号等)
yes
Sass/SCSS(with node-sass)
Standard
Lint an fix on commit 
In dedicated config files 
yes
自定义名字

如果遇到斜杠等无法安装,直接ctrl+c退出  手动去目录下删掉module文件,
然后cd myapp进入myapp中,执行cnpm i接着安装package.json里面的模块

入口文件main.js

启动 cnpm run serve
查看ip 进入浏览器输入localhost:8080 启动成功

下载 Vetur插件
npm run lint 自动修正代码
npm run build 上线代码,生成dist文件夹交给后端

入口页面 public/index.html
<div id="box"></div>
入口文件 src/main.js
根组件 src/App.vue

main.js

import Vue from 'vue' // ES6 模块导入方式
import App from './App.vue'
// import router from './router'
// import store from './store'

Vue.config.productionTip = false

new Vue({
  // router,
  // store,
  render: h => h(App)
}).$mount('#box')
<template> -html代码,最多可以包含一个
<script> -js代码,最多可以包含一个
<style> -css代码,可以包含多个,src的路径是相对的
style标签 加上scoped属性,css局部生效
style标签 加上lang='scss'  支持scss

    1.vue create *** 一个项目
    2.写项目(在src下编译 ,vue组件放在src中的component下)
        npm run serve 开发环境构建
        npm run build 生产环境构建
        npm run lint   代码检测工具(会自动修正)
    3.vs终端上面,cd myapp中,输入ls,输入npm run lint自动修复错误
    4.上线项目
        新开一个终端,右键主文件,在终端打开 即myapp下
        输入 npm run build,自动生成dist文件

        express版本中将命令工具分家出来了(项目地址:https://github.com/expressjs/generator),所以我们还需要安装一个命令工具,命令如下:
        npm install -g express-generator      express-generator 是项目生成器
        express --version 

        右键进入项目所在的路径中的windows powershell中 
        1.输入express -e backend
        2.cd backend
        3.cnpm i
        4.复制dist里面的文件到backend里的public文件夹中
        5.后端启动项目 npm start
        6.浏览器打开localhost:3000

反向代理配置
    跨域:是指浏览器不能执行其他网站的脚本,它是由浏览器的同源策略造成的,是浏览器对JS实施的安全限制
    无法跨域是浏览器对于用户安全的考虑,如果自己写个没有同源策略的浏览器,完全不用考虑跨域问题
    同源策略限制了以下行为
        Cookie、 LocalStorage和IndexDB无法读取
        DOM和JS对象无法获取
        Ajax请求发送不出去
    狭义的同源就是指:域名、协议、端口均为相同

    后端接口与前端接口一定会有跨域的现象  
        前端localhost:8080
        后端localhost:3000

    例:8080请求猫眼 跨域
    在network中随便点击一个文件,发现Access-Control-Allow-Origin: https://maoyan.com 这是允许请求
    但是有一些网站不允许请求,需要配置反向代理
    cd myapp文件夹下输入npm install --save axios(下载库)
    引入库  import axios from 'axios'
    调用接口
    反向代理配置 vue.config.js是一个可选的配置文件,如果项目的(和 package.json同级的)根路径存在这个文件,那么它会被@vue/cli-service自动加载(https://cli.vuejs.org/zh/config/#css-loaderoptions)
    创建一个vue.config.js文件
    如果你的前端应用和后端 API 服务器没有运行在同一个主机上,你需要在开发环境下将 API 请求代理到 API 服务器。
    这个问题可以通过 vue.config.js 中的 devServer.proxy 选项来配置。

    只要更改了配置文件,一定要重启服务器 ctrl+ c  npm start

App.vue

<template>
  <div>
    hello vue
    <input type = "text" ref='mytext'>
    <button @click='handleAdd()'>add</button>
    <ul>
      <li v-for = 'data in dataList' :key='data'>
        {{ data }}
      </li>
    </ul>

    <navbar>
      <button @click="isShow=!isShow">navbar-click</button>
    </navbar>
    <sidebar v-show='isShow'></sidebar>

  </div>
</template>

<script>
// commonJS  module.exports
import navbar from './components/Navbar'
import sidebar from './components/Sidebar'
import axios from 'axios'
// 全局组件
// import Vue from 'vue'
// Vue.component('navbar', navbar)
// Vue.component('sidebar', sidebar)
// ES6 导出
export default {
  data () {
    return {
      dataList: [],
      isShow: false
    }
  },
  methods: {
    handleAdd () {
      // console.log('add', this.$refs.mytext.value)
      this.dataList.push(this.$refs.mytext.value)
    }
  },

  mounted () {
    axios.get('/ajax/mostExpected?ci=264&limit=10&offset=0&token=&optimus_uuid=05344D607A4411EAA227BF8336DA36C76B6E77239DE44EFD988866B692B8D66B&optimus_risk_level=71&optimus_code=10').then((res) => {
      console.log(res.data)
    })
  },
  components: {
    navbar: navbar,
    sidebar: sidebar
  }
}
</script>

<style lang="scss">
  ul {
    list-style: none;
    li {
      background:yellow
    }
  }
</style>

navbar.vue

<template>
    <nav>
        navbar-<slot></slot>
    </nav>
</template>

sidebar.vue

<template>
    <aside>
        sidebar
        <ul>
            <li>1</li>
            <li>2</li>
            <li>3</li>
        </ul>
    </aside>
</template>

<style lang="scss" scoped>
    ul {
        li {
            background:blue
        }
    }
</style>

vue.config.js

module.exports = {
    devServer: {
      proxy: {
        '/ajax': {
          target: 'https://m.maoyan.com',
        //   ws: true,
          changeOrigin: true
        },
        /* '/foo': {
          target: '<other_url>'
        } */
      }
    }
  }
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值