Vue学习记录

Here, you can get source code.

Vue (pronounced /vjuː/, like view) is a progressive framework for building user interfaces. Unlike other monolithic frameworks, Vue is designed from the ground up to be incrementally adoptable.

Vue

Using IDEA plugin:

image-20200915111843300

Using Vue, You can create an index.html file and include Vue with:



or:



Declarative Rendering

At the core of Vue.js is a system that enables us to declaratively render data to the DOM using straightforward template syntax:

{{ message }}

You can offer the data by:

var app = new Vue({
  el: '#app',
  data: {
    message: 'Hello Vue!'
  }
})

Run it:

Hello Vue!

The data and the DOM are now linked, and everything is now reactive. How do we know? Open your browser’s JavaScript console (right now, on this page) and set app.message to a different value. You should see the rendered example above update accordingly.

vue_reactive

Note that we no longer have to interact with the HTML directly. A Vue app attaches itself to a single DOM element (#app in our case) then fully controls it.

In addition to text interpolation, we can also bind element attributes like this:

Hover your mouse over me for a few seconds to see my dynamically bound title!
    var app2 = new Vue({
        el: '#app-2',
        data: {
            message: 'You loaded this page on ' + new Date().toLocaleString()
        }
    })

Hover your mouse over me for a few seconds to see dynamically bound title.

Here we are encountering something new. The v-bind attribute you are seeing is called a directive. Directives are prefixed with v- to indicate that they are special attributes provided by Vue, and as you may have guessed, they apply special reactive behavior to the rendered DOM. Here, it is basically saying “keep this element’s title attribute up-to-date with the message property on the Vue instance.”

If you open up your JavaScript console again and enter app2.message = 'some new message', you’ll once again see that the bound HTML - in this case the title attribute - has been updated like before.

Conditionals and Loops

It’s easy to toggle the presence of an element, too:

Now you see me
var app3 = new Vue({
  el: '#app-3',
  data: {
    seen: true
  }
})

result:

Now you see me

Go ahead and enter app3.seen = false in the console. You should see the message disappear.

There are quite a few other directives, each with its own special functionality. For example, the v-for directive can be used for displaying a list of items using the data from an Array:

  1. {{ todo.text }}
var app4 = new Vue({
  el: '#app-4',
  data: {
    todos: [
      { text: 'Learn JavaScript' },
      { text: 'Learn Vue' },
      { text: 'Build something awesome' }
    ]
  }
})

result:

image-20200916102159331

In the console, enter app4.todos.push({ text: 'New item' }). You should see a new item appended to the list.

Handling User Input

To let users interact with your app, we can use the v-on directive to attach event listeners that invoke methods on our Vue instances:

{{ message }}

var app5 = new Vue({
  el: '#app-5',
  data: {
    message: 'Hello Vue.js!'
  },
  methods: {
    reverseMessage: function () {
      this.message = this.message.split('').reverse().join('')
    }
  }
})
vue_reverse

Note that in this method we update the state of our app without touching the DOM - all DOM manipulations are handled by Vue, and the code you write is focused on the underlying logic.

Vue also provides the v-model directive that makes two-way binding between form input and app state a breeze:

{{ message }}

var app6 = new Vue({
  el: '#app-6',
  data: {
    message: 'Hello Vue!'
  }
})
vue_model

Composing with Components

The component system is another important concept in Vue, because it’s an abstraction that allows us to build large-scale applications composed of small, self-contained, and often reusable components. If we think about it, almost any type of application interface can be abstracted into a tree of components:

Component Tree

In Vue, a component is essentially a Vue instance with pre-defined options. Registering a component in Vue is straightforward:

// Define a new component called todo-item
Vue.component('todo-item', {
  template: '
  • This is a todo
  • ' }) var app = new Vue(...)

    Now you can compose it in another component’s template:

    But this would render the same text for every todo, which is not super interesting. We should be able to pass data from the parent scope into child components. Let’s modify the component definition to make it accept a prop:

    Vue.component('todo-item', {
      // The todo-item component now accepts a
      // "prop", which is like a custom attribute.
      // This prop is called todo.
      props: ['todo'],
      template: '
  • {{ todo.text }}
  • ' })

    Now we can pass the todo into each repeated component using v-bind:

    Vue.component('todo-item', {
      props: ['todo'],
      template: '
  • {{ todo.text }}
  • ' }) var app7 = new Vue({ el: '#app-7', data: { groceryList: [ { id: 0, text: 'Vegetables' }, { id: 1, text: 'Cheese' }, { id: 2, text: 'Whatever else humans are supposed to eat' } ] } })

    run it:

    image-20200916110629416

    This is a contrived example, but we have managed to separate our app into two smaller units, and the child is reasonably well-decoupled from the parent via the props interface. We can now further improve our component with more complex template and logic without affecting the parent app.

    In a large application, it is necessary to divide the whole app into components to make development manageable. We will talk a lot more about components later in the guide, but here’s an (imaginary) example of what an app’s template might look like with components:

    Vue-Axios

    Vue 实例生命周期

    Axios是一个开源的可以在浏览器端和NodeJS的异步通信框架,主要作用是实现Ajax异步通信。

    准备一份JSON文件:

    {
      "name": "Q",
      "url": "https://hellooooo.top",
      "page": 1,
      "liangzai": true
    }
    

    使用Vue的钩子函数进行Axios异步请求:

        var vue = new Vue({
            el: '#app',
            data: {
                message: "Hello"
            },
            //钩子
            mounted(){
                axios.get('/Vue/vue-first/data.json').then(response => console.log(response.data));
            }
        });
    

    结果:

    image-20200922102058918

    将Axios得到的数据与页面进行绑定:

        var vue = new Vue({
            el: '#app',
            data() {
                return{
                    info: {
                        name: null,
                        url: null,
                        liangzai: null
                    }
                }
            },
            //钩子
            mounted(){
                // axios.get('/Vue/vue-first/data.json').then(response => console.log(response.data));
                axios.get('/Vue/vue-first/data.json').then(response => this.info = response.data);
    
            }
        });
    

    页面:

    {{info.name}} {{info.url}} {{info.liangzai}}

    结果:

    image-20200922103904787

    计算属性

    有缓存的味道。

        var vm = new Vue({
            el: '#app',
            data: {
                message: "Hello"
            },
            methods: {
                currentTime: function (){
                    return Date.now();
                }
            },
            //计算属性
            //注意methods和computed尽量不要重名
            computed: {
                currentTime2: ()=>{
                    return Date.now();
                }
            }
        });
    
        

    current: {{currentTime()}}

    current: {{currentTime2}}

    运行:

    vue_computed

    可以看到currentTime方法输出的时间都在变化,而currentTime2每次都输出相同的时间戳。

    内容分发

    
        Vue.component("todo",{
            template: '
    ' + '' + '
      ' + '' + '
    ' + '
    ' }); Vue.component("todo-title", { props: ['title'], template: '
    {{title}}
    ' }); Vue.component("todo-items", { props: ['item'], template: '
  • {{item}}
  • ' }); var vm = new Vue({ el: '#app', data: { title: "liang", todoItems: [ 'Liang0', 'Liang1', 'Liang2', 'Liang3' ] } });

    下面的":"是"v-bind:"的简写,":title"相当于"v-bind:title"。

    效果:

    image-20200922111638314

    如果需要在每个项目之后增添一个删除按钮:

        Vue.component("todo-items", {
            props: ['item'],
            template: '
  • {{item}}
  • ', methods: { remove: ()=>{ alert("Choose delete.") } } });
        var vm = new Vue({
            el: '#app',
            data: {
                title: "liang",
                todoItems: [
                    'Liang0',
                    'Liang1',
                    'Liang2',
                    'Liang3'
                ]
            },
            methods:{
                removeItems: (index)=>{
                    console.log("Will remove: " + this.todoItems[index]);
                    //删除当前
                    this.todoItems.splice(index, 1);
                }
            }
    
        });
    

    可以做到监听,但是组件无法做到调用Vue实例的removeItems方法删除数据。

    即组件如何删除Vue实例中的数据?

    自定义事件

    this.$emit

        Vue.component("todo",{
            template: '
    ' + '' + '
      ' + '' + '
    ' + '
    ' }); Vue.component("todo-title", { props: ['title'], template: '
    {{title}}
    ' }); Vue.component("todo-items", { props: ['item', 'index'], template: '
  • {{index}}:{{item}}
  • ', methods: { remove: function (index){ // alert("Choose delete.") this.$emit('remove', index); } } }); var vm = new Vue({ el: '#app', data: { title: "liang", todoItems: [ 'Liang0', 'Liang1', 'Liang2', 'Liang3' ] }, methods:{ removeItems: function (index){ console.log("Will remove: " + this.todoItems[index]); //删除当前 this.todoItems.splice(index, 1); } } });

    Vue-Cli

    官方提供的一个脚手架。

    先安装Node.js,安装完成后,打开CMD:

    C:\Users\Q>node -v
    v10.18.0
    C:\Users\Q>npm -v
    6.13.4
    

    安装淘宝镜像加速器:

    # -g 全局安装
    npm install cnpm -g
    

    如果不想安装可以在安装的时候增加如下参数:

    npm install --registry=https://registry.npm.taobao.org
    

    安装vue-cli:

    cnpm install vue-cli -g
    

    查看:

    vue list
    
    image-20200922160314070

    创建第一个vue-cli应用程序

    在命令行执行:

    vue init webpack myvue
    

    myvue为项目名称.

    image-20200922161813167

    初始化并且运行:

    cd myvue
    npm install
    npm run dev
    
    image-20200922162200979

    Webpack

    安装Webpack:

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

    查看版本:

    webpack -v
    webpack-cli -v
    

    新建文件夹webpack-study并进入:

    mkdir webpack-study
    cd webpack-study
    

    新建modules:

    mkdir modules
    

    在其内新建一个Hello.js:

    //暴露一个方法
    exports.sayHi = ()=>{
        document.write("

    Liangzai

    ") };

    新建一个main.js:

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

    在webpack-study内新建一个webpack.config.js:

    module.exports = {
        entry: './modules/main.js',
        output: {
            filename: "./js/bundle.js"
        }
    };
    
    image-20200922183904503

    在命令行输入:

    webpack
    

    自动生成了bundle.js:

    image-20200922184053396

    测试使用:

    新建index.html:

    
    
    
        
        Hello
    
    
    
    
    
    
    image-20200922184240938

    Vue-Router

    进入自己项目根目录,安装:

    npm install vue-router --save-dev
    

    声明使用Vue-Router

    import VueRouter from "vue-router";
    //显式声明使用Vue-Router
    Vue.use(VueRouter);
    

    简单使用:

    新建两个Component,一个Content,一个Main:

    
    
    
    
    
    
    
    
    
    
    
    

    在src目录下新建router目录,并添加index.js作为配置文件:

    import Vue from "vue";
    import VueRouter from "vue-router";
    import Content from "../components/Content";
    import Main from "../components/Main";
    //安装路由
    Vue.use(VueRouter);
    
    //配置导出路由
    export default new VueRouter({
      routes: [
        {
        //  路由路径
          path: '/content',
          name: "content",
        //  跳转组件
          component: Content
        },
        {
          //  路由路径
          path: '/main',
          name: "main",
          //  跳转组件
          component: Main
        }
      ]
    })
    

    编辑main.js配置路由:

    //自动扫描里的路由配置
    import router from './router';
    ...
    //在Vue实例内配置路由
    new Vue({
      el: '#app',
      //在Vue实例配置路由
      router,
      components: { App },
      template: ''
    })
    

    配置App.vue,添加路由跳转:

    
    

    其他保持不变,运行测试:

    vue-router

    Vue + ElementUI

    创建一个名为hello-vue的工程:

    vue init webpack hello-vue
    

    进入hello-vue安装vue-router,element-ui,sass-loader和node-sass:

    npm install vue-router --save-dev
    npm i element-ui -S
    #安装依赖
    npm install
    #安装SASS加载器
    npm install sass-loader node-sass --save-dev
    #启动测试
    npm run dev
    

    准备Main页面以及Login页面,

    Main:

    
    
    
    
    
    
    

    Login:

    
    
    
    

    路由配置:

    import Vue from "vue";
    import VueRouter from "vue-router";
    
    import Main from "../views/Main";
    import Login from "../views/Login";
    
    Vue.use(VueRouter);
    
    export default new VueRouter({
      routes: [
        {
          path: '/login',
          component: Login
        },
        {
          path: '/main',
          component: Main
        }
      ]
    });
    

    App.vue配置展示界面:

    
    

    main.js配置:

    import Vue from 'vue'
    import App from './App'
    import router from "./router";
    
    import Element from 'element-ui';
    import 'element-ui/lib/theme-chalk/index.css';
    
    Vue.config.productionTip = false
    
    Vue.use(router);
    Vue.use(Element);
    
    /* eslint-disable no-new */
    new Vue({
      el: '#app',
      router,
      render: h => h(App),
      components: { App },
      template: ''
    })
    

    如果报错:

     ERROR  Failed to compile with 1 errors    
    

    可能是sass版本太高所致:

    卸载当前sass版本:

    npm uninstall sass-loader
    
    npm install [email protected] --save-dev
    

    结果:

    vue-router-elementui

    路由嵌套

    替换Main.vue:

    
    
    
    
    
    
    

    我这代码抄得有点问题,但是大致还能看看。

    在views下新建user目录并添加List .vue和profile.vue:

    
    
    
    
    
    
    
    
    
    
    
    
    image-20200923110940907

    配置路由组件router/index.js:

    import List from "../views/user/List";
    import Profile from "../views/user/Profile";
    ...
    export default new VueRouter({
      routes: [
        {
          path: '/login',
          component: Login
        },
        {
          path: '/main',
          component: Main,//嵌套路由
          children: [
            {
              path: '/user/profile',
              component: Profile
            },
            {
              path: '/user/list',
              component: List
            }
          ]
        }
      ]
    });
    

    测试:

    vue-router-elementui-childrouter

    参数传递及重定向

    个人信息页面应该因人而异。

    修改Main.vue的个人信息的

    个人信息
    

    这里的name是路由配置router/index.js中添加的name:

            {
              path: '/user/profile/:id',
              name: 'UserProfile',
              component: Profile
            }
    

    Profile.vue展示这个数字:

    
    

    还可以通过props达到目的

    关于重定向:

    
      GoHOME
    
    

    编辑路由配置index.js:

    routes: [
        {
          path: '/login',
          component: Login
        },
        {
          path: '/main',
          component: Main,//嵌套路由
          children: [
            {
              path: '/user/profile/:id',
              name: 'UserProfile',
              component: Profile
            },
            {
              path: '/user/list',
              component: List
            },
            {
              path: '/goHome',
              redirect: '/main'
            }
          ]
        }
      ]
    

    通过redirect进行即可,结果:

    vue-router-redirect

    比如,我们登录之后需要把用户名展示在页面,我们可以这样。

    将用户名放在main路径之后:

    修改Login.vue

                //使用 vue-router路由到指定页面,该方式称之为编程式导航
                this.$router.push("/main" + "/" + this.form.username);
    

    修改index.js:

          path: '/main/:name',
          component: Main,//嵌套路由
          props: true,
          children: [
              ...
    

    修改Main.vue,展示用户名:

    {{name}}
    ...
    export default {
      props: ['name'],
      name: "Main"
    }
    

    运行:

    vue-router-username

    如何去除访问路径中的‘#’?

    编辑路由配置文件:

    export default new VueRouter({
      mode: 'history',//hash
      ...
    

    将模式修改为'history'即可。

    404

    如何统一展示404?

    在views下新建NotFound.vue:

    
    
    
    
    
    

    在路由配置中添加该组件:

    import NotFound from "../views/NotFound";
    

    同时配置路径:

      routes: [
        {
          path: '/login',
          component: Login
        },
          ...
        {
          path: '*',
          component: NotFound
        }
      ]
    

    测试:

    vue-router-404

    此外,Vue还提供了各种钩子回调:

    export default {
      name: "Profile",
      beforeRouteEnter: (to, from, next) => {
        console.log("进入路由之前");
        next();
      },
      beforeRouteLeave: (to, from, next) => {
        console.log("进入路由之后");
        next();
      }
    }
    

    到时候可以再看。

    参考

    1. Vue
    2. 【狂神说Java】Vue最新快速上手教程通俗易懂
    3. # Vue项目 报错TypeError 【ERR INVALID ARG TYPE】: The “path“ argument must be of type string

    你可能感兴趣的:(Vue学习记录)