zf-6-vue (26天)

zf-6-vue (26天)

二.配置vue-config.js

let path = require('path');
let skeletionWebpackPlugin = require('vue-skeleton-webpack-plugin');


module.exports = {
    publicPath:process.env.NODE_ENV === 'production'? '/vue-project':'/',
    outputDir:'myassets', // 输出路径
    assetsDir:'static', // 生成静态目录的文件夹
    runtimeCompiler: true, // 是否可以使用template模板
    parallel:require('os').cpus().length > 1, //多余1核cpu时 启动并行压缩
    productionSourceMap:false, //生产环境下 不使用soruceMap

    // https://github.com/neutrinojs/webpack-chain
    chainWebpack:config=>{
        // 控制webpack内部配置
        config.resolve.alias.set('component',path.resolve(__dirname,'src/components'));
    },
    // https://github.com/survivejs/webpack-merge
    configureWebpack:{
        // 新增插件等
        plugins:[
            new SkeletonWebpackPlugin({
                webpackConfig: {
                    entry: {
                        app: resolve('./src/skeleton.js')
                    }
                }
            })
        ]
    },
    devServer:{ // 配置代理
        proxy:{
            '/api':{
                target:'http://a.zf.cn:3000',
                changeOrigin:true
            }
        }
    },
    pages: {
        index: { // 首页入口
            entry: "./src/main.js"
        },
        other: { // 其他页面入口
            entry: './src/a.js',
            chunks:['other'] // 引入的资源
        }
    },
    // 第三方插件配置
    pluginOptions: {
        'style-resources-loader': {
            preProcessor: 'less',
            patterns: [
                // 插入全局样式
                path.resolve(__dirname,'src/assets/common.less'), 
            ],
        }
    }
}

三.封装axios

import axios from 'axios';
let baseUrl = process.env.NODE_ENV !== 'production'?'http://localhost:8080':'/';
class AjaxRequest{
  constructor(){
      this.baseURL = baseUrl; // 配置默认路径
      this.requestQueue = {}; // 缓存当前请求队列 用来操作loading的显示或者隐藏
  }
  configInterceptors(instance,url){
      // 配置请求拦截
      instance.interceptors.request.use( (config) => {
          //  loading效果 开始请求前显示loading
          if(Object.keys(this.requestQueue).length === 0){
              console.log('显示loading');
          }
          this.requestQueue[url] = config.url;
          return config;
      });
      // 配置响应拦截
      instance.interceptors.response.use(res=>{
          // 取消loading效果
          delete this.requestQueue[url];
          if(Object.keys(this.requestQueue).length === 0){
              console.log('取消loading');
          };
          if(res.status !== 200){
              return Promise.reject(res);
          }else{
              return res.data;
          }
      })

  }
  request(config){
      // 创建一个axios实例
      let instance = axios.create();
      // axios(config);
      config = {baseURL:this.baseURL,...config};
      this.configInterceptors(instance,config.url);
      return instance(config);
  }
}
export default new AjaxRequest();

组件间通信 ===========================

安装工具

  • npm install @vue-cli@3 -g
  • npm install -g @vue/cli-service-global@3 -g

组件通信

  • 父传递给子数据 props emit

  • $parent $children

  • $attrs $listeners

  • provide inject 和 context (可以在父组件中声明一个公共数据),在子组件中可以注入原理 (比较混乱,名称问题 他不会在业务代码中使用) 组件库 多级通信为了方便你可以使用provide

  • ref 获取真实dom元素,如果放到组件上 代表的是 当前组件的实例 ,父组件中可以直接获取子组件的方法或者数据

  • eventbus ( p a r e n t , parent, parent,children) 绑定 o n 只 能 通 过 绑 定 on 只能通过绑定 onon的那个组件来触发 (混乱)

菜单组件 ====================

App.vue调用 menu.vue 传入data
menu.vue 简析data发现children渲染调用Resub渲染,没有的话调用item直接渲染
Resub 核心,发现children调用自己,否则调用item

<zf-submenu >
      <!-- 标题 -->
      <template slot="title">{{data.name}}</template>
      <!-- 内容 -->
      <template v-for="menu in data.children">
          <!-- 3) 递归当前自己 -->
          <a-sub :data="menu" :key="menu.id" v-if="menu.children"></a-sub>
          <zf-menu-item v-else :key="menu.id">{{menu.name}}</zf-menu-item>
      </template>
  </zf-submenu>
</template>
message 应用组件
this.$message.success({
   message: "你好",
   duration: 3000
 });
messge的源码
import MessageComponent from './Message.vue';
import Vue from 'vue';

// 单例
let instance;
let getVueInstance = () => {
    // 此instance 是全局的
    instance = new Vue({ // 就一个孩子
        render: h => h(MessageComponent)
    }).$mount();
    // 把生成的结果放到页面
    document.body.appendChild(instance.$el);
}
const Message = {
    success(options) {
        // 点击弹出层 需要将.vue文件挂载到 内存中

        // 就是将这个 new Vue的操作 只做一次
        // 默认如果实例不存在 我就创建一个实例
        !instance && getVueInstance();
        // 将渲染好的内容 放到 页面中
        instance.$children[0].add({
            ...options,
            type:'success'
        });
        // $mount() document.body.appendChild
        // options 就是当前弹出来的框
        // 通过数据来驱动
    },
    info(){

    },
    warn(){}
}

export {
    Message
}

export default {
    // _Vue 是当前的构造函数 ,默认Vue.use 就会使用调用这个方法
    install(){
       // 1) 注册全局组件 2) 注册全局指令 3) 往原型上添加方法 、属性 
       let $message = {}
       Object.keys(Message).forEach(key=>{
            $message[key] = Message[key];
       })
       // 一般使用新对象时 就采用拷贝的方式
       Vue.prototype.$message = $message
    }
}
// vuex vue-router 表格组件 ,单元测试 cli axios

// 讲项目实战

// render 函数

render

render函数和JSX应用(五)

一.模板缺陷

模板的最大特点是扩展难度大,不易扩展。可能会造成逻辑冗余

<Level :type="1">哈哈</Level>
<Level :type="2">哈哈</Level>
<Level :type="3">哈哈</Level>

Level组件需要对不同的type产生不同的标签

<template>
 <h1 v-if="type==1">
  <slot></slot>
 </h1>
 <h2 v-else-if="type==2">
  <slot></slot>
 </h2>
 <h3 v-else-if="type==3">
  <slot></slot>
 </h3>
</template>
<script>
export default {
 props: {
  type: {
   type: Number
  }
 }
};
</script>

二.函数式组件

函数式组件没有模板,只允许提供render函数

export default {
 render(h) {
  return h("h" + this.type, {}, this.$slots.default);
 },
 props: {
  type: {
   type: Number
  }
 }
};

复杂的逻辑变得非常简单

三.JSX应用

使用jsx会让代码看起来更加简洁易于读取

export default {
 render(h) {
  const tag = "h" + this.type;
  return <tag>{this.$slots.default}</tag>;
 },
 props: {
  type: {
   type: Number
  }
 }
};

四.render方法订制组件

编写List组件可以根据用户传入的数据自动循环列表

<List :data="data"></List>
<script>
import List from "./components/List";
export default {
 data() {
  return { data: ["苹果", "香蕉", "橘子"] };
 },
 components: {
  List
 }
};
</script>

<!-- List组件渲染列表 -->
<template>
 <div class="list">
  <div v-for="(item,index) in data" :key="index">
   <li>{{item}}</li>
  </div>
 </div>
</template>
<script>
export default {
 props: {
  data: Array,
  default: () => []
 }
};
</script>

通过render方法来订制组件,在父组件中传入render方法

<List :data="data" :render="render"></List>
render(h, name) {
   return <span>{name}</span>;
 }

我们需要createElement方法,就会想到可以编写个函数组件,将createElement方法传递出来

<template>
 <div class="list">
  <div v-for="(item,index) in data" :key="index">
   <li v-if="!render">{{item}}</li>
   <!-- 将render方法传到函数组件中,将渲染项传入到组件中,在内部回调这个render方法 -->
   <ListItem v-else :item="item" :render="render"></ListItem>
  </div>
 </div>
</template>
<script>
import ListItem from "./ListItem";
export default {
 components: {
  ListItem
 },
 props: {
  render: {
   type: Function
  },
  data: Array,
  default: () => []
 }
};
</script>

ListItem.vue调用最外层的render方法,将createElement和当前项传递出来

<script>
export default {
 props: {
  render: {
   type: Function
  },
  item: {}
 },
 render(h) {
  return this.render(h, this.item);
 }
};
</script>

五.scope-slot

使用v-slot 将内部值传即可

<List :arr="arr">
    <template v-slot="{item}">
        {{item}}
    </template>
</List>

<div v-for="(item,key) in arr" :key="key">
    <slot :item="item"></slot>
</div>

六.编写可编辑表格

基于iview使用jsx扩展成可编辑的表格

<template>
<div>
  <Table :columns="columns" :data="data"></Table>
</div>
</template>
<script>
import Vue from 'vue';
export default {
  methods:{
    render(h,{column,index,row}){
      let value = row[column.key];
      return <div on-click={(e)=>this.changeIndex(e,index)} >
      {this.index === index? 
        <i-input type="text" value={value} on-input={(value)=>{
          this.handleChange(value,column,row)
        }} onOn-enter={()=>this.enter(row,index)}/>:
        <span>{value}</span>
      }
      </div>
    },
    enter(row,index){
      this.data.splice(index,1,row);
      this.index = -1;
    },
    handleChange(value,column,row){
      row[column['key']]= value;
    },
    changeIndex(e,index){
      this.index = index;
      this.$nextTick(()=>{
        e.currentTarget.getElementsByTagName("input")[0].focus()
      })
    }
  },
  data() {
    return {
      index:-1,
      columns: [
        {
          title: 'Name',
          key: 'name',
          render:this.render
        },
        {
          title: 'Age',
          key: 'age',
        },
        {
          title: 'Address',
          key: 'address',
        },
      ],
      data: [
        {
          name: 'John Brown',
          age: 18,
          address: 'New York No. 1 Lake Park',
          date: '2016-10-03',
        },
        {
          name: 'Jim Green',
          age: 24,
          address: 'London No. 1 Lake Park',
          date: '2016-10-01',
        },
        {
          name: 'Joe Black',
          age: 30,
          address: 'Sydney No. 1 Lake Park',
          date: '2016-10-02',
        },
        {
          name: 'Jon Snow',
          age: 26,
          address: 'Ottawa No. 2 Lake Park',
          date: '2016-10-04',
        },
      ],
    };
  },
};
</script>
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值