Vue框架(三)

一、 过滤器

1.0 

<body>
  
  <div id='app'>
    <div v-color='color'>111</div>
  </div>
</body>

指令 => 封装DOM操作
自定义指令 => 封装自己的DOM操作(封装一些ui框架特别有用)
v-color='red' => DOM操作把当前标签设置为背景红

<script src="js/vue.js"></script>

  <script>
    new Vue({
      el: '#app',
      data: {
        color: 'green'
      },
      directives: {
        // 第一个参数是绑定了自定义指令的标签。
        // 第二个参数是当前指令的一些信息.
        // config.value就是自定义指令的值.
        color(el, config) {
          el.style.backgroundColor = config.value
        }
      }
    })

  </script>

 1.1

<body>
  
  <div id='app'>
    <input type="text" v-model='msg'>
    <div>{{msg | money}}</div>
  </div>
</body>

如果一个数据要显示的格式需要更改,应该使用过滤器
| => 管道符.(angular).

<script src="js/vue.js"></script>
  <script>
    new Vue({
      el: '#app',
      data: {
        msg: ''
      },
      // 过滤器.val形参就是 | 前面的表达式的值.
      filters: {
        money(val) {
          let re = /\B(?=((\d{3})+$))/g;
          return val.replace(re, ',');
        }
      }
    })

  </script>

二、自定义指令

 

<body>
  
  <div id='app'>
    <div v-color='color'>111</div>
  </div>
</body>

指令 => 封装DOM操作
自定义指令 => 封装自己的DOM操作(封装一些ui框架特别有用)
v-color='red' => DOM操作把当前标签设置为背景红

<script>
    new Vue({
      el: '#app',
      data: {
        color: 'green'
      },
      directives: {
        // 第一个参数是绑定了自定义指令的标签。
        // 第二个参数是当前指令的一些信息.
        // config.value就是自定义指令的值.
        color(el, config) {
          el.style.backgroundColor = config.value
        }
      }
    })

  </script>

三、组件

<body>

  <div id='app'>
    <news></news>
    <news></news>
    <news></news>
  </div>
</body>

函数为什么要封装?
复用相同的逻辑和代码.

组件都是vm实例.它可以有自己的视图,自己的数据,自己的逻辑.
组件是为了复用布局以及逻辑.

<script>
    new Vue({
      el: '#app',
      components: {
        news: {
          template: `
            <div>
              <h3>今天的新闻</h3>
              <p>今天的新闻内容</p>
            </div>
          `
        }
      }
    })

  </script>

四、组件注册

<body>
  <div id='app'>
    <news></news>
    <news></news>
    <news></news>
  </div>
</body>
<script src="js/vue.js"></script>

  <script>

    // 函数要声明
    // 组件要注册

    const news = {
      template: `
        <div>
          <h3>新闻</h3>
          <p>新闻内容</p>
        </div>
      `
    }
    // 全局注册 => 哪里都能用news组件
    Vue.component('news', news);

    new Vue({
      el: '#app',
      // 注册一个叫news的组件
      // 局部注册 => 只能在当前组件视图中使用.
      components: { news }
    })

  </script>

五、组件命名

<body>

  <div id='app'>
    <!-- 组件挂载时,大写都会变小写 -->
    <news-view></news-view>
    <news-view></news-view>
    <news-view></news-view>
  </div>
</body>
<script src="js/vue.js"></script>

  <script>

    // 函数要声明
    // 组件要注册

    const newsView = {
      template: `
        <div>
          <h3>新闻</h3>
          <p>新闻内容</p>
        </div>
      `
    }

    new Vue({
      el: '#app',
      // 组件名如果是驼峰命名,需要在引用组件时,添加-
      // components: { newsView }
      components: { "news-view": newsView }
    })

  </script>

六、组件的挂载

一个组件挂载了3次.挂载时可以用单标签,也可以用双标签.
挂载时,如果组件名是带驼峰的,你需要挂载的时候加
挂载的最终结果就是挂载的标签被组件的template指定的布局替换

<body>

  <div id='app'>
    <news-view></news-view>
    <news-view></news-view>
    <news-view></news-view>
  </div>
</body>
<script src="js/vue.js"></script>
  <script>

    // 函数要调用
    // 组件要挂载(组件的引用)

    const newsView = {
      template: `
        <div>
          <h3>今天的新闻</h3>
          <p>今天的新闻内容</p>
        </div>
      `
    }

    new Vue({
      el: '#app',
      components: { newsView }
    })

  </script>

七、组件的选项

一个组件挂载了3次.挂载时可以用单标签,也可以用双标签. 
挂载时,如果组件名是带驼峰的,你需要挂载的时候加- 
挂载的最终结果就是挂载的标签被组件的template指定的布局替换

<body>

  <div id='app'>
    
    <news-view></news-view>
    <news-view></news-view>
    <news-view></news-view>
  </div>
</body>

 newsView是组件的配置项.
template是组件的布局选项.(写组件的视图用的)
组件都是vue实例.可以写任意的Vue选项.除了el选项(例如data,methods,computed,filter,components...)

组件的选项和new Vue的选项区别:
1:不用el选项.(写了没意义).
2:data必须写成函数.把数据对象return出来.

<script src="js/vue.js"></script>

  <script>
 const newsView = {
      template: `
        <div>
          <h3 @click='fn'>{{title}}</h3>
          <p>今天的新闻内容</p>
        </div>
      `,
      data() {
        return {
          title: '今天的新闻'
        }
      },
      methods: {
        fn() {
          alert(this.title)
        }
      }
    }

    new Vue({
      el: '#app',
      components: { newsView },
    })

  </script>

八、组件的组件

<body>

  <div id='app'>
    <news-view></news-view>
    <news-view></news-view>
    <news-view></news-view>
  </div>
</body>

 组件都是vue实例,隐藏它也可以写components选项
在newsView中注册了box组件。
newsView就是box的父组件.
box组件就是newsView的子组件.
box组件和son组件是兄弟组件.

哪个组件的视图使用了数据,就在哪个组件内声明这个数据
哪个组件的视图挂载了其他组件A,就在哪个组件内声明这个A组件

<script src="js/vue.js"></script>

  <script>
 const box = {
      template: `<button>box组件的按钮</button>`
    }

    const son = {
      template: `<span>son组件</span>`
    }

    const newsView = {
      template: `
        <div>
          <h3 @click='fn'>{{title}}</h3>
          <p>今天的新闻内容</p>
          <box />
          <box />
          <box />
          <son />
        </div>
      `,
      data() {
        return {
          title: '今天的新闻'
        }
      },
      methods: {
        fn() {
          alert(this.title)
        }
      },
      components: { box, son }
    }

    new Vue({
      el: '#app',
      components: { newsView },
    })

  </script>

九、v-for和组件

body>

  <div id='app'>
    <news v-for='d in 3'></news>
    <div>
      <div>
        <section>
          <news v-for='d in 3'></news>
        </section>
      </div>
    </div>
    <footer>
      <news v-for='d in 3'></news>
    </footer>
  </div>
</body>

组件的template内必须有一个唯一的父元素包裹所有的布局.
如果组件的这个父元素需要v-for渲染.则应该把v-for写在组件挂载的地方.

<script src="js/vue.js"></script>

  <script>
    const news = {
      template: `
        <div>
          <h3 @click='fn'>{{title}}</h3>
          <p>今天的新闻内容</p>
        </div>
      `,
      data() {
        return {
          title: '今天新闻'
        }
      },
      methods: {
        fn() {
          alert(9090)
        }
      },
    }

    new Vue({
      el: '#app',
      components: { news }
    })

  </script>

十、父传子props

<body>

  <div id='app'>
    <news-view day='今天'></news-view>
    <news-view day='明天'></news-view>
    <news-view day='后天'></news-view>
  </div>
</body>

 组件数据
     1:data数据(一般数据)
     2:计算属性数据.
     3:props数据.(父传子数据)

<script src="js/vue.js"></script>

  <script>
    const newsView = {
      template: `
        <div>
          <h3>{{day}}新闻标题</h3>
          <p>{{day}}新闻内容</p>
        </div>
      `,
      // 声明一个props数据
      props: ['day']
    }

    new Vue({
      el: '#app',
      components: { newsView },
    })

  </script>

十一、根组件

template => 为了指定视图。
el => 为了挂载视图
组件可以写template选项.
new Vue时可以写吗?

new Vue时,如果没有写template选项,则vue会使用el所在的标签作为视图。

根组件. => 所有组件的唯一祖先组件。

 1.0

<!-- 挂载点 -->
  <span id='app'></span>

  <script src="js/vue.js"></script>

  <script>
    const App = {
      template: `
        <div id='app'>
          <h3>App根组件--{{day}}</h3>
        </div>
      `,
      data() {
        return {
          day: '今天'
        }
      }
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    });

  </script>
new Vue({
      el: '#app',
      template: `
        <div id='app'>
          <h3>App根组件--{{day}}</h3>
        </div>
      `,
      data: {
        day: '今天'
      }
    });

1.1

<body>
  
  <div id='app'></div>
</body>

完成以上计算总价的效果.
分别用计算属性和watch实现.

<script src="../js/vue.js"></script>
  <script>

    const App = {
      template: `
        <div id='app'>
          <input type="text" placeholder="单价" v-model='price'>
          <input type="text" placeholder="数量" v-model='count'>
          <div>总价:{{total}}</div>
        </div>
      `,
      data() {
        return  {
          price: 10,
          count: 1
        }
      },
      computed: {
        total() {
          return this.price * this.count
        }
      }
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })
  </script>

十二、props父传子

<body>

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

 1.0

<script src="js/vue.js"></script>

  <script>

    const newsView = {
      template: `
        <div>
          <h3>{{day}}的新闻标题</h3>
          <p>{{day}}的新闻内容</p>
        </div>
      `,
      // 声明一个props数据
      props: ['day']
    }

    const App = {
      template: `
        <div id='app'>
          <news-view day='今天'></news-view>
          <news-view day='明天'></news-view>
          <news-view day='后天'></news-view>
        </div>
      `,
      components: { newsView },
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })

  </script>

 1.1

如果props的数据在赋值时,希望通过一个变量来赋值,则需要加:(v-bind)
子组件数据 => day
父组件数据 => day1,day2,day3
子组件在挂载时,子组件数据被父组件数据赋值.(父传子)

父传子 => 让子组件复用时渲染了不同的内容(数据).
插槽 => 让子组件复用时,渲染不同的标签.

父传子 => 前子后父.

<script src="js/vue.js"></script>

  <script>

    const newsView = {
      template: `
        <div>
          <h3>{{day}}的新闻标题</h3>
          <p>{{day}}的新闻内容</p>
        </div>
      `,
      // 声明一个props数据
      props: ['day']
    }

    const App = {
      template: `
        <div id='app'>
          <news-view v-bind:day='day1'></news-view>
          <news-view :day='day2'></news-view>
          <news-view :day='day3'></news-view>
        </div>
      `,
      data() {
        return {
          day1: '今天',
          day2: '明天',
          day3: '后天',
        }
      },
      components: { newsView },
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })

  </script>

1.2

Vue => 单向数据流 => 从上往下的.(不能自下而上)
父组件数据变化 => 父组件视图更新 => :msg='msg'重新执行 => 新的msg的值传递给了子组件 => 子组件msg变化 => 子组件视图更新
    
在子组件中,是不能修改父组件传递的props数据.
但是可以操作应用类型的数据.
如果传递的是一个引用类型,则传递的是这个引用类型的引用.
我们不能在子组件中修改这个引用,但是可以修改这个引用背后的对象.
这样做修改的对象其实是父组件的对象,会导致父组件和子组件同时更新.

<script src="js/vue.js"></script>

  <script>
    const myComponent = {
      template: `
        <div>
          <h3>子组件msg---{{msg}}</h3>
          <h3>子组件obj---{{obj.name}}</h3>
          <button @click='fn'>按钮</button>
        </div>
      `,
      props: ['msg', 'obj'],
      methods: {
        fn() {

          // 可以通过this访问props数据.
          // console.log(this.msg)

          // 报错
          // this.msg = Math.random();

          // 不报错.
          // this.obj.name = '超越';

          // 报错.不能修改obj本身
          // this.obj = 10000;
        }
      }
    }

    const App = {
      template: `
        <div id='app'>
          <h3>App根组件msg--{{msg}}</h3>
          <h3>App根组件obj--{{obj.name}}</h3>
          <myComponent :msg='msg' :obj='obj' />
          <button @click='fn'>父按钮</button>
        </div>
      `,
      data() {
        return {
          msg: '父组件的数据msg',
          obj: { name: '幂幂' },
        }
      },
      methods: {
        fn() {
          this.msg = Math.random();
        }
      },
      components: { myComponent },
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })

  </script>

十三、子传父

<body>
  
  <div id='app'></div>
</body>

 1.0

子传父:
1:父组件需要一个方法来接收子组件数据.
2:子组件触发父组件的这个方法.并传入子组件数据.

子组件如何触发父组件的方法?
 1:把父组件的方法传递给子组件触发.(引用赋值传递)

<script src="js/vue.js"></script>

  <script>

    const myComponent = {
      template: `
        <div>
          <h3>子组件msg---{{msg}}</h3>
          <button @click='fn'>按钮</button>
        </div>
      `,
      props: ['getMsg'],
      data() {
        return {
          msg: '子组件的msg'
        }
      },
      methods: {
        fn() {
          // 调用父组件方法,并传递子组件的数据.
          this.getMsg(this.msg);
        }
      }
    }

    const App = {
      template: `
        <div id='app'>
          <h3>App根组件msg--{{msg}}</h3>
          <!--父组件方法传递给子组件-->
          <myComponent :getMsg='getMsg' />
        </div>
      `,
      data() {
        return {
          msg: '',
        }
      },
      methods: {
        // 父组件用于接收子组件的方法。
        getMsg(msg) {
          this.msg = msg;
        }
      },
      components: { myComponent },
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })

  </script>

1.2

子传父:
   1:父组件需要一个方法来接收子组件数据.
   2:子组件触发父组件的这个方法.并传入子组件数据.

子组件如何触发父组件的方法?
    1:把父组件的方法传递给子组件触发.(引用赋值传递)
    2:自定义事件实现.(给子组件绑定一个自定义事件,这个自定义事件触发时调用父组件的方法)

<script src="js/vue.js"></script>

  <script>
    const myComponent = {
      template: `
        <div>
          <h3>子组件msg---{{msg}}</h3>
          <button @click='fn'>按钮</button>
        </div>
      `,
      data() {
        return {
          msg: '子组件的msg'
        }
      },
      methods: {
        fn() {
          // $emit => 主动触发事件.
          // 第一个参数是事件名, 第二个参数是传递给事件句柄的参数
          this.$emit('myevent', this.msg);
        }
      }
    }

    const App = {
      template: `
        <div id='app'>
          <h3>App根组件msg--{{msg}}</h3>
          <!--给子组件绑定一个myevent自定义事件,这个自定义事件的事件句柄是getMsg-->
          <myComponent @myevent='getMsg' />
        </div>
      `,
      data() {
        return {
          msg: '',
        }
      },
      methods: {
        // 父组件用于接收子组件的方法。
        getMsg(msg) {
          this.msg = msg;
        }
      },
      components: { myComponent },
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })

  </script>

十四、如何在子组件修改父组件数据

<body>
  
  <div id='app'></div>
</body>

子组件修改父组件的数据
   1:把修改数据的逻辑方法写在父组件上.
   2:在子组件中触发父组件的方法.(子传父)

<script src="js/vue.js"></script>

  <script>
    const myComponent = {
      template: `
        <div>
          <h3>子组件msg---{{msg}}</h3>
          <button @click='show'>按钮</button>
        </div>
      `,
      props: ['fn', 'msg'],
      methods: {
        show() {
          this.fn(Math.random());
        }
      }
    }

    const App = {
      template: `
        <div id='app'>
          <h3>App根组件msg--{{msg}}</h3>
          <myComponent :fn='fn' :msg='msg' />
        </div>
      `,
      data() {
        return {
          msg: '父组件的数据msg',
        }
      },
      methods: {
        // 用fn修改父组件的msg数据 => 这样父子组件可以同时更新。
        // 只要让子组件能够触发父组件的这个fn.就可以实现子组件修改父组件的数据.
        fn(msg) {
          this.msg = msg
        }
      },
      components: { myComponent },
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })

  </script>

十五、如何子组件修改父组件数据

<body>
  
  <div id='app'></div>
</body>

子组件修改父组件的数据
   1:把修改数据的逻辑方法写在父组件上.
   2:在子组件中触发父组件的方法.(子传父) 

<script src="js/vue.js"></script>

  <script>   
    const myComponent = {
      template: `
        <div>
          <h3>子组件msg---{{msg}}</h3>
          <button @click='show'>按钮</button>
        </div>
      `,
      props: ['msg'],
      methods: {
        show() {
          this.$emit('myevent', Math.random())
        }
      }
    }

    const App = {
      template: `
        <div id='app'>
          <h3>App根组件msg--{{msg}}</h3>
          <myComponent @myevent='fn' :msg='msg' />
        </div>
      `,
      data() {
        return {
          msg: '父组件的数据msg',
        }
      },
      methods: {
        // 用fn修改父组件的msg数据 => 这样父子组件可以同时更新。
        // 只要让子组件能够触发父组件的这个fn.就可以实现子组件修改父组件的数据.
        fn(msg) {
          this.msg = msg
        }
      },
      components: { myComponent },
    }

    new Vue({
      el: '#app',
      template: `<App />`,
      components: { App }
    })

  </script>

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值