Vue入门

if for

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-if-for</title>

    <!--    导入vue.js-->
    <script src="/vue.js/vue.js"></script>
</head>
<body>

<!--view层-->
<div id="app">
    <h1 v-if="ok">Yes</h1>
    <h1 v-else>No</h1>

    <h1 v-if="type==='A'">A</h1>
    <h1 v-else-if="type==='B'">B</h1>
    <h1 v-else="type==='C'">C</h1>

    <li v-for="(item,index) in items">
        {{item.message}}--{{index}}
    </li>
</div>

<script type="text/javascript">
    let vm =new Vue({
        el:"#app",
        //Model层
        data:{
            ok:true,
            type:"A",
            items:[
                {message:"111"},
                {message:"222"},
                {message:"333"},
            ]
        }
    });
</script>

</body>
</html>

事件

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-事件</title>

</head>
<body>

<div id="app">
    <button v-on:click="message+=1">click me</button>
    <h1>{{message}}</h1>

    <button v-on:click="say('hi')">say Hi</button>
    <button v-on:click="say('hello')">say hello</button>
    <button v-on:click="say()">say</button>
</div>


<script src="/vue.js/vue.js"></script>
<script type="text/javascript">
    let vm =new Vue({
        el:"#app",
        data:{
            message: 0
        },
        methods:{
            //方法必须定义在Vue的methods对象中
            say:function () {
                alert(this.message)
            }
            // say:function (e) {
            //     alert(e)
            // }
        }
    });
</script>

</body>
</html>

双向绑定

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-双向绑定</title>
</head>
<body>

<div id="app">
    输入的文本:<input type="text" v-model="message">

    <h3>
        {{message}}
    </h3>

    性别:
    <input type="radio" name="sex" value="男" v-model="fan">男
    <input type="radio" name="sex" value="女" v-model="fan">女

    <h3>
        选中了: {{fan}}
    </h3>

    下拉框:
    <select v-model="select">
        <option disabled value="">---请选择---</option>
        <option>A</option>
        <option>B</option>
        <option>C</option>
    </select>

    <h3>
        选中了: {{select}}
    </h3>
</div>


<script src="/vue.js/vue.js"></script>
<script type="text/javascript">
  let vm =new Vue({
    el:"#app",
    data:{
        message: "",
        fan: "",
        select:""
    }
  });
</script>
</body>
</html>

component

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

<div id="app">
<!--    组件-->
    <fan v-for="item in items" v-bind:number="item"></fan>
</div>


<script src="/vue.js/vue.js"></script>
<script type="text/javascript">

<!--定义一个vue组件-->
  Vue.component("fan",{
      props:['number'],
      template:'<li>{{number}}</li>'
  });

  let vm =new Vue({
    el:"#app",
    data:{
        items:["111","222","333"]
    }
  });
</script>

</body>
</html>

axios通信

什么是axios?

Axios是一个开源的可以用在浏览器端和Node JS的异步通信框架, 她的主要作用就是实现AJAX异步通信,其功能特点如下:

  • 从浏览器中创建XMLHttpRequests
  • 从node.js创建http请求
  • 支持Promise API[JS中链式编程]
  • 拦截请求和响应
  • 转换请求数据和响应数据
  • 取消请求
  • 自动转换JSON数据
  • 客户端支持防御XSRF(跨站请求伪造)
{
  "name": "fanna",
  "url": "https://www.cnblogs.com/fanyaa",
  "page": 1,
  "isNonProfit": true,
  "address": {
    "street": "含光门",
    "city": "陕西西安",
    "country": "中国"
  },
  "links": [
    {
      "name": "bilibili",
      "url": "https://space.bilibili.com/95256449"
    },
    {
      "name": "狂神说Java",
      "url": "https://blog.kuangstudy.com"
    },
    {
      "name": "百度",
      "url": "https://www.baidu.com/"
    }
  ]
}

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

<div id="vue">
    <div>{{info.name}}</div>
    <div>{{info.address.street}}</div>
    <a v-bind:href="info.url">点我进入我的博客</a>
</div>


<script src="/vue.js/vue.js"></script>
<script src="/axios.js/axios.js"></script>
<script type="text/javascript">

    let vm =new Vue({
        el:"#vue",
        //接收数据
        data(){
          return{
              // 请求的返回参数格式必须和json字符串一样
              info:{
                  name:null,
                  url:null,
                  address:{
                      street:null,
                      city:null,
                      country:null
                  }
              }
          }
        },
        mounted(){//钩子函数  链式编程
            axios.get('data.json').then(response=>(console.log(this.info=response.data)))
        }
    });
</script>

</body>
</html>

计算属性

计算属性的重点突出在属性两个字上(属性是名词),首先它是个属性其次这个属性有计算的能力(计算是动词),这里的计算就是个函数:简单点说,它就是一个能够将计算结果缓存起来的属性(将行为转化成了静态的属性),仅此而已;可以想象为缓存!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-计算属性</title>
</head>
<body>

<div id="app">
  <h3>Time1:{{currentTime1()}}</h3>
  <h3>Time2:{{currentTime2}}</h3>
</div>


<script src="/vue.js/vue.js"></script>
<script type="text/javascript">

  let vm =new Vue({
    el:"#app",
    data:{
      message:'hello,fan'
    },
    methods:{
      currentTime1:function () {
        return new Date().toTimeString();
      }
    },
    computed:{//计算属性,methods 和 computed 方法不能重名
      currentTime2:function () {
        this.message;
        return new Date().toTimeString();
      }
    }
  });
</script>
</body>
</html>

插槽slot

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>vue-插槽slot</title>
</head>
<body>

<div id="app">
    <todo>
      <todo-title slot="todo-title" v-bind:title="todoTitle"></todo-title>
      <todo-items slot="todo-items" v-for="todoItem in todoItems" v-bind:item="todoItem"></todo-items>
    </todo>
</div>


<script src="/vue.js/vue.js"></script>
<script type="text/javascript">

  Vue.component("todo",{
    template:
         '<div>\
            <slot name="todo-title"></slot>\
            <ul>\
                <slot name="todo-items"></slot>\
            </ul>\
         </div>'
  });

  Vue.component("todo-title",{
    props:['title'],
    template:
        '<div>{{title}}</div>'
  });

  Vue.component("todo-items",{
    props:['item'],
    template:
        '<li>{{item}}</li>'
  });


  let vm =new Vue({
    el:"#app",
    data:{
        todoTitle:"书籍列表",
        todoItems:['java','python','c++']
    },
  });
</script>

</body>
</html>

自定义事件

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>vue-自定义事件</title>
</head>
<body>

<div id="app">
  <todo>
    <todo-title slot="todo-title" v-bind:title="todoTitle"></todo-title>
    <todo-items slot="todo-items" v-for="(todoItem,todoIndex) in todoItems"
                v-bind:item="todoItem" v-bind:index="todoIndex" v-on:remove="removeItems(todoIndex)"></todo-items>
  </todo>
</div>


<script src="/vue.js/vue.js"></script>
<script type="text/javascript">

  Vue.component("todo",{
    template:
            '<div>\
               <slot name="todo-title"></slot>\
               <ul>\
                   <slot name="todo-items"></slot>\
               </ul>\
            </div>'
  });

  Vue.component("todo-title",{
    props:['title'],
    template:
            '<div>{{title}}</div>'
  });

  // v-on:click简写@click
  Vue.component("todo-items",{
    props:['item','index'],
    template://只能绑定当前组件的方法
            '<li>{{index}}---{{item}}<button v-on:click="remove()">删除</button></li>',
    methods:{
      remove:function (index) {
        //自定义事件
        this.$emit('remove',index);
      }
    }
  });


  let vm =new Vue({
    el:"#app",
    data:{
      todoTitle:"书籍列表",
      todoItems:['java','python','c++']
    },
    methods: {
      removeItems:function (index){
        this.todoItems.splice(index,1,);//一次删除一个元素
      }
    }
  });
</script>

</body>
</html>

理一下思路:
在插槽的基础上,我想达到一个效果,我点击哪一个,哪一个就被删除。
所以,就需要在组件todo-items上绑定一个删除事件,就需要在组件内写一个remove方法,但是组件只能绑定当前组件的方法,无法实现删除Vue内date数据里的
todoItems:['java','python','c++'],所以,自定义事件出现了。

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

因为Vue获取了这个标签,所以在这个标签里,可以操作Vue的data和methods,所以

<todo-items slot="todo-items" v-for="(todoItem,todoIndex) in todoItems"
                v-bind:item="todoItem" v-bind:index="todoIndex" v-on:remove="removeItems(todoIndex)"></todo-items>

通过v-for获取列表的下标值,再通过v-bind绑定index,props参数传递到组件中,v-on将自定义事件remove和Vue下的removeItems(todoIndex)方法
绑定起来,

      removeItems:function (index){
        this.todoItems.splice(index,1,);//一次删除一个元素
      }

这个方法就是用来删除数据中的元素

      remove:function (index) {
        //自定义事件
        this.$emit('remove',index);
      }

而,remove则通过this.$emit('remove',index)方法,进行事件分发,从而实现效果。

vue-cli

需要的环境

node.js下载:http://nodejs.cn/download/

安装就是无脑的下一步就好,安装在自己的环境目录下

Git:https://git-scm.com/doenloads

镜像:https://npm.taobao.org/mirrors/git-for-windows/

确认nodejs安装成功:

  • cmd下输入node -v,查看是否能够正确打印出版本号即可!
  • cmd下输入npm -v,查看是否能够正确打印出版本号即可!
    这个npm,就是一个软件包管理工具,就和linux下的apt软件安装差不多!安装Node.js淘宝镜像加速器(cnpm),这样的话,下载会快很多~
    尽量使用管理员运行安装
# -g 就是全局安装
npm install cnpm -g

# 或使用如下语句解决npm速度慢的问题
npm install --registry=https://registry.npm.taobao.org

cnpm instal1 vue-cli-g
#测试是否安装成功#查看可以基于哪些模板创建vue应用程序,通常我们选择webpack vue list

创建一个基于webpack模板的vue应用程序

总结一下,配了好久一直报错,cnpm配了呀,但没啥用。最后是先配了淘宝的镜像,然后就OK了。
步骤:

  • vue init webpack vue_cli
  • cd vue_cli
  • npm install
  • npm install -g npm-check-updates
  • npm run dev

webpack使用

安装Webpack

  npm install webpack -g
  npm install webpack-cli -g

测试

  webpack -v
  webpack-cli -v

创建一个idea项目,webpack_study

在modules下新建一个hello.js

// 暴露一个方法

exports.sayHi = function () {
    document.write("<h1>扣1送地狱火</h1>");
}

再新建一个main.js

var hello = require("./hello")
hello.sayHi();

在根目录下创建webpack.config.js

module.exports = {
    entry:"./modules/main.js",
    output:{
        filename:"./js/bundle.js"
    }
}

命令行打包

最后创建一个index.html,测试一下

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

<script src="./dist/js/bundle.js"></script>

</body>
</html>

vue-router路由

vue-router是一个插件包, 所以我们还是需要用npm/cnpm来进行安装的。打开命令行工具,进入你的项目目录,输入下面命令。

cnpm install vue-router@3.1.3 --save-dev

基于之前创建的vue_cli进行测试,先删除src中没用的数据,最终的框架如下:

先定义一个Content.vue组件和Main.vue组件

<template>
    <h1>内容页</h1>
</template>

<script>
export default {
  name: "Content"
}
</script>

<style scoped>

</style>

<template>
    <h1>首页</h1>
</template>

<script>
export default {
  name: "Main"
}
</script>

<style scoped>

</style>

再建一个router文件夹,index.js,用来存放路由

import Vue from 'vue'
import VueRouter from "vue-router"
import Content from "../components/Content"
import Main from "../components/Main"
//安装路由

// 显示声明使用vue-router
Vue.use(VueRouter);



//配置导出路由

export default new VueRouter({
  routes:[
    {
      // 路由路径
      path:'/content',
      name:'content',
      //跳转到的组件
      component:Content
    },
    {
      path: "/main",
      name: "main",
      component: Main
    }
  ]
});

再在main.js中引用路由

import Vue from 'vue'
import App from './App'
import router from "./router"    //自动扫描里面的路由配置

Vue.config.productionTip = false


new Vue({
  el: '#app',
  router,//配置路由
  components: { App },
  template: '<App/>'
})

最后在App.vue下使用路由

<template>
  <div id="app">
    <h1>Fan</h1>
    <router-link to="/main">首页</router-link>
    <router-link to="/content">内容页</router-link>
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App',

}

</script>

<style>
#app {
  font-family: 'Avenir', Helvetica, Arial, sans-serif;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
  text-align: center;
  color: #2c3e50;
  margin-top: 60px;
}
</style>

运行测试:npm run dev

vue+ElementUI

创建一个新项目

  vue init webpack hello_vue
  #进入工程目录
  cd hello_vue
  #安装vue-routern 
  cnpm install vue-router@3.1.3 --save-dev
  #安装element-ui
  npm i element-ui -S
  #安装依赖
  npm install
  # 安装SASS加载器
  cnpm install sass-loader node-sass --save-dev
  #启功测试
  npm run dev

先删除src中没用的框架格式,最终框架如下:

创建一个Main.vue

<template>
    <h1>首页</h1>
</template>

<script>
export default {
  name: "Main"
}
</script>

<style scoped>

</style>

写一个Login.vue组件

<template>
  <div>
    <el-form ref="loginForm" :model="form" :rules="rules" label-width="80px" class="login-box">
      <h3 class="login-title">欢迎登录</h3>
      <el-form-item label="账号" prop="username">
        <el-input type="text" placeholder="请输入账号" v-model="form.username"/>
      </el-form-item>
      <el-form-item label="密码" prop="password">
        <el-input type="password" placeholder="请输入密码" v-model="form.password"/>
      </el-form-item>
      <el-form-item>
        <el-button type="primary" v-on:click="onSubmit('loginForm')">登录</el-button>
      </el-form-item>
    </el-form>

    <el-dialog title="温馨提示" :visible.sync="dialogVisible" width="30%" :before-close="handleClose">
      <span>请输入账号和密码</span>
      <span slot="footer" class="dialog-footer">
          <el-button type="primary" @click="dialogVisible = false">确定</el-button>
        </span>
    </el-dialog>
  </div>
</template>

<script>
export default {
  name: "Login",
  data(){
    return{
      form:{
        username:'',
        password:''
      },
      //表单验证,需要在 el-form-item 元素中增加prop属性
      rules:{
        username:[
          {required:true,message:"账号不可为空",trigger:"blur"}
        ],
        password:[
          {required:true,message:"密码不可为空",trigger:"blur"}
        ]
      },

      //对话框显示和隐藏
      dialogVisible:false
    }
  },
  methods:{
    onSubmit:function(formName){
      //为表单绑定验证功能
      this.$refs[formName].validate((valid)=>{
        if(valid){
          //使用vue-router路由到指定界面,该方式称为编程式导航
          this.$router.push('/main');
        }else{
          this.dialogVisible=true;
          return false;
        }
      });
    },
    handleClose:function () {
      this.dialogVisible=false;
    }
  }
}
</script>

<style lang="scss" scoped>
.login-box{
  border:1px solid #DCDFE6;
  width: 350px;
  margin:180px auto;
  padding: 35px 35px 15px 35px;
  border-radius: 5px;
  -webkit-border-radius: 5px;
  -moz-border-radius: 5px;
  box-shadow: 0 0 25px #909399;
}
.login-title{
  text-align:center;
  margin: 0 auto 40px auto;
  color: #303133;
}
</style>

router包下index.js配置路由

import Vue from 'vue'
import Router from 'vue-router'

import Main from '../views/Main'
import Login from '../views/Login'
Vue.use(Router);

export default new Router({
  routes:[
    {
      path:'/login',
      component:Login
    },
    {
      path:'/main',
      component:Main
    }
  ]
});

main.js引用路由

import Vue from 'vue'
import App from './App'
import router from "./router"
import ElementUI from 'element-ui'
import 'element-ui/lib/theme-chalk/index.css'

Vue.use(ElementUI);

new Vue({
  el: '#app',
  router,
  render: h => h(App)//ElementUI
});

App.vue

<template>
  <div id="app">
    <router-link to="/main">首页</router-link>
    <router-link to="/login">登录</router-link>
    <router-view></router-view>
  </div>
</template>

<script>

export default {
  name: 'App',
}

</script>

最后npm run dev,可能会有问题,原因是saas-loader版本和node.js版本不匹配

node -v查看自己的版本号

在package.json文件中找到sass-loader,将后面的版本号修改为对应的版本号后,之后重新打包一下npm install,然后 npm run dev

参数传递及重定向

hello_vue项目基础上实现

Profile.vue

<template>
<!--  所有的元素,不能直接在根节点下-->
  <div>
    <h1>个人信息页</h1>
<!--    <h3>{{$route.params.id}}</h3>-->
    <h3>{{id}}</h3>
  </div>
</template>

<script>
export default {
  props:['id'],
  name: "Profile"
}
</script>

<style scoped>

</style>

List.vue

<template>
    <h1>用户列表</h1>
</template>

<script>
export default {
  name: "List"
}
</script>

<style scoped>

</style>

Main.vue

<template>
  <div>
    <el-container>
      <el-aside width="200px">
        <el-menu :default-openeds="['1']">

          <el-submenu index="1">
            <template slot="title"><i class="el-icon-caret-right"></i>用户管理</template>
            <el-menu-item-group>
              <el-menu-item index="1-1">
                <!--插入的地方-->
<!--                name:传组件名,params:传递参数,需要对象v-bind-->
                <router-link v-bind:to="{name:'UserProfile',params:{id:1}}">个人信息</router-link>
              </el-menu-item>

              <el-menu-item index="1-2">
                <!--插入的地方-->
                <router-link to="/user/list">用户列表</router-link>
              </el-menu-item>

              <el-menu-item index="1-3">
                <!--插入的地方-->
                <router-link to="/goHome">回到首页</router-link>
              </el-menu-item>
            </el-menu-item-group>
          </el-submenu>

          <el-submenu index="2">
            <template slot="title"><i class="el-icon-caret-right"></i>内容管理</template>
            <el-menu-item-group>
              <el-menu-item index="2-1">分类管理</el-menu-item>
              <el-menu-item index="2-2">内容列表</el-menu-item>
            </el-menu-item-group>
          </el-submenu>

        </el-menu>
      </el-aside>

      <el-container>
        <el-header style="text-align: right; font-size: 12px">
          <el-dropdown>
            <i class="el-icon-setting" style="margin-right: 15px"></i>
            <el-dropdown-menu slot="dropdown">
              <el-dropdown-item>个人信息</el-dropdown-item>
              <el-dropdown-item>退出登录</el-dropdown-item>
            </el-dropdown-menu>
          </el-dropdown>
        </el-header>
        <el-main>
          <!--在这里展示视图-->
          <router-view />
        </el-main>
      </el-container>
    </el-container>
  </div>
</template>

<script>

export default {
  name: "Main"
}

</script>

<style scope d lang="scss">
.el-header {
  background-color: #b9cbe1;
  color: #333;
  line-height: 60px;
}
.el-aside {
  color: #333;
}
</style>

index.js

import Vue from 'vue'
import Router from 'vue-router'

import Main from '../views/Main'
import Login from '../views/Login'
import UserList from '../views/user/List'
import UserProfile from '../views/user/Profile'

Vue.use(Router);

export default new Router({
  routes:[
    {
      path:'/login',
      component:Login
    },
    {
      path:'/main',
      component:Main,//嵌套路由
      children:[
        {path:'/user/profile/:id', name:"UserProfile", component:UserProfile,props:true},//设置props为true,允许参数传递以props形式接收
        {path:'/user/list', component:UserList}
      ]
    },
    {
      //重定向
      path:'/goHome',
      redirect:'/main'
    }
  ]
});

404和路由钩子

去url中#,index.js下配置mode:'history'

404

建一个NotFound.vue

<template>
    <div>
      <h1>你的页面走丢了</h1>
    </div>
</template>

<script>
export default {
  name: "NotFound"
}
</script>

<style scoped>

</style>

然后去index.js下配路由

    {
      path:'*',
      component:NotFound
    }

路由钩子与异步请求

安装axios

cnpm install --save vue-axios

main.js引入axios

    import axios from 'axios'
    import VueAxios from 'vue-axios'
    Vue.use(VueAxios, axios)

准备数据,静态数据存放的位置:static/mock/data.json

Profile.vue

<template>
<!--  所有的元素,不能直接在根节点下-->
  <div>
    <h1>个人信息页</h1>
<!--    <h3>{{$route.params.id}}</h3>-->
    <h3>{{id}}</h3>
  </div>
</template>

<script>

export default {
  props:['id'],
  name: "Profile",
  //过滤器,拦截器
  beforeRouteEnter:(to,from,next)=>{
    console.log("beforeRouteEnter");
    //加载数据

    next(vm=>{
      vm.getData();//进入路由之前执行getData()
    });
  },
  beforeRouteLeave:(to, from, next)=>{
    console.log("beforeRouteLeave");
    next();
  },
  methods:{
    getData:function () {
      this.axios({
        method:'get',
        url:'http://localhost:8081/static/mock/data.json'
      }).then(function (response) {
        console.log(response);
      });
    }
  }
}
</script>

<style scoped>

</style>

beforeRouteEnter:在进入路由前执行
beforeRouteLeave:在离开路由前执行

参数说明:
to:路由将要跳转的路径信息
from:路径跳转前的路径信息
next:路由的控制参数
next() 跳入下一个页面
next('/path') 改变路由的跳转方向,使其跳到另一个路由
next(false) 返回原来的页面
next((vm)=>{}) 仅在 beforeRouteEnter 中可用,vm 是组件实例

posted @ 2023-01-08 20:39  Fannaa  阅读(40)  评论(0)    收藏  举报