vue(筑基篇一)

1基础知识

1.1、概念区别

vue(读view)是“渐进式“javascript框架。
渐进式
渐:逐渐。进:增加进来。vue由核心库(体积小)和相关的插件组成,先使用核心库,当需要特定功能再添加所需要的插件。
如需要路由,则添加路由插件,需要状态管理,添加vuex....
构建用户界面:将后台数据在前台界面动态显示出来。
vue插件和第三方库
vue插件也是库,但是依赖vue,第三方库不依赖vue
声明式开发:
不需要管流程,想干什么就按照特定语法做一些声明的描述(即写一些特定的代码),需要的展现和交互就有了。
命令式开发:
不仅要知道要显示什么,还要知道怎么告诉他。
如:jquery需要绑定监听,在监听里去读当前输入值,读完以后把之设置到标签里....整个流程,所有事情都需要做,这种开发方式叫命令式开发。
 
与其它前端js框架(angular、react)区别:
  1)、借鉴angular的模板数据绑定技术
  2)、借助react的组件化虚拟DOM技术
vue是把它们的特点整合起来。
react入门难,上手后会很容易,大公司用react多一些。vue入门简单、好理解,小公司用的多。
特点:
1、单页面框架
2、给予模块化组件化的安装模式
Vue.js是当下很火的一个JavaScript MVVM库(Model-View-ViewModel),它是以数据驱动和组件化的思想构建的。相比于Angular.js,Vue.js提供了更加简洁、更易于理解的API,使得我们能够快速地上手并使用Vue.js。
如果你之前已经习惯了用jQuery操作DOM,学习Vue.js时请先抛开手动操作DOM的思维,因为Vue.js是数据驱动的,你无需手动操作DOM。它通过一些特殊的HTML语法,将DOM和数据绑定起来。一旦你创建了绑定,DOM将和数据保持同步,每当变更了数据,DOM也会相应地更新。
当然了,在使用Vue.js时,你也可以结合其他库一起使用,比如jQuery
这2个链接是60分钟快速入门,讲解了原理
http://www.cnblogs.com/keepfool/p/5619070.html
https://www.cnblogs.com/rik28/p/6024425.html


这个是菜鸟入门,可运行看效果
http://www.runoob.com/vue2/vue-install.html

1.2  前端构建工具和脚手架工具

前端构建工具(如 Webpack  Gulp )和脚手架工具(如 Vue CLI 、 Create React App )的主要区别:

功能定位

  • ‌构建工具‌(如Webpack、Gulp)主要负责‌代码转换、打包和优化‌,将开发中的源代码(如ES6、Sass)转换为浏览器可识别的静态文件,并优化资源(如压缩CSS/JS、合并图片等)。
  • ‌脚手架工具‌(如Vue CLI、Create React App)则提供‌项目快速搭建和初始化配置‌,生成项目结构、配置文件及基础代码,减少手动配置工作量。

使用场景

  • 构建工具贯穿项目‌整个生命周期‌,从开发到维护均需使用(如Webpack需手动配置入口文件和loader)。
  • 脚手架工具仅在项目‌初期使用‌,后续开发可直接使用其生成的配置文件。 ‌15

典型差异

  • ‌Webpack‌需手动配置webpack.config.js文件,支持模块化打包、代码拆分等功能;
  • ‌Vue CLI‌通过命令行生成项目模板,内置Vue Router、Vuex等插件,无需手动配置基础架构。 ‌

1.3 webpack

Webpack 是一个前端资源加载/打包工具。它将根据模块的依赖关系进行静态分析,然后将这些模块按照指定的规则生成对应的静态资源。

Webpack 本身只能处理 JavaScript 模块,如果要处理其他类型的文件,就需要使用 loader 进行转换。

所以如果我们需要在应用中添加 css 文件,就需要使用到 css-loader 和 style-loader,他们做两件不同的事情,css-loader 会遍历 CSS 文件,然后找到 url() 表达式然后处理他们,style-loader 会把原来的 CSS 代码插入页面中的一个 style 标签中。

接下来我们使用以下命令来安装 css-loader 和 style-loader(全局安装需要参数 -g)。

cnpm install css-loader style-loader

执行以上命令后,会再当前目录生成 node_modules 目录,它就是 css-loader 和 style-loader 的安装目录。

http://www.runoob.com/w3cnote/webpack-tutorial.html

使用Vue的过程就是定义MVVM各个组成部分的过程。


1.4、环境搭建

必须先安装nodejs(自带Node.js 的包管理器npm),安装vue脚手架工具(命令行工具)
# 最新稳定版
$ npm install vue
安装淘宝npm(cnpm)
(1)输入以下命令
npm install -g cnpm --registry=https://registry.npm.taobao.org
(2)输入cnpm -v输入是否正常,这里肯定会出错。   
cnpm -v
(3)添加系统变量path的内容
因为cnpm会被安装到D:\Program Files\nodejs\node_global下,而系统变量path并未包含该路径。在系统变量path下添加该路径即可正常使用cnpm。

npm从国外下载包,cnpm从国内下载包
安装脚手架工具,即vue的命令行cli工具
cnpm install --global vue-cli

cnpm install -g @vue/cli
(它创建的目录结构很简单) 
chcp 65001切换到utf8编码,应为在dos下项目有中文输出

安装webpack
cnpm install -g webpack
webpack是javascript打包器(module bundler)
 
buntu16.04安装
1.node和npm卸载干净
1.1 apt-get卸载
sudo apt-get remove --purge npm
sudo apt-get remove --purge nodejs
sudo apt-get remove --purge nodejs-legacy
sudo apt-get autoremove
1.2 手动删除npm及相关目录
rm -r /usr/local/bin/npm
rm -r /usr/local/lib/node-moudels
find / -name npm
rm -r /tmp/npm* 


2.离线安装node和npm
# apt-get install nodejs #安装nodejs安装好后node、noejs-legacy、npm都安装了,安装n把node更新到最新版,然后升级npm # 先在系统上安装好nodejs和npm #apt
-get install nodejs-legacy #apt-get install npm # 升级npm为最新版本 #sudo npm install npm@latest -g # 安装用于安装nodejs的模块n sudo npm install -g n # 通过n模块安装指定的nodejs(3选一) sudo n stable(安装node稳定版) sudo n latest(不建议) sudo n lts(不建议) #which n #查看n安装目录 升级npm #npm i -g npm 设置淘宝镜像,此时npm就是cnpm(不是产生cnpm命令) sudo npm config set registry https://registry.npm.taobao.org //设置淘宝镜像 source ~/.bashrc //使修改立即生效 或安装淘宝镜像,因为npm的源是国外的,有时候会比较慢 (这么设置cnpm才是走淘宝镜像) npm install -g cnpm --registry=https://registry.npm.taobao.org

 

2、创建项目

2.1、创建项目:

vue init webpack projectName

如:使用vue初始化一个项目,  vue init webpack demo1

vue init webpack-simple demo2
注意:不能在vue当前目录执行这个命令,否则一直在下载中
或vue ui直接进入视图操作界面生成

2.2、进入项目,下载依赖:

npm install 或者 cnpm install
依赖放在node_modules目录,如果使用vue init webpack projectName安装,这个依赖会被同时安装,这一步可以省略

3、运行项目:

npm run dev
运行完它,访问地址会自动生成

三、vue指令
安装脚手架工具,即vue的命令行cli工具
指令的作用:
将指令绑定在元素上时,指令会为绑定的目标元素添加一些特殊的行为。

vue内置的指令有:
   v-html将key值当做html代码解析输出
    v-if:v-if是条件渲染指令,它根据表达式的真假来删除和插入元素、
    v-show:是条件渲染指令,元素始终会被渲染到HTML,它只是简单地为元素设置CSS的style属性、
    v-else:为v-ifv-show的“else块”。v-else元素必须立即跟在v-ifv-show元素的后面,否则它不能被识别,如:
        <h1 v-if="age >= 25">Age: {{ age }}</h1>
        <h1 v-else>Name: {{ name }}</h1>
  v-else
元素是否渲染在HTML中,取决于前面使用的是v-if还是v-show指令、
    v-for:基于一个数组渲染一个列表,它和JavaScript的遍历语法相似、
    v-bind:
语法:v-bind:属性="属性key",可简写为:属性="属性key"
如<div v-bind:class="student"></div>,简写为<div :class="student"></div>
可以在其名称后面带一个参数,中间放一个冒号隔开,这个参数通常是HTML元素的特性(attribute),
例如:
        <li v-for="n in pageCount">
            <a href="javascripit:void(0)" v-bind:class="activeNumber === n + 1 ? 'active' : ''">{{ n + 1 }}</a>表达式的含义是:高亮当前页
        </li>
        new Vue({
             el: '#app',
             data: {
                 activeNumber: 1,
                 pageCount: 10 }
            })  
  v-on:用于监听DOM事件,它的用语法和v-bind是类似的,例如监听<a>元素的点击事件,例如:
可简写为@click

<button v-on:click='func'>点击</button>
可简写为
<button @click='func'>点击</button>

<div id="app">
     <p><input type="text" v-model="message"></p>
     <button v-on:click="greet">Greet</button>
     <button v-on:click="say('Hi')">Hi</button>
</div>
var vm = new Vue({
        el: '#app',
        data: { message: 'Hello, Vue.js!' }, // 在 `methods` 对象中定义方法
        methods: {
              greet: function() {
                    // 方法内 `this` 指向 vm
                    alert(this.message)
             },
              say: function(msg) {
                    alert(msg) }
              }
     })
也可以自定义指令。
指令里的变量定义在vue实例选项对象的data属性中。
<div id="app"> 
     <h1 v-if="yes">Yes!</h1>
     <h1 v-if="age >= 25">Age: {{ age }}</h1>
    <h1 v-if="name.indexOf('jack') >= 0">Name: {{ name }}</h1>
</div>
var vm = new Vue({
    el: '#app',
    data: {
          yes: true,
         age: 28,
        name: 'keepfool'
    }
})

双向数据绑定v-model
只能在表单里面实现,model改变影响视图,view改变影响model

ref:用户获取dom节点,类似于id
 <textarea ref='userDetail'></textarea>
<button  @click='getUserDetail'>获取描述</button>

在方法中通过this.$refs.对应的ref名获取相应的dom节点
  getUserDetail: function() {
      alert(this.$refs.userDetail.value);
    }

设置ref用于获取dom节点
<div class="user" ref='userBox'>
,使用原生js对其属性进行设置
 this.$refs.userBox.style.width='100px';

事件传值
  <button data-sex='man' @click="getEvent($event)">事件传值</button>
通过传递的$event可以获取当前DOM节点的所有属性
getEvent :function(e) {
      e.srcElement.style.backgroundColor='red';
      alert(e.srcElement.dataset.sex);
      alert(e.srcElement.innerHTML);
      console.log(e);
    }



四、route路由

Vue.js 路由允许我们通过不同的 URL 访问不同的内容。

通过 Vue.js 可以实现多视图的单页Web应用(single page web application,SPA)。

Vue.js 路由需要载入 vue-router 库

安装中文文档地址:
https://router.vuejs.org/zh/
1、安装vue-router,并引入插件
推荐使用淘宝镜像:
cnpm install vue-router(或
直接下载 / CDN:https://unpkg.com/vue-router/dist/vue-router.js

在main.js配置文件中进行配置,引入vue-router
import VueRouter  from 'vue-router';
Vue.use(VueRouter);
 
2、引入组件
import Home from '../components/Home.vue';
import News from '../components/News.vue';
 
3、配置路由到组件的映射,配置默认跳转路由
const main_routes = [
  {path:'/news', component: News},
  {path:'/home', component: Home},
  {path:'*', redirect:'/home'} //上面路由都没匹配到,默认跳转到/home路由
];
 
4、实例化路由vuerouter,加载配置。如果配置的路由名为routes,则routes:routes可缩写为routes,否则必须写为routers:配置的路由别名 
const router = new VueRouter({
  routes:main_routes
});
 
5、挂载VueRoute
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})
6、在app.vue根组件中将动态匹配到组件将渲染到<router-view></router-view>
    路由链接或跳转
    <router-link to="/home">home</router-link>
    <router-link to="/news">news</router-link>
    <hr/>
    <router-view></router-view>

五、动态路由获取参数和get传值获取
url为http://localhost:8080/#/news_detail?id=2通过this.$route.query可获取参数
url为:http://localhost:8080/#/news_detail/2通过配置动态路由获取,
在main.js里
//1、引入路由插件
import VueRouter  from 'vue-router';
Vue.use(VueRouter);
//2\创建组件
import Home from '../components/Home.vue';
import News from '../components/News.vue';
import NewsDetail from '../components/NewsDetail.vue';
//3、配置路由
const main_routes = [
  .....
  {path:'/news_detail/:news_id', component: NewsDetail},
];
//4、实例化vuerouter,如果配置的路由名为routes,则routes:routes可缩写为routes
const router = new VueRouter({
  routes:main_routes
});
//5、挂载VueRoute
new Vue({
  el: '#app',
  router,
  render: h => h(App)
})

在news.vue里
<template>
  <div>
    <h1>{{ news_title }}</h1>
    <ul>
      <li v-for="item,key in list">
        <router-link :to="'/news_detail/'+key">{{ item }}</router-link>
      </li>
    </ul>
  </div>
</template>
 
<script>
  import VueEvent from '../model/VueEvent.js';
  export default {
    data(){
      return {
        'news_title': '新闻组件',
        'list' :['news_111', 'news_2222', 'news_3333']
      }
    }
  }
</script>
在NewsDetail.vue可直接通过this.$route.params获取动态路由参数
<script>
  export default {
    mounted() {
        // console.log(this.$route.query);
        console.log(this.$route.params);
    }
  }
</script>





六、model模块化方法封装和使用
在model里封装storage.js
var storage = {
  set(key, value) {
    localStorage.setItem(key, JSON.stringify(value));
  },
  get(key) {
    return JSON.parse(localStorage.getItem(key));
  },
  remove(key) {
    localStorage.removeItem(key);
  }
}
//把封装的 方法storage暴露出去
export default storage;

在xxx.vue中引入
 import storage from '../model/localstorage.js';

就可使用封装的方法了
如:storage.set('todoDataList', this.todoDataList);

七、组件封装注册和使用

组件用于扩展html在构建应运的不足,封装可重用的代码。由包含html的模板(所有内容要被根节点,如<div>包含)、js、css组成
 App.vue是根组件,在里面可以引用其它组件,其它组件再引用别的组件,形成树状组件结构

1、写组件
2、使用import引用组件
3、使用components注册组件,起个别名
4、在模板中使用注册的别名组件
在components/ButtonCount.Vue写组件
<template>
  <div>
    <h1>点击计算器演示</h1>
    <button @click="clickfnc">
      {{ title }} you click me {{ cnt }} times
      <slot></slot> //使用槽,这样在别的组件引用它时,可以在<button></button>元素里添加内容,否则不显示
    </button>
    </div>
</template>

<script>
    export default {
        // name : 'button_count',
        props: {  //定时组件元素属性,类型为String,默认值为title1
            title: {
                type : String,
                default: 'title1:'
            }
        },
        data(){
            return {
                cnt : 0,
            };
        },
        methods: {
            clickfnc : function() {
                this.cnt++;
                this.$emit('clicknow', this.cnt); //绑定clicknow方法,传递参数 this.cnt
            }
        }
    }
</script>
//使用scoped,可以使该css样式只对当前组件起作用,但scoped对部分浏览器不支持,最好使用类限制
<style scoped="scoped">
  h1 {
      color:red;
  }
</style>

在根组件app.Vue里引用ButtonCount组件
//组件属性,title为组件定义的属性,不写使用其默认值
<button-count title="描述" >
      <h2>这是点击按钮</h2> //因为ButtonCount组件里使用了 <slot></slot>,这里的h2内容才能显示
    </button-count>
<script>
 //2、引用组件
  import ButtonCount from '../components/ButtonCount.vue';
 export default {
  ....,
    components:{ //组件注册
      'button-count': ButtonCount
    }
  }
</script>
八、生命周期钩子函数

生命周期钩子函数是组件挂载、更新、销毁时触发的一系列方法

beforeCreate 组件实例刚被创建,组件属性计算之前,如data属性等
created 组件实例创建完成,属性已绑定,但DOM还未生成,$el属性还不存在
beforeMount 模板编译 / 挂载之前
mounted 模板编译 / 挂载之后
beforeUpdate 组件更新之前
update 组件更新之后
activated 组件被激活时调用
deactivated 组件被移除时调用
beforeDestory 组件销毁前调用
destoryed 组件销毁后调用
实例
在components/Life.Vue写组件
<template>
  <div>
    <h1>{{ message }}</h1>
    <button @click='change'>更新message的值</button>
  </div>
</template>

<script>
  export default {

    data(){
      return {
        message : '生命周期钩子组件'
      };
    },
    methods: {
      change: function() {
        this.message='声明周期组件更新值测试'
      }
    },
     beforeCreate(){
          console.group('beforeCreate 创建前状态 ------------>');
          console.log("%c%s", "color:red" , "el     : " + this.$el); //undefined
          console.log("%c%s", "color:red","data   : " + this.$data); //undefined
          console.log("%c%s", "color:red","message: " + this.message)
        },
        created() {
          console.group('created 创建完毕状态 ------------>');
          console.log("%c%s", "color:red","el     : " + this.$el); //undefined
          console.log("%c data值为:%O", "color:red", this.$data); //已被初始化
          console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        beforeMount() {
          console.group('beforeMount 挂载前状态 ------------>');
          console.log("%c%s", "color:red","el     : " + (this.$el)); //已被初始化
          console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
          console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        mounted() {
          console.group('mounted 挂载结束状态 ------------>');
          console.log("%c%s", "color:red","el     : " + this.$el); //已被初始化
          console.log(this.$el);
          console.log("%c%s", "color:red","data   : " + this.$data); //已被初始化
          console.log("%c%s", "color:red","message: " + this.message); //已被初始化
        },
        beforeUpdate() {
          console.group('beforeUpdate 更新前状态 ------------>');
          console.log("%c%s", "color:red","el     : " + this.$el);
          console.log(this.$el);
          console.log('真实dom结构:' + document.getElementById('app').innerHTML);
          console.log("%c%s", "color:red","data   : " + this.$data);
          console.log("%c%s", "color:red","message: " + this.message);
        },
        updated() {
          console.group('updated 更新完成状态 ------------>');
          console.log("%c%s", "color:red","el     : " + this.$el);
          console.log(this.$el);
          console.log('真实dom结构:' + document.getElementById('app').innerHTML);
          console.log("%c%s", "color:red","data   : " + this.$data);
          console.log("%c%s", "color:red","message: " + this.message);
        },
        beforeDestroy() {
          console.group('beforeDestroy 销毁前状态 ------------>');
          console.log("%c%s", "color:red","el     : " + this.$el);
          console.log(this.$el);
          console.log("%c%s", "color:red","data   : " + this.$data);
          console.log("%c%s", "color:red","message: " + this.message);
        },
        destroyed() {
          console.group('destroyed 销毁完成状态 ------------>');
          console.log("%c%s", "color:red","el     : " + this.$el);
          console.log(this.$el);
          console.log("%c%s", "color:red","data   : " + this.$data);
          console.log("%c%s", "color:red","message: " + this.message)
        }
  }
</script>
//最常用的生命周期函数:mounted、beforeDestroy
如倒计时,那应该在vm的什么地方实现,应该是mounted里。使用setInterval时会创建内存,但使用this.$destroy();销毁vm时,虽然页面上倒计时停止了,但使用console.log(this.time);发现倒计时依然进行,
这就是所谓的内存泄露,内存没有被销毁,需要在销毁vm之前的生命周期函数里beforeDestroy使用clearInterval(this.intervalId);清除内存

<div id="app">
  <button @click="delVM">destory vm</button>
  倒计时:{{ time }}秒
</div>

const vm = new Vue({
  el: '#app',
  data:{
    time: 100,
  },
  methods: {
    delVM() {
      this.$destroy();
    }
  },

  mounted(){

    this.intervalId = setInterval(()=>{
      console.log(this.time);
      this.time--;
    }, 1000);
  },
  beforeDestroy() {
    clearInterval(this.intervalId);
  }
});



在根组件App.vue,模仿组件销毁
<template>
  <div id="app">
    <v-life v-if="flag"></v-life>
    <button @click="flag=!flag">创建或销毁组件</button>
  </div>
</template>
 
<script>
 import Life from "../components/Life.vue";
  export default {
     components: {
        'v-life' : Life
     }
}
</script>


posted @ 2019-12-28 18:25  六只小猫  阅读(94)  评论(0)    收藏  举报